在Ruby中实现to_int和to_str的后果
I,它公开一个字符串值和一个int值(分别是命令输出和退出代码)。除了通过在Ruby中实现to_int和to_str的后果,ruby,duck-typing,Ruby,Duck Typing,I,它公开一个字符串值和一个int值(分别是命令输出和退出代码)。除了通过向_s和向_i公开它们之外,我还使用向_str和向_int公开它们,如下所示: class Status def to_s @output end alias :to_str :to_s def to_i @status.exitstatus end alias :to_int :to_i end 我的想法是能够在尽可能多的情况下使用这个对象。将其强制为字符串或int可以提高可用
向_s
和向_i
公开它们之外,我还使用向_str
和向_int
公开它们,如下所示:
class Status
def to_s
@output
end
alias :to_str :to_s
def to_i
@status.exitstatus
end
alias :to_int :to_i
end
我的想法是能够在尽可能多的情况下使用这个对象。将其强制为字符串或int可以提高可用性。例如,我可以用字符串连接对象:
a_string = "Output was: " + results
(我想用它作为int强制的一个例子,但是Fixnum.+不喜欢它,所以它实际上不起作用:)
到目前为止,我读到的所有东西都表明,这可能是一件“不好”的事情。常见的主题是这样的:“当对象可以表示为字符串/int时,使用to_s
/to_i
,但只有当对象基本上是字符串/int时才使用to_str
/to_int
”
毫无疑问,我的类“基本上”不是字符串或int
我对这条规则有一些问题:
Float.to_int
。故事是这样的,因为浮点数总是有一个整数分量,to_int
是一个有效的方法。然而,我认为这是错误的:浮点不是整数(因为它有一个非整数成分),所以试图将它们的“类型”等同起来没有多大意义。您可以合法地将浮点转换为整数(通过截断),但我可以说我也可以将状态转换为整数(通过“截断”所有非退出代码信息)到str
和到int
的过程中是否存在任何实际的(即:实际的)危害
更新:Jörg W Mittag举了一个让我想到一些事情的例子。重新表述这个问题:当你已经有了
到
/到
的时候,真的有必要有到_str
/到_int
?(除了特定方法已经期望超过到
)
例如,在Jörg的Array.join示例中,数组成员通过转换为_s,而分隔符通过转换为_str。但是这真的是必要的吗?如果Array.join改为调用separator.to_,那么您可以成功地向它传递更多的对象(例如:整数、符号等),并获得更大的灵活性。Ruby会从这种分离中受益吗?duck类型的精神当然不会让人在源代码中查找Status对象来找出返回的内容
我个人认为您应该通过两种实例方法公开文本结果和退出状态:
class Status
...
def message
@output
end
def exit_status
@status.exitstatus
end
end
然后按如下方式使用它
a_string = "Output was: " + results.message
a_int = 1 + results.exit_status
这对任何阅读代码的人来说都是有意义的,IMHO
它使我的类不那么灵活/可用。例如:如果我没有Status#to_str
,我无法使用String++
将状态输出与另一个字符串连接起来
这是一个糟糕的例子,因为串接字符串是单向的Ruby。字符串插值是首选方法:
a_string = "Output was: #{results}"
这就行了™, 因为字符串插值实际上对插值表达式的结果调用
这似乎违背了鸭子打字的精神。对象的用户(即:将其作为参数获取的方法)不应该关心该对象是什么,而应该只关心它能做什么。(在本例中,“do”表示“可以表示为字符串/int”。)
我认为“可以表示为字符串/int”并不是真正的行为。IOW:“对象可以做什么”是关于特定上下文中有趣的行为,“可以表示为字符串/int”不是真正有趣的行为
如果你说“Status IS-A Integer”(这本质上就是to_int
的意思),那么你可以用它来做算术运算。但“将42添加到未找到的文件”意味着什么呢?成功的对数是多少?失败的平方根是多少
在上面的字符串插值示例中,有趣的行为是“可以显示”。这基本上是通过实现#to_s
来表示的。连接两个字符串OTOH需要两个字符串
“基本上是字符串/int”的参数对我来说非常模糊。例如,您会看到经常提到Float#to_int
。故事是这样的,因为浮点数总是有一个整数分量,to_int
是一个有效的方法。然而,我认为这是错误的:浮点不是整数(因为它有一个非整数成分),所以试图将它们的“类型”等同起来没有多大意义。您可以合法地将浮点转换为整数(通过截断),但我可以说我也可以将状态转换为整数(通过“截断”所有非退出代码信息)
同样,这是一个相当弱的论点,因为我实际上同意你的观点:那是错误的
在德国法律中,我们有一项原则很难掌握,而且是非首创的,但我认为它在这里完全适用。它被称为“Keine Gleichheit im Unrecht”(错误中没有平等)。这意味着宪法赋予的基本平等权利只适用于法律。换句话说:OJ不会让谋杀合法化
所以,就因为有垃圾代码
a_string = "Output was: #{results}"