Ruby: Как мы можем определить, имеет ли объект o класс C в качестве предка в иерархии классов? - PullRequest
3 голосов
/ 26 ноября 2010

Можно ли в Ruby определить, имеет ли объект o класс C в качестве предка в иерархии классов, используя какой-либо метод?

Ниже приведен пример, в котором я использую гипотетический метод has_super_class? для его выполнения.Как мне сделать это в реальности?

o = Array.new
o[0] = 0.5
o[1] = 1
o[2] = "This is good"
o[3] = Hash.new

o.each do |value|
  if (value.has_super_class? Numeric)
    puts "Number"
  elsif (value.has_super_class? String)
    puts "String"
  else
    puts "Useless"
  end
end

Ожидаемый результат:

Number
Number
String
Useless

Ответы [ 4 ]

8 голосов
/ 26 ноября 2010

Попробуйте obj.kind_of?(Klassname):

1.kind_of?(Fixnum) => true
1.kind_of?(Numeric) => true
....
1.kind_of?(Kernel) => true

Метод kind_of? также имеет идентичную альтернативу is_a?.

Если вы хотите проверить только, является ли объект (прямым)экземпляр класса, используйте obj.instance_of?:

1.instance_of?(Fixnum) => true
1.instance_of?(Numeric) => false
....
1.instance_of?(Kernel) => false

Вы также можете получить список всех предков объекта, вызвав метод ancestors для его class.Например, 1.class.ancestors дает вам [Fixnum, Integer, Precision, Numeric, Comparable, Object, PP::ObjectMixin, Kernel].

3 голосов
/ 26 ноября 2010

Просто используйте .is_a?

o = [0.5, 1, "This is good", {}]

o.each do |value|
  if (value.is_a? Numeric)
    puts "Number"
  elsif (value.is_a? String)
    puts "String"
  else
    puts "Useless"
  end
end

# =>
Number
Number
String
Useless
0 голосов
/ 03 октября 2014

Рад пути:

1.class.ancestors => [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject]
1.class <= Fixnum => true
1.class <= Numeric => true
1.class >= Numeric => false
1.class <= Array => nil

Если вы хотите быть увлеченным этим, вы можете сделать что-то вроде этого:

is_a = Proc.new do |obj, ancestor|
  a = { 
    -1 => "#{ancestor.name} is an ancestor of #{obj}",
    0 => "#{obj} is a #{ancestor.name}",
    nil => "#{obj} is not a #{ancestor.name}",
  }
  a[obj.class<=>ancestor]
end

is_a.call(1, Numeric) => "Numeric is an ancestor of 1"
is_a.call(1, Array) => "1 is not a Array"
is_a.call(1, Fixnum) => "1 is a Fixnum"
0 голосов
/ 26 ноября 2010
o.class.ancestors

используя этот список, мы можем реализовать has_super_class? вот так (как синглетный метод):

def o.has_super_class?(sc)
  self.class.ancestors.include? sc
end
...