Rubyクラスインスタンスのものは私に頭痛の種を与えています。私はこれを考えると理解しています...
class Foo
@var = 'bar'
end
...それ @var
は、作成されたクラスのインスタンス上の変数です。
しかし、サブクラスのオーバーライド可能なクラス変数を作成するにはどうすればよいですか?
これが私がPythonで行うことの例です:
class Fish:
var = 'fish'
def v(self):
return self.var
class Trout(Fish):
var = 'trout'
class Salmon(Fish):
var = 'salmon'
print Trout().v()
print Salmon().v()
どの出力:
trout
salmon
ルビーで同じことをするにはどうすればよいですか?
@khelllの答えと対照的に、これはClassオブジェクトのインスタンス変数を使用します。
class Fish
# an instance variable of this Class object
@var = 'fish'
# the "getter"
def self.v
@var
end
# the "setter"
def self.v=(a_fish)
@var = a_fish
end
end
class Trout < Fish
self.v = 'trout'
end
class Salmon < Fish
self.v = 'salmon'
end
p Trout.v # => "trout"
p Salmon.v # => "salmon"
編集:クラスのインスタンス変数への読み取りアクセスをインスタンスに与えるには:
class Fish
def type_of_fish
self.class.v
end
end
p Trout.new.type_of_fish # => "trout"
p Salmon.new.type_of_fish # => "salmon"
@var
上記はクラスインスタンス変数と呼ばれ、インスタンス変数とは異なります。 -)...答えを読んでください ここ 差分を確認してください。
とにかくこれは同等のRubyコード:
class Fish
def initialize
@var = 'fish'
end
def v
@var
end
end
class Trout < Fish
def initialize
@var = 'trout'
end
end
class Salmon < Fish
def initialize
@var = 'salmon'
end
end
puts Trout.new.v
puts Salmon.new.v
これが、私がhobodaveのリンクを使用して考え出したバージョンです。
_class Fish
class << self
attr_accessor :var
end
@var = 'fish'
def v
self.class.var
end
end
class Trout < Fish
@var = 'trout'
end
class Salmon < Fish
@var = 'salmon'
end
puts (Trout.new).v # => trout
puts (Salmon.new).v # => salmon
_
サブクラス化には_@var
_の追加のみが必要であることに注意してください。初期化をオーバーライドする必要はありません。
これは、JavaコーダーがRubyにやってくるというよくある間違いであり、頭を悩ませなければならなかった大きな概念上のジャンプの1つです。最初は奇妙に思われるかもしれませんが、それは実際にRuby-のクールな側面の1つです-クラス定義を含むすべてのコードは実行可能です。
したがって、インスタンス変数はメソッド内で宣言する必要があります。それは「自己」がどのように評価されるかに関係しています。 「自己」は現在のオブジェクトです。インタプリタは、最初に「self」でメソッド呼び出しと変数参照を検索します。
class Fish
@var = "foo" # here 'self' == Fish, the constant which contains the class object
def foo
# do foo
end
end
fish = Fish.new
fish.foo # here 'self' == fish, an instance of Fish
クラス定義では、「self」が定義されているクラスオブジェクトに設定されているため、クラス定義内の参照はすべて、そのクラスオブジェクト(この場合はFish)を参照します。
ただし、Fishのインスタンスでメソッドが呼び出されると、selfは、Fishの特定のインスタンスである呼び出しの受信者として設定されます。したがって、メソッド定義の外では、selfはクラスオブジェクトです。メソッド内では、selfはレシーバーのインスタンスです。これが、メソッド定義の外の@varがJavaの静的変数に似ており、メソッド定義内の@varがインスタンス変数である理由です。
1つの問題があります:@varをオーバーライドできます:
Salmon.var = 'shark'は@varをオーバーライドするため、
プット(Salmon.new).v#=>サメ