我想这样做
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或使用==但没有成功。任何想法?
答案 0 :(得分:11)
不幸的是,这是不可能的。
这是Ruby不面向对象的烦人案例之一。在OO中,必须一个对象可以模拟另一个对象(实际上,取决于你问的是谁,这是OO的定义 - 记住OO出来了模拟),但不可能建立一个模拟false
的对象。
这是因为,在Ruby中,条件控制结构被烘焙到语言中并且不会转换为消息发送,而在其他OO语言中它们只是常规消息发送(或者至少转换为消息发送,就像{ Ruby中的{1}}转换为for
)。例如,在Smalltalk中,Booleans实际上是使用Lambda Calculus所知的Booleans的Church编码实现的,并且翻译成Ruby它们看起来有点像这样:
each
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 })
的对象。
在其他情况下,某些对象确实必须必须是特定类的实例而不只是说正确的协议,Ruby提供了一个逃生舱。例如,如果方法确实需要false
作为参数,那么它将首先尝试调用Array
以至少让您有机会将对象转换为to_ary
。 Array
,to_str
,to_int
,to_proc
等也是如此。但是没有等效的to_float
协议。
答案 1 :(得分:4)
简短回答:不要这样做。
很长的答案是,在Ruby中只有 两个评估为false的东西:false
和nil
。从字面上看,其他一切评价为真。
许多应用程序依赖于此行为,如果您以某种方式设法更改此操作,可能会出现故障。它就像将1定义为偶数一样。它会导致问题。