gpt4 book ai didi

ruby - #{} 总是等同于 to_s 吗?

转载 作者:数据小太阳 更新时间:2023-10-29 07:26:47 26 4
gpt4 key购买 nike

在“What does it mean to use the name of a class for string interpolation?”中,Candide 建议字符串中的 #{} 隐式调用 to_s。所以,例如:

my_array = [1, 2, 3, 4]
p my_array.to_s # => "[1, 2, 3, 4]"
p "#{my_array}" # => "[1, 2, 3, 4]"

但是,如果如下所示重新定义 Array 的 to_s,我会得到不同的结果:

class Array
def to_s
self.map { |elem| elem.to_s }
end
end

p my_array.to_s # => ["1", "2", "3", "4"]
p "#{my_array}" # => "#<Array:0x007f74924c2bc0>"

我想这随时都会发生,无论如何 to_s 都会被覆盖。

如果可能的话,我应该怎么做才能使字符串中的 to_s 和表达式 #{} 保持相等?

我在 RubyMonk lesson 中遇到了这个问题: 根据类(class) #{ogres} 应该返回什么,根据我的经验是不同的。

最佳答案

请查看 Object#to_s 的文档.它表示 to_s 应该返回一个 String。当你覆盖一个方法时,你应该始终遵守它的约定。查看 Array#to_s 的文档如您所见,它 返回一个String。 [请注意,所有 to_Xto_XYZ 方法都是如此:它们必须 总是 返回相应类的对象,它们不得 引发 Exception 否则会失败。]

但是,to_s 的实现不会返回String。它返回一个数组,因此违反 to_s 的契约。一旦你违反了方法的约定,所有的赌注都会落空。就我个人而言,我认为在此处引发 TypeError 异常会更合适,但 Ruby 试图表现得很好并返回 some String 代替,它(在本例中)打印类名和一些唯一标识符。

这是对 RubySpec project 的提交其中(隐含地)声明没有Exceptionraised,并明确声明返回了一个实现定义但未指定的String:The spec for interpolation when Object#to_s did not return a String was confusing the default representation of an arbitrary object and Object#inspect.

最新版本的规范,在项目关闭之前看起来像这样 language/string_spec.rb#L197-L208 :

it "uses an internal representation when #to_s doesn't return a String" do
obj = mock('to_s')
obj.stub!(:to_s).and_return(42)

# See rubyspec commit 787c132d by yugui. There is value in
# ensuring that this behavior works. So rather than removing
# this spec completely, the only thing that can be asserted
# is that if you interpolate an object that fails to return
# a String, you will still get a String and not raise an
# exception.
"#{obj}".should be_an_instance_of(String)
end

如您所见,在这种情况下,可以保证的是您不会得到异常,而您 获取一个 String,但是,它没有说明该 String 的样子。

关于ruby - #{} 总是等同于 to_s 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32633510/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com