2009-04-02 6 views
12

のは、私はRubyのクラスがあるとしましょう:私がしようとするとMyClass.property=xを行う場合class.property = xにx以外の何かを返すことは可能ですか?

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 

を、全体の文の戻り値は、x常にあります。ブール値の「成功」値を返すことは、Cベースの/インスピレーションされた多くの言語で行われています。これは、Rubyで "equals syntax"を使用するセッターで可能ですか?

さらに、これが不可能な場合、どうしてですか? "equals setter"演算が値を返すことを許容することには考えられる欠点はありますか?

答えて

11

一つの欠点は、あなたが連鎖割り当てのセマンティクスを破るだろうということです。

$ 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 

を、これはあなたが(右結合性)を期待していたとして働いていた場合、xtrueを取るだろう。これは、あなたのインターフェースを使用している人々にとっては驚きであり、典型的なセマンティクスに慣れています。

また、私は例えば、並列割り当てについて考えてしまった:

x, y = 1, 2 

はどうやらその式の戻り値は、私はパラレル割り当てをチェーン化されることはありません推測... implementation specificです:)

ニースの質問!

+0

私が最初にこれを読んで"襲撃の答えが明らかになるので、そうではありません。譲渡方法の戻り値は通常無視されます。マーティンが言っていることは、「言語はあなたがそれをするのを許さず、もしそうであれば、あなたは連鎖された代入セマンティクスを破るだろう」ということです。 –

5

私はRubyのエキスパートではありませんが、私は恐れている場合はいいと言います。プロパティセッターは、結果フィールドを返すような副作用がないようにプライベートフィールドの値を設定するだけです。

この機能を使用するには、セッターを忘れて、TrySetPropertyなどの新しいメソッドを作成してプロパティを設定し、ブール値を返します。

7

マーティンさんのように、これは割り当ての連鎖を壊すでしょう。

ruby​​の割り当て方法を定義する方法は、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 

ただし、これを行うにはルビーの方法は例外である - 何かが 割り当て中に問題が発生した場合には、調達します例外。何かが うまくいかない場合は、すべての呼び出し側は、それを処理する必要があり、簡単に無視することができ、戻り値とは異なり:あなたがそのようなアクセサを定義した場合」、あなたはチェーンの割り当てのセマンティクスを破るよう

# 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 
関連する問題