Ruby 如何对 String 对象进行 String 插值?

问题描述 投票:0回答:1

我的假设是否正确,即 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 string interpolation
1个回答
0
投票

我的假设是否正确,即 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 实现中的代码,我们就可以确定一些事情:

  1. Ruby 方法查找是效率低下的根源。
  2. 只需调用一次
    is_a?
    方法即可识别对象是否为
    String
    子类的实例。
  3. Ruby 实现各不相同,但 C Ruby 至少可能不需要对
    is_a?
    进行方法查找,因为它可以对任何对象类型使用
    rb_obj_is_kind_of
  4. 检查
    to_s
    to_str
    至少涉及 1 或 2 个方法查找。实际上调用它们包括未知的额外数量的方法查找和额外调用。

考虑到这些事情,我们可以说,检查对象是否为 String 与调用

to_s
to_str
至少
一样高效,而且平均而言,它可能更高效。

© www.soinside.com 2019 - 2024. All rights reserved.