set_my_name_var
モジュールにメソッドがある場合、これはモジュール変数を に設定していA
ます。インクルード クラスを介してメソッドが呼び出された場合、この動作は変わりません。これはまた、時々人々を捕まえる別の事実につながります -複数のクラスに含める場合、含まれるクラスごとに 1 つのインスタンスではなく、 のインスタンスが 1 つだけ存在します。次の例は、これを示しています。@@my_name = 'A'
A
A
@@my_name
module Example
def name=(name)
@@name = name
end
def name
@@name
end
end
class First
include Example
end
class Second
include Example
end
irb(main):066:0> f = First.new
=> #<First:0x2d4b80c>
irb(main):067:0> s = Second.new
=> #<Second:0x2d491d8>
irb(main):068:0> f.name = 'Set via f'
=> "Set via f"
irb(main):069:0> s.name
=> "Set via f"
アップデート
期待どおりに機能しないように見える理由を説明するために何が起こっているのかを理解したと思います。cattr_reader
(および拡張cattr_accessor
) には以下が含まれます。
class_eval(<<-EOS, __FILE__, __LINE__)
unless defined? @@#{sym} # unless defined? @@hair_colors
@@#{sym} = nil # @@hair_colors = nil
end
# code to define reader method follows...
次のシーケンスが行われます。
B
定義されています
- モジュール
A
が含まれています
included
コールバックが行いますklass.send(:cattr_accessor, :my_name)
。
- に設定されている
@@my_name
クラスにanが作成されます。B
nil
cattr_accessor
then after 呼び出しがなければ、その中でset_my_name_var
言うと、モジュールの変数を参照します。しかし、in place を使用すると、同じ名前の変数がクラスに存在するため、withinと言うと、 の変数よりも の変数の値が優先されます。これが私がマスキングした意味です。(の変数が の表示を妨げています)@@my_name
B
cattr_accessor
@@my_name
B
B
A
B
A
たぶん、以下が説明します。想像してみてくださいb = B.new
。次のことを行います。
>> A.class_variables
=> [] # No methods called on A yet so no module variables initialised
>> B.class_variables
=> ["@@my_other_name", "@@my_name"] # these exist and both set to nil by cattr_accessor
>> B.send(:class_variable_get, '@@my_name')
=> nil # B's @@my_name is set to nil
>> b.set_my_name_var # we call set_my_name_var as you did in the question
=> "A"
>> A.send(:class_variable_get, '@@my_name')
=> "A" # the variable in the module is to to 'A' as you expect
>> B.send(:class_variable_get, '@@my_name')
=> nil # but the variable in the class is set to nil
>> B.my_name
=> nil # B.my_name accessor has returned the variable from the class i.e. nil
セッターの前にゲッターを使用しようとすると、エラーcattr_reader
を回避するためにこれを行うと思います。uninitialized class variable
(クラス変数はnil
、インスタンス変数と同じようにデフォルトにはなりません。)