22

ルビーのクラスインスタンスのものは私に頭痛の種を与えています。私はこれを考えると理解しています...

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

ルビーで同じことをするにはどうすればよいですか?

4

5 に答える 5

21

@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"
于 2010-01-18T14:49:54.210 に答える
8

@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
于 2010-01-18T08:21:51.080 に答える
4

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-- の追加のみが必要であることに注意してください。初期化をオーバーライドする必要はありません。

于 2010-01-18T16:57:02.887 に答える
2

これは、Ruby に移行する Java コーダーが犯すよくある間違いであり、頭を悩ませなければならなかった概念上の大きなジャンプの 1 つです。最初は奇妙に思えますが、これは Ruby の優れた点の 1 つです。クラス定義を含め、すべてのコードが実行可能です。

したがって、インスタンス変数はメソッド内で宣言する必要があります。それは「自己」がどのように評価されるかに関係しています。「self」は現在のオブジェクトです。インタープリターは、最初に「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 がインスタンス変数である理由です。

于 2010-01-18T14:57:14.180 に答える
1

問題が 1 つあります。@var をオーバーライドできます:
Salmon.var = 'shark' は @var をオーバーライドするため、
puts (Salmon.new).v # => shark

于 2012-09-14T17:57:24.393 に答える