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がメソッドを検索するクラスを、そのクラス自身から順に一覧表示します。完全なリストには、6章で取り上げるKernelなどのモジュールも含まれるため、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オンラインコンパイラ