类对象的Case语句[复制]

时间:2021-11-15 10:17:25

This question already has an answer here:

这个问题已经有了答案:

If I have klass that may (or may not) be an instance of Class, how can I check klass against given classes in case-statement style to see which class it is a subclass of?

如果我有klass,它可能(也可能不是)是类的实例,我如何用case-statement样式检查klass,以查看它是哪个类的子类?

For example, suppose klass happens to be Fixnum. When I check klass against Integer, Float, ..., I want it to match Integer. This code:

例如,假设klass碰巧是Fixnum。当我检查klass与整数,浮点数,…,我希望它匹配整数。这段代码:

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

will not work because it will check whether klass is an instance of the classes. I want to check whether klass is a subclass of the classes (or is itself that class).

将无法工作,因为它将检查klass是否是类的实例。我想检查klass是否是类的子类(或者它本身就是类)。

This is the best I can do so far, but I feel it may be an overkill and is not efficient:

这是到目前为止我所能做的最好的,但我觉得这可能有点过头了,没有效率:

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 个解决方案

#1


7  

Something more functional?

一些更多的功能?

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

#2


2  

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

Repetitive, but probably the only way to do what you're looking for.

重复,但可能是做你想做的事情的唯一方法。

#3


2  

How about using Enumerable#find and Module#<= ?

使用Enumerable#find和Module#<=怎么样?

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

or simple if, elsif, ..:

或者简单地说,elsif。

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

#4


1  

Well, actually it will:

事实上,它将:

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

Edit:

编辑:

Only that comes to my mind after your explanations:

只有在你解释之后我才想起:

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

#1


7  

Something more functional?

一些更多的功能?

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

#2


2  

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

Repetitive, but probably the only way to do what you're looking for.

重复,但可能是做你想做的事情的唯一方法。

#3


2  

How about using Enumerable#find and Module#<= ?

使用Enumerable#find和Module#<=怎么样?

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

or simple if, elsif, ..:

或者简单地说,elsif。

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

#4


1  

Well, actually it will:

事实上,它将:

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

Edit:

编辑:

Only that comes to my mind after your explanations:

只有在你解释之后我才想起:

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