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

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

my_boolean_attribute?

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

class MyClass
  attr_accessor :my_boolean_attribute?

  def initialize
    :my_boolean_attribute? = false
  end
end

Очевидно, Рубин ненавидит знак "?". Это конвенция? Что я делаю неправильно?


person Dane O'Connor    schedule 11.08.2009    source источник


Ответы (6)


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

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

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.
person Nick Zadrozny    schedule 11.08.2009
comment
Rubyist обычно не использует префикс is_ ни в именах переменных, ни в именах методов. Просто круто? вместо is_awesome? - person Simone Carletti; 12.08.2009
comment
Хорошая мысль, веппосы. Отредактировал 'is_', чтобы не запутать потомство ;-) - person Nick Zadrozny; 12.08.2009
comment
Из этого ответа я понимаю, что нет настоящего соглашения? : / - person Steven Jeuris; 28.04.2011
comment
Вы можете сделать :"my_boolean_attribute?" или даже :"my boolean attribute?" (хотя удачи в последнем звонке без send!) - person Andrew Grimm; 28.04.2011
comment
Это не просто синтаксический сахар, есть прирост производительности, как указано в stackoverflow.com/questions/5046831/ - person Andrew Grimm; 28.04.2011
comment
Чтобы быть педантичным в отношении вашего ответа на редактирование, символы могут иметь вопросительные знаки, а имена переменных (например, instance-var) - не могут. См. Ответ @Julik, чтобы узнать, что я считаю лучшим способом сделать это. - person Excalibur; 13.08.2014

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

class Foo
  attr_accessor :dead
  alias_method :dead?, :dead # will pick up the reader method
end 
person Julik    schedule 13.08.2009
comment
классно! Я делал это долго. - person Dane O'Connor; 13.08.2009
comment
Используя это, вы можете использовать как dead, так и dead?, верно? Но разрешает установку только через dead? - person Steven Jeuris; 28.04.2011
comment
Настройка остается через dead = - person Julik; 01.07.2012

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

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

person Platinum Azure    schedule 11.08.2009
comment
ty для символа защелки. self.my_boolean_attribute будет работать правильно? - person Dane O'Connor; 12.08.2009
comment
О, позвольте мне добавить - только в методах экземпляра. В области класса он будет искать переменную области класса (@@ my_boolean_attribute). Не то чтобы мне, конечно, нужно было вам говорить, но я хотел убедиться, что сказанное мной технически правильно. - person Platinum Azure; 12.08.2009

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

person sepp2k    schedule 11.08.2009
comment
хм, так что помощник attr_accessor не удаляет '?' с конца для меня да. Рад слышать, что это на самом деле не конвенция, например, vars. Думал, что схожу с ума. - person Dane O'Connor; 12.08.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» или что-то подобное.

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

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

person Andrew Y    schedule 11.08.2009
comment
+1 за ссылку! Вероятно, в этом случае не будет добавлен удобный метод, поскольку это не соглашение. Не хочу сбивать с толку других. Однако эти идеи, к счастью, будут уничтожены другими проблемами! - person Dane O'Connor; 12.08.2009
comment
Если вы поддерживаете его в команде, я думаю, что такие вопросы следует подробно обсуждать при проверках - в некоторых сценариях это может иметь смысл, в некоторых - нет. Я не занимался программированием Ruby в команде, поэтому я предпочитаю подход, который дает мне наименьшее внимание. - person Andrew Y; 12.08.2009

Я просмотрел ответы, и хотя принятый ответ верен, он вносит "лишний" шум в класс. Я предлагаю решить эту проблему следующим образом:

class Animal
  attr_writer :can_swim
  def initialize(animal_type_name)
    @can_swim = true
    @animal_type_name = animal_type_name
  end


  def can_swim?
    @can_swim
  end

  def to_s
    @animal_type_name
  end
end

dog = Animal.new('Dog in a bag')
dog.can_swim = false
puts "Can this #{dog} Swim? --- [#{dog_without_legs.can_swim? ? 'YEP!' : 'NOPE!'}]"
person Vlad    schedule 08.01.2020