ruby除非有多种条件的bug

Thu*_*der 0 ruby multiple-conditions

共同代码:

class ThingA end
class ThingB end
class ThingC end
Run Code Online (Sandbox Code Playgroud)

为了设置上述类型的条件检查,我使用了基本的"if!..."结构,它可以产生预期的准确结果.

示例代码if!...:

obj = ThingA.new
puts 'yes it is a ThingC' if !obj.is_a?(ThingA) && !obj.is_a?(ThingB) # works ok
# stdout => nothing

obj = ThingB.new
puts 'yes it is a ThingC' if !obj.is_a?(ThingA) && !obj.is_a?(ThingB) # works ok
# stdout => nothing

obj = ThingC.new
puts 'yes it is a ThingC' if !obj.is_a?(ThingA) && !obj.is_a?(ThingB) # works ok
# stdout => yes it is a ThingC
Run Code Online (Sandbox Code Playgroud)

考虑到"除非"是基本"if!..."构造的更具描述性的替代,我使用"除非"来实现上述.

示例代码除非:

obj = ThingA.new
puts 'yes it is a ThingC' unless obj.is_a?(ThingA) && obj.is_a?(ThingB) # BUG
# stdout => yes it is a ThingC

obj = ThingB.new
puts 'yes it is a ThingC' unless obj.is_a?(ThingA) && obj.is_a?(ThingB) # BUG
# stdout => yes it is a ThingC

obj = ThingC.new
puts 'yes it is a ThingC' unless obj.is_a?(ThingA) && obj.is_a?(ThingB) # ???
# stdout => yes it is a ThingC
Run Code Online (Sandbox Code Playgroud)

显然,"除非"版本无法产生相同的准确结果.

基于这些简单而直截了当的结果,任何人都难以得出结论"除非准确地处理多个条件"吗?

Eri*_*nil 8

逻辑与除非

布尔逻辑变得难以解析unless.您可以使用以下命令重写它if:

  • unless a || b相当于if !(a || b),相当于if !a && !b
  • unless a && b相当于if !(a && b),相当于if !a || !b

你的"虫子"

obj.is_a?(ThingA) && obj.is_a?(ThingB)必须是falseif ThingA并且ThingB是独立的类.

它只能是true一个类是另一个类的子类.在这种情况下,您只需要检查是否obj是Subclass实例:

obj.is_a?(ThingA) && obj.is_a?(Object)当且仅当它obj是一个ThingA对象时才是真的,所以你可以写:

obj.is_a?(ThingA)

备择方案

对于您的示例,您应该使用case:

obj = ThingA.new

case obj
when ThingA
  puts "yes, it is a ThingA"
when ThingB
  puts "yes, it is a ThingB"
when ThingC
  puts "yes, it is a ThingC"
else
  puts "no, it is some other Object"
end
Run Code Online (Sandbox Code Playgroud)

要么

case obj
when ThingA, ThingB, ThingC
  puts "yes, it is a Thing A B or C"
else
  puts "no, it is some other Object"
end
Run Code Online (Sandbox Code Playgroud)

要么

puts "yes, it is a #{obj.class}"
Run Code Online (Sandbox Code Playgroud)

他们回来了 :

yes, it is a ThingA
yes, it is a Thing A B or C
yes, it is a ThingA
Run Code Online (Sandbox Code Playgroud)