class Dog
def initialize
puts "self in Dog#initialize = #{self}"
@breed = []
end
def show
puts "#{@first_name} of breed #{@breed}"
end
end
class Lab < Dog
attr_reader :first_name, :i
def initialize
super
@first_name = "good dog"
@i = 1
end
def add
@breed << @i
@i += 1
end
end
Давайте создадим экземпляр Lab
и рассмотрим его переменные экземпляра:
sue = Lab.new
#=> #<Lab:0x000059195710eec8 @breed=[], @first_name="good dog", @i=1>
# displays: self in Dog#initialize = #<Lab:0x000059195710eec8>
sue.instance_variables
#=> [:@breed, :@first_name, :@i]
sue.first_name"
#=> "good dog"
sue.i
#=> 1
sue.instance_variable_get(:@breed)
#=> []
Обратите внимание, что мне пришлось использовать Object # instance_variable_get , чтобы получить значение переменной экземпляра sue
@breed
, поскольку для этой переменной экземпляра не было создано средство получения.
Вы говорите, что wi sh to "update переменная родительского класса из дочернего класса ". Во-первых, родительский класс Dog
не имеет переменных класса или переменных экземпляра (иногда их называют переменные экземпляра класса ). Я предполагаю, что вы имеете в виду переменную экземпляра @breed
, связанную с каждым экземпляром Dog
. На самом деле, похоже, что вряд ли кто-то создаст экземпляр Dog
; что Dog
было создано только для определения методов и переменных экземпляра, которые должны использоваться подклассами Dog
. Тем не менее, давайте создадим экземпляр Dog
:
bob = Dog.new
#=> #<Dog:0x0000591956ffd4a8 @breed=[]>
# displays: self in Dog#initialize = #<Dog:0x0000591956ffd4a8>
bob.instance_variables
#=> [:@breed]
bob.instance_variable_get(:@breed)
#=> []
Давайте также изменим значение @breed
для этого экземпляра:
bob.instance_variable_get(:@breed) << "pug"
#=> ["pug"]
Теперь давайте добавим метод get_iv
Lab
, чтобы получить значение переменной экземпляра @breed
экземпляра Dog
. Подумайте об информации, которая должна быть передана этому методу. Нужно знать, какой экземпляр Dog
нас интересует (поскольку разные экземпляры могут очень хорошо иметь разные значения для своих переменных экземпляра), а для этого экземпляра - какая переменная экземпляра нас интересует. (Здесь есть только один, но давайте сделаем так, чтобы мы могли добавлять переменные экземпляра к экземплярам Dog
.
class Lab
def get_iv(instance, instance_variable)
instance.public_send(:instance_variable_get, instance_variable)
end
end
См. Object # public_send . Теперь мы можем написать:
sue.get_iv(bob, :@breed)
#=> ["pug"]
sue.get_iv(bob, :@breed) << "collie"
#=> ["pug", "collie"]
Конечно же, мы выполнили задачу:
bob.instance_variable_get(:@breed)
#=> ["pug", "collie"]
Но подождите! Теперь давайте создадим совершенно не связанный класс и его экземпляр.
class Bird
def initialize
@type = ["canary"]
end
end
tweetie = Bird.new
#=> #<Bird:0x0000591956ffee98 @type=["canary"]>
Далее, давайте sue
получим и изменим значение * Переменная экземпляра 1059 * @type
:
sue.get_iv(tweetie, :@type)
#=> ["canary"]
sue.get_iv(tweetie, :@type) << "robin"
#=> ["canary", "robin"]
и подтверждение того, что они были изменены:
tweetie.instance_variable_get(:@breed)
#=> ["canary", "robin"]
Дело в том, что метод экземпляра мы должны добавить к Lab
требуется две части информации:
- экземпляр, значение переменной экземпляра которого необходимо получить; и
- имя переменной экземпляра.
Это не имеет ничего общего с тем фактом, что Lab
является подклассом Dog
! Следовательно, получение или установка значения переменной экземпляра экземпляра суперкласса Lab
ничем не отличается от получения или установки значения переменной экземпляра любого другого класса .