如何创建一个在 Ruby 中充当 False 的对象 [英] How to create an Object who act as a False in Ruby
问题描述
我想这样做
lol = Klass.new(values)
unless lol
print "false"
end
lol.other_method # it is not nil or false, it is a Klass instance!
但是,在这种情况下,lol 不是 nil 或 false,而是可以根据某些内部值充当 false 的对象.我有这个选择
But lol, in this case, is not nil or false, but an object who can act as a false based on some internal value. I have this alternative
lol = Klass.new(values)
unless lol.to_bool
print "false"
end
但恕我直言,这很丑陋.
But it is ugly IMHO.
我正在考虑扩展 FalseClass 或使用 == 但没有成功.有什么想法吗?
I was thinking in extend the FalseClass or play with == but without success. Any Ideas?
推荐答案
很遗憾,这是不可能的.
Unfortunately, this is not possible.
这是 Ruby 不面向对象的烦人情况之一.在面向对象中,一个对象必须可以模拟另一个对象(实际上,这取决于你问的是谁,这就是面向对象的定义——记住 OO 出现了模拟),但不可能构建一个模拟 false
的对象.
This is one of those annoying cases where Ruby is not object-oriented. In OO, it must be possible for one object to simulate another (in fact, depending on whom you ask, this is the very definition of OO – remember that OO came out of simulation), but it is not possible to build an object which simulates false
.
这是因为,在 Ruby 中,条件控制结构被嵌入语言中并且不会转换为消息发送,而在其他 OO 语言中,它们只是常规的消息发送(或至少转换为消息发送,就像 for 转换为 each
).例如,在 Smalltalk 中,布尔值实际上是使用您从 Lambda Calculus 中知道的布尔值的 Church 编码实现的,然后转换为 Ruby 它们看起来有点像这样:
This is because, in Ruby, conditional control structures are baked into the language and don't translate into message sends, whereas in other OO languages they are just regular message sends (or at least translate into message sends, just like for
in Ruby translates into each
). For example, in Smalltalk, Booleans are actually implemented using the Church encoding of Booleans you know from Lambda Calculus, and translated to Ruby they look a bit like this:
class FalseClass
def if(&block)
# do nothing
end
def if_then_else(then_lambda, else_lambda)
else_lambda.()
end
def not
true
end
def and(&block)
self
end
def or(&block)
block.()
end
end
而 TrueClass
只是镜像:
class TrueClass
def if(&block)
block.()
end
def if_then_else(then_lambda, else_lambda)
then_lambda.()
end
def not
false
end
def and(&block)
block.()
end
def or(&block)
self
end
end
然后,而不是像
if 2 < 3 then foo end
if 2 < 3 then bar else baz end
你会
(2 < 3).if { foo }
(2 < 3).if_then_else(-> { bar }, -> { baz })
# using the new keyword arguments in Ruby 2.0, it almost reads like Smalltalk:
class FalseClass
def if(then: -> {}, else: -> {})
else.()
end
end
class TrueClass
def if(then: -> {}, else: -> {})
then.()
end
end
(2 < 3).if(then: -> { bar }, else: { baz })
这样,您只需实现相应的方法即可轻松创建一个模拟 false
的对象.
That way, you can easily create an object which simulates false
simply by implementing the respective methods.
在其他情况下,某些对象确实绝对必须是特定类的实例,而不仅仅是说出正确的协议,Ruby 提供了一个逃生舱口.例如,如果一个方法真的需要一个 Array
作为参数,那么它会首先尝试调用 to_ary
至少给你一个机会将您的对象转换为 Array
.to_str
、to_int
、to_proc
、to_float
等也是如此.但是没有等效的 to_bool
协议.
In other cases, where some object really absolutely must be an instance of a specific class and not just speak the correct protocol, Ruby provides an escape hatch. For example, if a method really requires an Array
as an argument, then it will first try to call to_ary
to at least give you a chance to convert your object into an Array
. The same goes for to_str
, to_int
, to_proc
, to_float
etc. But there is no equivalent to_bool
protocol.
这篇关于如何创建一个在 Ruby 中充当 False 的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!