【问题标题】:Can #to_s ever fail?#to_s 会失败吗?
【发布时间】:2023-03-24 21:00:01
【问题描述】:

我正在用 Ruby 构建一个简单的工厂,它返回一个 Callable(在本例中为 Lambda),它知道如何转换为传递的类型的名称(例如 String.name # => 'String')。

要尝试转换Fixnums,我正在使用Integer,如果传递的值不可转换,它将失败。同样,我正在使用FloatTime.zone.parse(x).to_time 等...

然而,对于Strings,我发现自己只是使用#to_s,我相信这会使我的Lambdas 有点不一致,因为除了String 转换器之外的所有转换器都可能失败(引发Exception)。

假设没有恶意的猴子补丁,除了 Rails 提供的补丁,#to_s 真的不会引发异常吗?

【问题讨论】:

标签: ruby-on-rails ruby casting


【解决方案1】:

每个对象都继承自Object,它实现了默认的to_sinspect,返回“#”字符串。因此,如果您不覆盖该定义,#to_s 将适用于每个类。

但是,可以编写自己的 #to_s 实现并在那里引发异常,但这不太可能 - 我无法想象为什么有人要这样做。

【讨论】:

  • 其实可以继承BasicObject(不实现to_s)
  • 对!无论如何,这不是很平常。
【解决方案2】:

Ruby 中的每个对象都继承自具有 to_s 实现的基础对象,所以你应该没问题。请记住,结果并不总是可以预测的。

例如。 nil.to_s 返回 ""

【讨论】:

  • nil.to_s 返回一个空字符串是完全可以预测的。
  • 选词不当。很多人希望 nil.to_s 在实际上返回“”时返回“nil”。对某些人来说,这违反了最小意外的原则。我们可以为此争论一整天,这就是我的评论的全部意思。
  • @JeffPrice Matz 似乎将便利性置于可预测性/一致性之上。 nil.to_s 返回 "" 比返回 "nil" 有用得多。
  • 它还会返回什么?它为每个其他类返回代数“零”,那么为什么它会为字符串返回不同的东西呢? (即,对于nil 响应的每条to_X 消息,以下情况成立:nil.to_X + some_X == some_X && some_X + nil.to_X == some_X。)
【解决方案3】:

#to_X 方法(to_ato_hto_sto_fto_ito_cto_r)和to_XYZ(@9876543330@4、 、to_strto_floatto_intto_symto_procto_ioto_enumto_path) 方法不应失败。一个对象可能不响应其中一些或任何一个,但如果它确实响应,那么它不应该失败,它不应该引发异常并且它应该返回正确类的实例。

我不确定这是否真的在文档中明确说明,但 Ruby 社区就是这样对待它们的。

Kernel#XYZ 方法(Kernel#ArrayKernel#ComplexKernel#FloatKernel#HashKernel#IntegerKernel#RationalKernel#String)如果参数不可转换,OTOH 将引发异常。

所以,简而言之:iff 一个对象响应to_s,那么它不应该失败,但是,它可以选择干脆不响应@987654349 @(不过,这很不寻常)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-04
    • 2019-03-27
    • 2016-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-29
    • 2011-05-07
    相关资源
    最近更新 更多