'String#reverse' 如何返回非 'String' 对象?

How can 'String#reverse' return non-'String' objects?

提问人:Tony Marshle 提问时间:11/15/2017 最后编辑:sawaTony Marshle 更新时间:11/15/2017 访问量:71

问:

我有一个班级:Word

class Word < String
end

w = Word.new("level")
y = w.reverse
y.class # => Word

1) 这怎么可能? 应该返回 ,因为它继承了 ,它返回一个 .Word#reverseStringString#reverseString

我添加了以下代码:

class Word < String
  attr_accessor :s

  def magic
    @s = Time.now
  end
end

y.magic
sleep(5)
w.magic
y.s == w # => false
y == w # => true

2) 和 是 和 相等,因此它们都具有相同的方法,例如 。从哪里获得该方法?wyWordmagicymagic

3) 为什么计算到 while 并返回不相等的值?y == wtruey.sw.s

Ruby Equality 返回类型

评论

0赞 sawa 11/15/2017
我不确定你的第二个问题是什么意思。

答:

7赞 Simple Lime 11/15/2017 #1

虽然 String#reverse 的文档指出:

返回一个新字符串,其中包含 str 中的字符,顺序相反。

因此,您可能期望返回类型为 ,如果您弹出该方法,您可以看到以下行String

rev = rb_str_new_with_class(str, 0, RSTRING_LEN(str));

这就是实际得到的回报。我的 C 相当生疏,但是环顾 ruby 的 C 代码,该方法似乎完全按照它所说的去做,它创建了任何类的新实例,在这种情况下。因此,当文档说它返回一个新字符串时,它的意思是它返回该字符串的任何类的新实例,在大多数情况下是 .revrb_str_new_with_classstrWordString

因此,知道它创建了当前字符串的任何类的新实例,很容易看出最终如何拥有一个方法......因为给了它方法,而且它是一个.w.reversemagicWordWord

最后,它们如何相等?您没有在 上定义一个新方法,因此它采用父 String#== 方法,该方法不知道或不关心是否存在实例变量,只是比较字符串的值,在必要时强制使用,您甚至可以执行以下操作:==Wordto_str

Word.new("level") == "level" # => true

(注意:我实际上不确定是否被胁迫。Word