Переменные класса 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

Как я делаю то же самое в рубине?

22
задан docwhat 18 January 2010 в 07:31
поделиться

4 ответа

Чтобы контрастировать ответ @ Khelll, это использует переменные экземпляра на объектах класса:

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"
21
ответ дан 29 November 2019 в 05:00
поделиться

@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
8
ответ дан 29 November 2019 в 05:00
поделиться

Вот версия, которую я закончил, используя ссылку хободава:

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 -- нет необходимости переопределять инициализацию.

4
ответ дан 29 November 2019 в 05:00
поделиться

Это распространенная ошибка, сделанная Java Кодеры, приезжающие в Ruby, а также один из крупных концептуальных прыжков, которые я должен был заставить голову. Сначала это кажется странным, но это действительно один из охладительных аспектов RUBY - все код выполняется исполняемым, включая определения классов.

Итак, переменные экземпляра должны быть объявлены внутри методов. Это связано с тем, как оценивается «я». «Я» - это текущий объект. Переводчик будет найти метод вызовов и переменных ссылок в первую очередь в «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» устанавливается, чтобы быть определенным объектом класса, поэтому любые ссылки в определении класса будут ссылаться на этот класс объекта, В этом случае рыба.

Когда метод вызывается на экземпляре рыбы, однако, я должен быть приемником вызова, конкретный экземпляр рыбы. Поэтому за пределами определения метода SEA - это объект класса. Внутри метода я является экземпляром приемника. Вот почему @var вне определения метода больше похоже на статическую переменную в Java, и @var внутри определения метода представляет собой переменную экземпляра.

2
ответ дан 29 November 2019 в 05:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: