类对象的case语句

时间:2013-12-28 05:25:21

标签: ruby class

如果我klass可能(或可能不是)Class的实例,我如何检查klass对着给定类的case-statement样式,看看它是哪个类是?

的子类

例如,假设klass恰好是Fixnum。当我针对klassInteger,...检查Float时,我希望它与Integer匹配。这段代码:

case klass
when Integer ...
when Float ...
else ...
end

无效,因为它会检查klass是否为类的实例。我想检查klass是否是类的子类(或者它本身就是那个类)。

这是迄今为止我能做的最好的事情,但我觉得这可能是一种矫枉过正而且效率不高:

class ClassMatcher
  def initialize klass; @klass = klass end
  def === other; other.kind_of?(Class) and other <= @klass end
end

class Class
  def matcher; ClassMatcher.new(self) end
end

klass = Fixnum
case klass
when Integer.matcher then puts "It is a subclass of Integer."
when Float.matcher then puts "It is a subclass of Float."
end
# => It is a subclass of Integer.

4 个答案:

答案 0 :(得分:7)

更实用的东西?

is_descendant = lambda { |sample, main| main <= sample }
not_a_class = lambda { |x| !x.kind_of?(Class) }

mine = Fixnum

case mine
when not_a_class then raise 'Not a class' # Credits to @brymck
when is_descendant.curry[Float] then puts 'Float'
when is_descendant.curry[Integer] then puts 'Integer'
else raise 'Shit happens!'
end

# ⇒ Integer

答案 1 :(得分:3)

case 
when klass <= Integer ...
when klass <= Float ...
else ...
end

重复,但可能是你正在寻找的唯一方法。

答案 2 :(得分:2)

如何使用Enumerable#findModule#<=

obj = Fixnum
[Float, Integer].find { |cls| obj.kind_of?(Class) && obj <= cls }
# => Integer

或简单ifelsif,..:

obj = Fixnum
if ! obj.kind_of? Class; puts 'It is not a class'
elsif obj <= Integer; puts 'It is a subclass of Integer'
elsif obj <= Float; puts 'It is a subclass of Float'
else; puts 'other'
end
# => It is a subclass of Integer

答案 3 :(得分:1)

实际上它会:

case Class
when Module
  puts 'Class is a subclass of Module'
end

编辑:

在您的解释之后,我才会想到这一点:

case
when Fixnum < Integer
  puts 'Fixnum < Integer'
end