Рубиновый материал экземпляра класса дает мне головную боль. Я понимаю, учитывая это...
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 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
Вот версия, которую я закончил, используя ссылку хободава:
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, а также один из крупных концептуальных прыжков, которые я должен был заставить голову. Сначала это кажется странным, но это действительно один из охладительных аспектов 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 внутри определения метода представляет собой переменную экземпляра.