Подтвердить что ты не робот

Ruby: соглашение об именах атрибутов Boolean и использование

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

my_boolean_attribute?

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

class MyClass
  attr_accessor :my_boolean_attribute?

  def initialize
    :my_boolean_attribute? = false
  end
end

По-видимому, рубин ненавидит "?". Это конвенция? Что я делаю неправильно?

4b9b3361

Ответ 1

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

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

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

Мой ответ на исходный вопрос следует, для потомков...


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

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

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

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

def foo
  @foo
end

def foo=(newfoo)
  @foo = newfoo
end

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

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

class MyClass

  def initialize
    @awesome = true
  end

  def awesome?
    @awesome
  end

end

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

Ура!


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

  • Ruby применяет определенные соглашения об именах. Символы в Ruby не могут иметь вопросительные знаки. Таким образом, вызовы :my_boolean_attribute? будут терпеть неудачу с NameError. Изменить: не правильно, просто используйте цитированный синтаксис для символа, например :"my_attribute?"
  • Символы неизменяемы, попытка присваивания одному будет вызывать SyntaxError.

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

 # 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" или что-то подобное.

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

О, и почти забыл включить обязательную ссылку: Увидеть метаклассы четко