我想做这个
lol = Klass.new(values)
unless lol
print "false"
end
lol.other_method # it is not nil or false, it is a Klass instance!
但在这种情况下,lol不是零或假,而是一个基于某种内在价值可以作为假的对象。我有这个选择
lol = Klass.new(values)
unless lol.to_bool
print "false"
end
但它是丑陋的恕我直言。
我在想扩展FalseClass或者玩==但没有成功。有任何想法吗?
不幸的是,这是不可能的。
这是Ruby不面向对象的烦人案例之一。在OO,它 必须 一个物体可以模拟另一个物体(事实上,取决于你问的是谁,这就是它 定义 OO - 记住OO来自模拟),但是不可能构建一个模拟的对象 false
。
这是因为,在Ruby中,条件控制结构被烘焙到语言中并且不会转换为消息发送,而在其他OO语言中它们只是常规消息发送(或者至少转换为消息发送,就像 for
在Ruby中翻译成 each
)。例如,在Smalltalk中,Booleans实际上是使用Lambda Calculus所知的Booleans的Church编码实现的,并且转换为Ruby它们看起来有点像这样:
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
只需实施各自的方法即可。
在其他情况下,某些对象真的绝对 必须 作为特定类的一个实例而不只是说正确的协议,Ruby提供了一个逃生舱。例如,如果一个方法 真 需要一个 Array
作为一个论点,那么它将首先尝试打电话 to_ary
至少让你有机会将你的对象转换为 Array
。同样的道理 to_str
, to_int
, to_proc
, to_float
等等。但没有相应的 to_bool
协议。
简短回答: 不要这样做。
答案很长,在Ruby中有 只要 评价为假的两件事: false
和 nil
。从字面上看,其他一切评价为真。
许多应用程序依赖于此行为,如果您以某种方式设法更改此操作,可能会出现故障。这就像将1定义为偶数一样。这会引起问题。