هل من الممكن أن يكون class.property = س عرض شيء آخر بخلاف العاشر؟
-
22-08-2019 - |
سؤال
ودعونا نقول لدي فئة روبي:
class MyClass
def self.property
return "someVal"
end
def self.property=(newVal)
# do something to set "property"
success = true
return success # success is a boolean
end
end
إذا كنت تحاول ان تفعل MyClass.property=x
، قيمة الإرجاع للبيان كله هو دائما س. وهي الاتفاقية في الكثير من / اللغات الملهمة لإرجاع منطقية قيمة "نجاح" C المستندة - هل من الممكن القيام بذلك لاضع باستخدام "يساوي جملة" في روبي
وعلاوة على ذلك - إذا لم يكن ذلك ممكنا، لماذا لا؟ هل هناك أي سلبيات يمكن تصوره إلى السماح ل"اضع يساوي" عملية بإرجاع قيمة؟
المحلول
واحد السلبي هو ان كنت كسر دلالات مهمة بالسلاسل:
$ irb
irb(main):001:0> x = y = 3
=> 3
irb(main):002:0> p x
3
=> nil
irb(main):003:0> p y
3
=> nil
irb(main):004:0>
والنظر فيما يلي:
x = MyClass.property = 3
وبعد ذلك x
سيستغرق true
إذا كان هذا العمل كما كنت قد توقعت (اليمين ترابطيات). يمكن أن تكون مفاجأة للأشخاص الذين يستخدمون واجهة وتستخدم لدلالات النموذجية.
وأنت أيضا حصلت لي التفكير حول تعيين بالتوازي مع ذلك، على سبيل المثال:
x, y = 1, 2
ويبدو أن قيمة الإرجاع من هذا التعبير هو تنفيذ محددة ... اعتقد انني لن يتم تسلسل المهام متوازيين:)
والسؤال لطيف!
نصائح أخرى
ومثل يقول مارتن، وهذا من شأنه كسر مهمة تسلسل.
والطريقة التي يتم بها تعريف طرق مهمة روبي للعمل توسع MyClass.property = 3
إلى ما يعادل (lambda { |v| MyClass.send('property=', v); v })[3]
(وليس حقا، ولكن هذا يظهر كيف يعمل تسلسل). قيمة الإرجاع المهمة هي دائما قيمة معينة.
إذا كنت تريد أن ترى نتيجة لطريقة MyClass#property=
الخاص بك، ثم استخدم #send
:
irb> o = Object.new
=> #<Object:0x15270>
irb> def o.x=(y)
irb> @x = y+1
irb> puts "y = #{y}, @x = #@x"
irb> true
irb> end
=> nil
irb> def o.x
irb> puts "@x = #@x"
irb> @x
irb> end
=> nil
irb> o.x = 4
y = 4, @x = 5
=> 4
irb> o.x
@x = 5
=> 5
irb> o.send('x=', 3)
y = 3, @x = 4
=> true
ومع ذلك، فإن الطريقة روبي للقيام بذلك هي مع بعض الاستثناءات - إذا حدث خطأ ما أثناء المهمة، رفع استثناء. ثم يجب على جميع invokers التعامل معها إذا سارت الامور خطأ، على عكس قيمة الإرجاع، والتي يمكن تجاهلها بسهولة:
# continued from above...
irb> def o.x=(y)
irb> unless y.respond_to? :> and (y > 0 rescue false)
irb> raise ArgumentError, 'new value must be > 0', caller
irb> end
irb> @x = y + 1
irb> puts "y = #{y}, @x = #@x"
irb> end
=> nil
irb> o.x = 4
y = 4, @x = 5
=> 4
irb> o.x = 0
ArgumentError: new value must be > 0
from (irb):12
from :0
irb> o.x = "3"
ArgumentError: new value must be > 0
from (irb):13
from :0
irb> o.x
@x = 5
=> 5
وأنا لست خبير روبي ولكن أقول لا لهذه الحالة أخشى. واضع الخاصية هي وحدها هناك لتعيين قيمة حقل الخاص، وليس لديك أي آثار جانبية مثل عودة رموز النتيجة.
إذا كنت تريد هذه الوظيفة ثم ينسى واضع والكتابة طريقة جديدة تسمى TrySetProperty
أو شيء من هذا الذي يحاول تعيين الخاصية وإرجاع منطقية.