我的假设是否正确,即 Ruby 在字符串插值期间解释
to_s
对象时不会调用 to_str
或 String
方法?
a = "Hallo"
class String
def to_s
"Servus"
end
end
def a.to_s
"Servus"
end
puts "Hier sagt man #{a}"
=> 你好,你好
检查对象是否为
String
是否比简单地调用 to_s
方法更有效?
我的假设是否正确,即 Ruby 在字符串插值期间解释
对象时不会调用to_s
或to_str
方法?String
这是正确的。
您提供的测试并不排除解析器通过识别
a
被分配给字符串文字而走捷径的可能性。这是一个测试:
a = "Hallo"
class String
def to_s
"Servus"
end
end
def a.to_s
"Servus"
end
test_string = 'puts "Hier sagt man #{' + 97.chr + '}'
eval(test_string) # => Hier sagt man Hallo
现在,Ruby 实际上并不做任何类型的“局部变量是文字字符串”自动替换,因为 Ruby 是如此动态,以至于可以在以下任何代码行中更新
a
的值,而无需解析器知道。但如果您还不知道确实是这种情况,像上面这样的测试可以保证这一点。
检查对象是否为
是否比简单地调用String
方法更有效?to_s
这是另一个有趣的测试,它表明 Ruby(至少是 C Ruby)没有使用某种秘密快捷方式来检查它是否恰好是
String
,而是使用更像 is_a?
的东西:
class Foo < String
def to_s
"foo"
end
def to_str
"foo"
end
end
a = Foo.new("initial value")
puts "a: #{a}"
#=> a: initial value
如果我们看到
a: foo
,我们就会知道使用了非常简单(并且可能更有效)的检查,并且无法识别 Foo
对象是 String
子类的实例。
鉴于上述情况,我们排除了
String
的测试是针对 String
类进行优化的简单测试的可能性。无需检查每个 Ruby 实现中的代码,我们就可以确定一些事情:
is_a?
方法即可识别对象是否为 String
子类的实例。is_a?
进行方法查找,因为它可以对任何对象类型使用 rb_obj_is_kind_of
。to_s
和 to_str
至少涉及 1 或 2 个方法查找。实际上调用它们包括未知的额外数量的方法查找和额外调用。考虑到这些事情,我们可以说,检查对象是否为 String
与调用
to_s
或 to_str
至少一样高效,而且平均而言,它可能更高效。