Menu
Coddy logo textTech

is_a? y ancestros

Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 25 de 57.

is_a?(Class) pregunta si un objeto es una instancia de esa clase o de cualquiera de sus subclases. kind_of? es otro nombre para el mismo método:

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)

Salida:

true
true
true
false

instance_of? es más estricto: solo es true para la propia clase del objeto. obj.class devuelve esa clase:

class Animal
end

class Dog < Animal
end

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

Salida:

true
false
Dog

ancestors enumera las clases en las que Ruby busca métodos, comenzando por la propia clase; la lista completa también contiene módulos como Kernel, que se aborda en el capítulo 6, por lo que take(3) muestra las primeras entradas. Las clases se pueden comparar: Dog < Animal es true cuando Dog hereda de Animal:

class Animal
end

class Dog < Animal
end

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

Salida:

[Dog, Animal, Object]
true
false

Usa is_a? cuando el código deba tratar un grupo de clases de la misma manera, por ejemplo, para contar todos los mamíferos, independientemente de cuál sea su subclase. Preguntar por una única clase exacta con instance_of? deja de funcionar en cuanto alguien añade una subclase:

mammals = animals.count { |a| a.is_a?(Mammal) }       # perros, murciélagos, ballenas...
exact = animals.count { |a| a.instance_of?(Mammal) }  # omite todas las subclases
challenge icon

Desafío

Fácil

Declara las clases de animales: Animal, Mammal < Animal, Bird < Animal, Dog < Mammal, Bat < Mammal y Penguin < Bird. Animal almacena un nombre. Después, completa la función auxiliar describe(animal) en functions.rb: devuelve Rex is a dog: mammal, Pingu is a penguin: bird, con el nombre de la clase en minúsculas y el grupo determinado mediante is_a?.

El código proporcionado lee líneas dog Rex, crea los objetos, imprime describe para cada uno y después mammals: 2, birds: 1.

Tu código va en animal.rb, mammal.rb, bird.rb, dog.rb, bat.rb, penguin.rb y functions.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

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

# Código de entrada/salida suministrado: déjalo tal como está
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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de Ruby online