Вызов переменной экземпляра в виртуальном атрибуте с помощью Ruby

Итак, я только начинаю изучать The Pragmatic Bookself, "Programming Ruby 1.9 ( 3-е издание)", и я наткнулся на код, который мне нужно немного пояснить.

Если у вас есть книга, она находится в главе 3 «Классы, объекты и переменные», особенно в разделе о виртуальных атрибутах.

По сути, класс определяется с помощью инициализатора, который устанавливает пару переменных экземпляра, одна из которых — @price. Эта переменная имеет аксессор/мутатор, созданный с помощью attr_accessor, например:

attr_accessor :price

Этот класс также имеет виртуальный атрибут с именем price_in_cents, который просто возвращает значение из этой строки:

Integer(price*100 + 0.5)

Теперь мой вопрос: почему price в виртуальном атрибуте не имеет префикса @? Это явно имеет дело с переменной экземпляра. Выполнение кода без @ работает так же, как и с; это почему?

P.S. Извините, что не публикую код оптом — учитывая, что это вопрос о коде в книге, я не был уверен, какое законное право я имел бы на публикацию.


person Jean-Charles    schedule 31.01.2011    source источник


Ответы (3)


Это отправка сообщения без получателя.

В Ruby получатель self является неявным: вы можете не указывать его, если хотите. Итак, price в основном то же самое, что и self.price (без учета ограничений доступа).

Другими словами, он вызывает метод price, который вы определили с помощью attr_accessor.

person Jörg W Mittag    schedule 31.01.2011
comment
Таким образом, это делается только для того, чтобы обеспечить доступ к переменной price через предоставленный классом метод доступа (в случае, если он не просто возвращает @price)? - person Jean-Charles; 31.01.2011
comment
@Жан-Шарль: Ага. По сути, это фундаментальный принцип объектной ориентации: все является отправкой сообщения. Доступ к переменной не является отправкой сообщения, поэтому он не является объектно-ориентированным, и его следует по возможности избегать. Это дает вам независимость от представления: метод price_in_cents совершенно не знает, как представлены цены, что позволяет вам изменять представление (например, извлекать его из базы данных вместо переменной экземпляра) без изменения кода. . - person Jörg W Mittag; 31.01.2011

Вы можете легко убедиться, что две ссылки (price и @price) указывают на одни и те же объекты:

#!/usr/bin/env ruby

class MyPrice < Object
  attr_accessor :price

  def initialize(price = 0)
    @price = price
  end

  def price_in_cents
    Integer(price * 100 + 0.5)
  end

  def objects
    puts "@price.object_id: #{@price.object_id}"
    puts "price.object_id:  #{price.object_id}"
  end
end

p = MyPrice.new(150)
p.objects
puts "price in cents: #{p.price_in_cents}"

Что производит:

# ./price.rb 
@price.object_id: 301
price.object_id:  301
price in cents: 15000

Тот факт, что price и @price имеют идентификатор объекта 301, показывает, что они оба являются ссылками на один объект.

person sflinter    schedule 31.01.2011
comment
За исключением того, что price не является ссылкой на объект, это отправляемое сообщение. - person Jörg W Mittag; 31.01.2011

Этот вопрос был опубликован много лет назад, но на всякий случай у кого-то возникнут похожие проблемы, как в примере сверху.

Я не думаю, что self.price имеет какое-либо отношение к attr_accessor, self.price применяется только к классу, где attr_accessor становится ярлыком для переменной экземпляра. Вам не нужно вводить '@' перед attr_accessor, потому что он действует как ярлык для ваших сеттеров и геттеров, если вы знакомы с Java. Часть легкого способа Ruby делать вещи быстрее и красноречивее.

person Ahmad    schedule 12.07.2014