روبي: مؤتمر تسمية سمة Boolean واستخدامها
-
13-09-2019 - |
سؤال
تعلم روبي. أنا تحت الانطباع بأنه يجب تسمية السمات المنطقية على النحو التالي:
my_boolean_attribute?
ومع ذلك، أحصل على أخطاء بناء الجملة عند محاولة القيام بما يلي:
class MyClass
attr_accessor :my_boolean_attribute?
def initialize
:my_boolean_attribute? = false
end
end
على ما يبدو روبي يكره "؟". هل هذه الاتفاقية؟ ما الخطأ الذي افعله؟
المحلول
تحرير: بعد ثلاث سنوات؛ الأوقات، هم A-Changin '...
إجابة جوليك هي أبسط وأفضل طريقة لمعالجة المشكلة هذه الأيام:
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
- بعد كل شيء، قد يكون ذلك واضحا أنك تعمل مباشرة مع سمة منطقية. بشكل عام، أحفظ لاحقة المسألة من أجله عندما أقوم بتنفيذ طريقة تستند قيمة عودة المنطقية إلى ظروف أكثر تعقيدا قليلا من مجرد قيمة السمة.
هتافات!
تحرير، بعد عامين، بعد تعليق حديث:
- روبي يفرض بعض اتفاقيات التسمية.
الرموز في روبي لا يمكن أن يكون لها علامات استفهام. وبالتالي دعواتتحرير: غير صحيح، فقط استخدم بناء الجملة المقتبس للرمز، على سبيل المثال،: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
واسم طريقة Getter (التي تم إنشاؤها يدويا) foo?
أذا كنت ترغب ب.
Metaprogramming Metaprogramming قرد - ربما يمكن أن يكون أكثر أناقة، وهذا مجرد مسودة سريعة، وأنا لم أفعل metaprogramming لفترة قصيرة ...
# 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." أو شيئا من هذا القبيل.
التعاريف التي قمت بها هي غريب الأطوار قليلا، بمعنى أن علامة الاستفهام موجودة في الرمز الأصلي. ربما يكون نهج نظافة هو تجنب المشاركة في اسم الرمز وإلحاقه أثناء تعريف الطريقة - يجب أن يكون أقل مربكة.
أوه، ونسيت تقريبا أن تشمل الرابط الإلزامي: رؤية metaclasses بوضوح