is_a? and ancestors
Part of the Object Oriented Programming section of Coddy's Ruby journey. Lesson 25 of 57.
is_a?(Class) asks whether an object is an instance of that class or of any subclass of it. kind_of? is another name for the same method:
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)Output:
true
true
true
falseinstance_of? is stricter: it is true only for the object's own class. obj.class returns that class:
class Animal
end
class Dog < Animal
end
rex = Dog.new
puts rex.instance_of?(Dog)
puts rex.instance_of?(Animal)
puts rex.classOutput:
true
false
Dogancestors lists the classes Ruby searches for methods, starting with the class itself; the full list also contains modules such as Kernel, which chapter 6 covers, so take(3) shows the first entries. Classes can be compared: Dog < Animal is true when Dog inherits from Animal:
class Animal
end
class Dog < Animal
end
p Dog.ancestors.take(3)
puts Dog < Animal
puts Animal < DogOutput:
[Dog, Animal, Object]
true
falseUse is_a? when code must treat a group of classes the same way, for example to count all mammals, whichever subclass they are. Asking for one exact class with instance_of? breaks as soon as someone adds a subclass:
mammals = animals.count { |a| a.is_a?(Mammal) } # dogs, bats, whales...
exact = animals.count { |a| a.instance_of?(Mammal) } # misses every subclassChallenge
EasyDeclare the animal classes: Animal, Mammal < Animal, Bird < Animal, Dog < Mammal, Bat < Mammal and Penguin < Bird. Animal stores a name. Then complete the helper describe(animal) in functions.rb: it returns Rex is a dog: mammal, Pingu is a penguin: bird, with the class name in lower case and the group decided with is_a?.
The supplied code reads lines dog Rex, creates the objects, prints describe for each and then mammals: 2, birds: 1.
Your code goes in animal.rb, mammal.rb, bird.rb, dog.rb, bat.rb, penguin.rb and functions.rb. main.rb holds the supplied input/output code and cannot be edited.
Try it yourself
require_relative 'animal'
require_relative 'mammal'
require_relative 'bird'
require_relative 'dog'
require_relative 'bat'
require_relative 'penguin'
require_relative 'functions'
# Supplied input/output code: keep it as it is
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}"
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Classes and Objects
Working With FilesDefining ClassesInstance VariablesMethods and selfto_s and inspectRecap - Library Card7Polymorphism and Duck Typing
PolymorphismDuck TypingAbstract Methodscase and ClassesRecap - Payment Methods2Accessors and Self
Readers and WritersCustom Settersself in MethodsIdentity and EqualityRecap - Contact List8Special Methods
Equality and hashOperator MethodsIndexing and AppendingCustom CollectionsRecap - Fractions11Project: Library Management
Books and MembersBorrowing Books3Class Methods and Variables
Class MethodsClass Instance VariablesConstantsFactory MethodsRecap - Coupon CodesPractice on your own: Online Ruby compiler