1

Ruby Koans から何かを理解しようとしています。1 つのレッスンで、次のように 2 つのクラスを作成します。

class CanNotBeTreatedAsString
  def to_s
    "non-string-like"
  end
end

not_like_a_string = CanNotBeTreatedAsString.new
not_like_a_string == "non-string-like"

class CanBeTreatedAsString
  def to_s
    "string-like"
  end

  def to_str
    to_s
  end
end

like_a_string = CanBeTreatedAsString.new
like_a_string.to_str == "string-like"

def acts_like_a_string?(string)
  string = string.to_str if string.respond_to?(:to_str)
  string.is_a?(String)
end

assert_equal false, acts_like_a_string?(CanNotBeTreatedAsString.new)
assert_equal true,  acts_like_a_string?(CanBeTreatedAsString.new)

したがって、2 つのクラスと最後の 2 つの "assert" ステートメントについては、よくわかりません。2 つのクラスはほぼ同じですが、2 番目のクラスにはto_strを呼び出す別の関数があるだけto_sです。最初の関数を呼び出す 2 番目の関数があるという理由だけで、2 番目の assert ステートメントが true である (したがって、2 番目のクラスを文字列として扱うことができる) 理由がわかりません。

4

2 に答える 2

3

ここには魔法はありません。2番目のテストは、 to_strメソッドの存在を確認することです。これはに対して定義されていませんCanNotBeTreatedAsStringが、に対して定義されていCanBeTreatedAsStringます。

の機能はrespond_to?、メソッドが定義されているかどうかをテストすることです。Ruby2.0では、メソッドを呼び出すことができるかどうかをさらに示します。呼び出すことができない保護されたメソッドは、カウントされなくなります。今のところ、respond_to?(:method_name)returnsのtrue場合send(:method_name)、必要な引数を指定すると理論的には機能します。

2番目のクラスはalias :to_str, :to_s、より少ないコードで同じ結果を達成するために使用できます。

于 2012-12-18T18:32:55.003 に答える
2

このレッスンのポイントは、「ダックタイピング」として知られる原則を説明することです。基本的に、アヒルのように見えてアヒルのように鳴くなら、それはアヒルです。この場合、何かが文字列であるかどうか (または文字列のように動作するかどうか) を決定する唯一の要因は、to_strメソッドに応答するかどうかです。

インタラクティブな ruby​​ ( irb) セッションでこのコードを実行し、2 つのクラスを試してみてください。各クラスのインスタンスは に応答しますto_sが、 にしかCanBeTreatedAsString応答しないことがわかりますto_str。つまり、Ruby に関する限り、CanBeTreatedAsStringに応答する他のものと同じくらい String ですto_str

于 2012-12-18T18:36:19.913 に答える