1

我试图从 Ruby Koans 中理解一些东西。在一堂课中,我们制作了两个类,如下所示:

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)

所以这两个类和最后两个“断言”语句是我不清楚的。这两个类几乎相同,除了第二个类只是有另一个函数to_str调用to_s. 我不明白为什么第二个断言语句是真的(因此第二个类可以被视为一个字符串)仅仅是因为有第二个函数调用第一个函数。

4

2 回答 2

3

这里没有魔法。第二个测试是检查 to_str方法的存在。这不是为 定义的,CanNotBeTreatedAsString而是定义的CanBeTreatedAsString

的作用respond_to?是测试一个方法是否被定义,在Ruby 2.0中会进一步指出是否可以调用。无法调用的受保护方法将不再计算在内。现在,如果respond_to?(:method_name)返回,true那么send(:method_name)理论上任何必需的参数都可以工作。

第二个类可以用alias :to_str, :to_s更少的代码实现相同的结果。

于 2012-12-18T18:32:55.003 回答
2

本课的重点是说明被称为“鸭式打字”的原理。基本上,如果它长得像鸭子,叫起来像鸭子,那么它就是鸭子。在这种情况下,确定某事物是否为字符串(或者更确切地说像字符串)的唯一因素是它是否响应该to_str方法。

尝试在交互式 ruby​​ ( irb) 会话中运行此代码并试验这两个类。你会发现每个类的一个实例都会响应to_s但只会CanBeTreatedAsString响应to_str. 这意味着,就 Ruby 而言,CanBeTreatedAsString它与任何其他响应to_str.

于 2012-12-18T18:36:19.913 回答