سؤال

تعلم روبي. أنا تحت الانطباع بأنه يجب تسمية السمات المنطقية على النحو التالي:

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 - بعد كل شيء، قد يكون ذلك واضحا أنك تعمل مباشرة مع سمة منطقية. بشكل عام، أحفظ لاحقة المسألة من أجله عندما أقوم بتنفيذ طريقة تستند قيمة عودة المنطقية إلى ظروف أكثر تعقيدا قليلا من مجرد قيمة السمة.

هتافات!


تحرير، بعد عامين، بعد تعليق حديث:

  1. روبي يفرض بعض اتفاقيات التسمية. الرموز في روبي لا يمكن أن يكون لها علامات استفهام. وبالتالي دعوات :my_boolean_attribute? كلاهما سوف يفشل مع NameError. تحرير: غير صحيح، فقط استخدم بناء الجملة المقتبس للرمز، على سبيل المثال، :"my_attribute?"
  2. الرموز غير قابلة للتغيير، وحاول تعيين واحد سوف رمي 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 بوضوح

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top