クラスインスタンス変数・Rubyの特異メソッド・モジュールについて
クラス変数と似ているが、クラス変数のように継承しているサブクラスからアクセスすることができない。
これによって、どこから読み込まれたり書き込まれたりとかが把握しやすくなる(アクセス元は必ず同じクラス)
code:rb
# ----- code 1 -----
class Foo
# クラス読み込み時にクラスインスタンス変数を設定する
@foo = 'デフォルトのクラスインスタンス変数'
def self.settings
{ foo: @foo }
end
# メソッド呼び出し時にクラスインスタンス変数を更新する
def self.update_settings
@foo = '更新されたクラスインスタンス変数'
end
end
class Bar < Foo
end
# Fooの中で@fooを取得、更新できる
puts Foo.settings
Foo.update_settings
puts Foo.settings
# Barからは@fooにアクセスできない
puts Bar.settings
特異メソッドについて
ある特定のオブジェクトのみに定義されたオブジェクト固有のメソッド
code:rb
hello = 'hello'
def hello.say
p 'say hello'
end
hello.say
このようにhello変数のStringクラスにsayメソッドを定義することができる。
これを考えた時、Rubyのクラスもオブジェクトと考えて良い。
上記のような特異メソッドの定義がオブジェクトにできるなら、クラスにも特異メソッドが定義できる。
実質以下はPaymentクラスに特異メソッドを定義してるのと同じである。
selfとしているが、Paymentとしても問題ない
code:rb
class Payment
def self.total_amount(amount)
amount + 500
end
end
class Payment
def Payment.total_amount(amount) # これでもいい
amount + 500
end
end
特異メソッドは、singleton_methodsで呼び出せる
特異クラスについて
code:rb
class << インスタンス
end
特異クラス定義式と呼ばれる。
クラスメソッドの追加は、クラス自体は元クラスメソッドのインスタンスという考え方もできる
code:rb
class Hello
class << self
def say
puts 'hello world'
end
end
end
こうもかける
code:rb
class Hello
end
class << Hello
def say
puts 'hello world'
end
end
モジュールの扱いについて
モジュールはインスタンス化できない。
その代わりクラスにincludeして利用することができるようになる
モジュール呼び出しで利用するなら、以下のように特異メソッドにする必要がある
code:rb
module Payment
FEE = 500
class << self
def total_amount(amount)
amount + FEE
end
end
end
p Payment::FEE
p Payment.total_amount(500)
インスタンスメソッドとして追加する場合は、includeする必要がある
code:rb
module Payable
FEE = 500
def initialize(amount:)
@amount = amount
end
def total_amount
@amount + FEE
end
end
class Payment
include Payable
end
payment = Payment.new(amount: 1000)
puts payment.total_amount
Payment.ancestorsで依存関係を知ることができる
クラスメソッドとする場合は、extendする