Рубин:Соглашение об именовании и использовании логических атрибутов
-
13-09-2019 - |
Вопрос
Изучаю ruby.У меня сложилось впечатление, что логические атрибуты должны быть названы следующим образом:
my_boolean_attribute?
Однако я получаю синтаксические ошибки при попытке выполнить следующее:
class MyClass
attr_accessor :my_boolean_attribute?
def initialize
:my_boolean_attribute? = false
end
end
Очевидно, Руби ненавидит это "?".Это и есть конвенция?Что я делаю не так?
Решение
Редактировать:три года спустя;времена, они меняются…
Ответ Юлика это самый простой и лучший способ решить проблему на сегодняшний день:
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
— в конце концов, может быть очевидно, что вы работаете напрямую с логическим атрибутом.Обычно я сохраняю суффикс вопросительного знака, когда реализую метод, логическое возвращаемое значение которого основано на немного более сложных условиях, чем просто значение атрибута.
Ваше здоровье!
Редактировать, два года спустя, после недавнего комментария:
- Ruby применяет определенные соглашения об именах.
Символы в Ruby не могут иметь вопросительных знаков.Таким образом, вызовыРедактировать:неверно, просто используйте синтаксис в кавычках для символа, например,:my_boolean_attribute?
оба потерпят неудачу сNameError
.:"my_attribute?"
- Символы неизменяемы, попытка назначить один из них вызовет ошибку.
SyntaxError
.
Другие советы
Самый простой способ быстро добавить «метод вопроса» — использовать псевдоним для метода чтения.
class Foo
attr_accessor :dead
alias_method :dead?, :dead # will pick up the reader method
end
Тот Самый attr_accessor
символ подразумевает, что имя переменной равно @my_boolean_attribute
, так что это то, что вы должны устанавливать (не символ).
Кроме того, вы не можете использовать?для переменных используйте только имена методов.
?это соглашение для имен методов, а не переменных.Вы не можете использовать переменную экземпляра с именем @foo?
, однако вы можете использовать переменную с именем @foo
и назовите (созданный вручную) метод получения foo?
если бы ты захотел.
Метапрограммирование с исправлением обезьян - возможно, его можно сделать более элегантным, это всего лишь быстрый набросок, и я какое-то время не занимался метапрограммированием...
# 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"или что-то подобное.
Определения, которые я дал, немного странные, в том смысле, что в исходном символе присутствует вопросительный знак.Вероятно, более чистым подходом было бы избежать вопросительного знака в имени символа и добавить его во время определения метода - это должно вызвать меньшую путаницу.
Да, и чуть не забыл включить обязательную ссылку: Ясно видеть метаклассы