Ruby: логическое соглашение об именах атрибутов и их использование - PullRequest
31 голосов
/ 12 августа 2009

Изучение рубина. У меня сложилось впечатление, что логические атрибуты должны называться следующим образом:

my_boolean_attribute?

Однако я получаю синтаксические ошибки при попытке сделать следующее:

class MyClass
  attr_accessor :my_boolean_attribute?

  def initialize
    :my_boolean_attribute? = false
  end
end

Видимо, рубин ненавидит "?" Это конвенция? Что я делаю не так?

Ответы [ 5 ]

42 голосов
/ 12 августа 2009

Редактировать: три года спустя; времена, они меняются ...

Ответ Джулика - это самый простой и лучший способ решения проблемы в наши дни:

class Foo
  attr_accessor :dead
  alias_method :dead?, :dead # will pick up the reader method
end

Далее следует мой ответ на оригинальный вопрос для потомков…


Краткая версия:

Нельзя использовать вопросительный знак в имени переменной экземпляра.

Более длинная версия:

Взять, к примеру, attr_accessor :foo - это просто концептуально немного синтаксического сахара для следующего:

def foo
  @foo
end

def foo=(newfoo)
  @foo = newfoo
end

Кроме того, суффикс вопросительного знака - это в основном просто соглашение, указывающее, что возвращаемое значение метода является логическим.

Лучшее приближение, которое я могу сделать для того, что вы собираетесь здесь ...

class MyClass

  def initialize
    @awesome = true
  end

  def awesome?
    @awesome
  end

end

В этом случае может быть необходимость использовать attr_accessor - в конце концов, это может быть явно, что вы работаете напрямую с логическим атрибутом. Обычно я сохраняю суффикс вопросительного знака, когда я реализую метод, логическое возвращаемое значение которого основано на несколько более сложных условиях, чем просто значение атрибута.

Ура!


Редактировать, два года спустя, после недавнего комментария:

  1. Ruby применяет определенные соглашения об именах. Символы в Ruby не могут иметь вопросительные знаки. Таким образом, вызовы :my_boolean_attribute? оба завершатся неудачно с NameError. Редактировать: не правильно, просто используйте синтаксис в кавычках для символа, например, :"my_attribute?"
  2. Символы неизменны, при попытке присвоить одному из них выбрасывается SyntaxError.
39 голосов
/ 13 августа 2009

Самый простой способ быстро добавить «метод вопроса» - использовать псевдоним для вашего метода чтения

class Foo
  attr_accessor :dead
  alias_method :dead?, :dead # will pick up the reader method
end 
6 голосов
/ 12 августа 2009

Символ attr_accessor означает, что имя переменной - @my_boolean_attribute, так что это то, что вы должны установить (не символ).

Кроме того, вы не можете использовать? для переменных просто имена методов.

5 голосов
/ 12 августа 2009

? это соглашение для имен методов, а не переменных. Вы не можете использовать переменную экземпляра с именем @foo?, однако вы можете использовать переменную с именем @foo и назвать (вручную созданный) метод получения foo?, если хотите.

3 голосов
/ 12 августа 2009

Метапрограммирование исправления обезьян - возможно, его можно сделать более элегантным, это всего лишь быстрый набросок, и я еще некоторое время не занимался метапрограммированием ...

 # inject the convenience method into the definition of the Object class
 class Object
   def Object::bool_attr(attrname)
     class_eval { define_method(attrname.to_s,
          lambda { instance_variable_get('@' + attrname.to_s.chop) }) }
     class_eval { define_method(attrname.to_s.chop+"=",
          lambda { |x| instance_variable_set('@'+attrname.to_s.chop, x) }) }
   end
 end

 ### somewhere later

 class MyClass

   bool_attr :my_boolean_attribute?

   def initialize
     @my_boolean_attribute = true
   end
 end

 # yet even more later

 foo = MyClass.new
 bar = MyClass.new

 foo.my_boolean_attribute = 1
 puts foo.my_boolean_attribute?
 puts bar.my_boolean_attribute?

При таком подходе вы можете быть СУХИМ и получить приятный вопросительный знак. Вам просто может понадобиться выбрать более подходящее имя, чем " bool_attr ", например, " bool_attr_accessor " или что-то подобное.

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

Да, и почти забыл включить обязательную ссылку: Четкое отображение метаклассов

...