Какова цель attr_accessor при создании объектов в Ruby?

Прежде чем я расширим свой вопрос, позвольте мне сказать, что я прочитал ответы на вопросы здесь, здесь и здесь. Поэтому просьба не отмечать мой вопрос как дубликат, поскольку эти ответы не заставили меня понять цель attr_accessor. Мой вопрос больше связан с логикой, а не с синтаксисом.

Я создал два набора кода ниже. Наборы идентичны друг другу, за исключением того, что в одном наборе просто нет строки attr_accessor. Когда я запустил оба набора, они оба дали мне одинаковый результат. Итак, с логической точки зрения, какая разница в строке attr_accessor, когда оба набора кода дали мне один и тот же предполагаемый результат?

Набор кодов 1:

class Animal 

   def initialize(name)
      @name = name
   end
end
class Cat < Animal
   def talk
     "Meaow!"
   end
end
class Dog < Animal
   def talk
     "Woof!"
   end
end

animals = [Cat.new("Flossie"), Dog.new("Clive"), Cat.new("Max")]
animals.each do |animal|
    puts animal.talk
end
#Output:
#Meaow!
#Woof!
#Meaow!

Набор кодов 2:

class Animal

attr_accessor :name  #this line is the only difference between the two code sets.

   def initialize(name)
      @name = name
   end
end
class Cat < Animal
   def talk
     "Meaow!"
   end
end
class Dog < Animal
   def talk
     "Woof!"
   end
end

animals = [Cat.new("Flossie"), Dog.new("Clive"), Cat.new("Max")]
animals.each do |animal|
    puts animal.talk
end
#Output:
#Meaow!
#Woof!
#Meaow!

Оба набора кода вызывают класс Animal для создания новых экземпляров объектов животных с именами. Я подчеркиваю "... С именами". потому что attr_accessor (во 2-м наборе) определяет атрибут :name. Но в 1-м наборе кодов я удалил attr_accessor, но все же смог создать экземпляры объекта с атрибутом имени.


person Community    schedule 21.08.2013    source источник


Ответы (2)


Переменные экземпляра всегда можно читать/записывать внутри методов экземпляра, что демонстрирует ваш код. attr_accessor делает переменные экземпляра доступными для чтения/записи вне класса (путем определения методов доступа). Добавив его во второй пример, вы разрешаете следующее:

cat = Cat.new("Garfield")
puts cat.name
cat.name = "Maru"

что поднимет NoMethodError в вашем первом примере.

person Max    schedule 21.08.2013
comment
Спасибо Макс, это именно то объяснение, которое мне было нужно! - person ; 21.08.2013

attr_accessor :attribute_name является сокращением для:

def attribute_name
  @attribute_name
end

def attribute_name=(value)
  @attribute_name = value
end

и это для установки переменной экземпляра. В вашем коде вы устанавливаете переменную экземпляра непосредственно в методе initialize, поэтому вам не нужен attr_accessor.

person Marek Lipka    schedule 21.08.2013
comment
Вам по-прежнему может понадобиться attr_accessor, если вы хотите снова назначить (или изменить) переменную attribute_name через вызов метода. - person vgoff; 21.08.2013