1

オブジェクトを介して呼び出されているときに、メソッドによって返される最後の式で遊んでいました。

以下の概念でコードが機能します。

class Simple
  def foo
    2 + 2
  end
end
#=> nil
simple = Simple.new
#=> #<Simple:0x11eb390>
simple.foo
#=> 4

しかし、なぜ以下のコードはとではなくそのようなエンコードされた値を返すの15です20か?

class Fixnum
  def to_s
    self + 5
  end
end
#=> nil
puts 10
#<Fixnum:0x000015>
#=> nil
puts 15
#<Fixnum:0x00001f>
#=> nil

誰かがここで私が概念を理解するのを手伝ってくれる?

編集:

class Fixnum
  def to_s
    self + 5
  end
end
#=> nil
10.to_s
#=> #<Fixnum:0x000029>

再び同じ結果。

4

2 に答える 2

3

の契約でto_sは、を返す必要がありますString。ただし、を返していFixnumます。契約に違反すると、あらゆる種類の奇妙なことが起こる可能性があります。

Stringメソッドからaを正しく返すとto_s、すべてが期待どおりに機能します。

class Fixnum
  def to_s
    "#{self + 5}"
  end
end

puts 10
# SystemStackError: stack level too deep

さて、「すべてが機能する」というのは少し誤解を招くかもしれません。しかし、ご覧のとおり、すべてが期待どおりに発生します。puts呼び出しto_sは、戻り10値に追加5され、次に呼び出し先、戻り値が追加され、次に呼び出します。1015to_s15520to_s20

class Fixnum
  orig_to_s = public_instance_method(:to_s)

  define_method(:to_s) do
    orig_to_s.bind(self + 5).()
  end
end

puts 10
# 15

これで、すべてが期待どおりに機能します

于 2013-02-27T15:07:39.027 に答える
0

自分自身に5を追加すると、別のFixnumを取得します。

結果を表示しないようにto_sを変更したFixnumを印刷すると、fixnumの値の代わりに結果のオブジェクトが表示されるようになりました。

于 2013-02-27T14:47:35.007 に答える