Menu
CoddyTech

is_a? 和祖先类

本课属于 Coddy Ruby 学习旅程的“面向对象编程”单元。第 25 课,共 57 课。

is_a?(Class)用于询问一个对象是否是该类或其任意子类的实例。kind_of?是同一个方法的另一个名称:

class Animal
end

class Dog < Animal
end

rex = Dog.new
puts rex.is_a?(Dog)
puts rex.is_a?(Animal)
puts rex.is_a?(Object)
puts rex.kind_of?(String)

输出:

true
true
true
false

instance_of? 更严格:只有当对象属于它自己的类时,结果才是 true。obj.class 会返回该类:

class Animal
end

class Dog < Animal
end

rex = Dog.new
puts rex.instance_of?(Dog)
puts rex.instance_of?(Animal)
puts rex.class

输出:

true
false
Dog

ancestors会列出 Ruby 搜索方法时会查找的类,从类本身开始;完整列表还包含 Kernel 这样的模块,第 6 章会介绍它,所以 take(3) 会显示前几项。类之间可以进行比较:当 Dog 继承自 Animal 时,Dog < Animal 的结果是 true:

class Animal
end

class Dog < Animal
end

p Dog.ancestors.take(3)
puts Dog < Animal
puts Animal < Dog

输出:

[Dog, Animal, Object]
true
false

当代码需要以相同方式处理一组类时,使用 is_a?,例如,无论哺乳动物属于哪个子类,都统计所有哺乳动物。使用 instance_of? 检查对象是否属于某个确切的类,一旦有人添加子类,这种做法就会出问题:

mammals = animals.count { |a| a.is_a?(Mammal) }       # 狗、蝙蝠、鲸鱼……
exact = animals.count { |a| a.instance_of?(Mammal) }  # 会漏掉所有子类
challenge icon

挑战

简单

声明这些动物类:Animal、Mammal < Animal、Bird < Animal、Dog < Mammal、Bat < Mammal 和 Penguin < Bird。Animal 存储一个名称。然后在 functions.rb 中完成辅助函数 describe(animal):它会返回 Rex is a dog: mammal、Pingu is a penguin: bird,类名使用小写形式,分组则由 is_a? 决定。

给定的代码会读取 dog Rex 这样的行,创建对象,为每个对象打印 describe 的结果,然后打印 mammals: 2, birds: 1。

你的代码要写在 animal.rb、mammal.rb、bird.rb、dog.rb、bat.rb、penguin.rb 和 functions.rb 中。main.rb 包含给定的输入/输出代码,不能编辑。

亲手试试

require_relative 'animal'
require_relative 'mammal'
require_relative 'bird'
require_relative 'dog'
require_relative 'bat'
require_relative 'penguin'
require_relative 'functions'

# 已提供的输入/输出代码:保持原样
input = []
while (line = gets)
  input << line.chomp
end
kinds = { "dog" => "Dog", "bat" => "Bat", "penguin" => "Penguin" }
animals = input.map do |line|
  kind, name = line.split
  Object.const_get(kinds[kind]).new(name)
end
animals.each { |a| puts describe(a) }
mammals = animals.count { |a| a.is_a?(Mammal) }
birds = animals.count { |a| a.is_a?(Bird) }
puts "mammals: #{mammals}, birds: #{birds}"
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Ruby 在线编译器