La herencia de clases es una relacción entre dos clases. La ventaja de la herencia es que las clases que en una jerarquía están en un nivel inferior, heredan las características de las clases de niveles superiores; y además, pueden añadir sus propias características.
Por ejemplo: todos los gatos son mamíferos. Si todos los mamíferos respiran, la clase gato por descender de la clase mamífero hereda esta característica: los gatos respiran.
Esto puede programarse así:
class Mamifero
def respirar
puts 'inspirar, espirar'
end
end
# el símbolo < indica que
# Gato es una subclase de Mamifero
class Gato < Mamifero
def maullar
puts 'Miaaaaaaaaaaau'
end
end
cribas = Gato.new
cribas.respirar
cribas.maullar
Aunque no se especificó que los gatos puedan respirar, todos los gatos herederán esa característica de la clase Mamifero
, ya que el gato es una subclase de los mamíferos. En el argot, Mamifero
es la super-clase o clase padre, y Gato
es la subclase, o clase hija. Esto es una ventaja para el programador: los gatos tienen la capacidad de respirar, sin haberlo implementado.
En Ruby, como se mostró en este esquema, la clase Object
es la madre de todas las clases en Ruby; por lo tanto, sus métodos están disponibles en todos los objetos, excepto aquellos que se han sobrescrito.
Habrá situaciones donde las propiedades de una super-clase no deberían ser heredadas por una subclase en particular. Por ejemplo, las aves generalmente saben volar, pero los pingüinos son una subclase de Ave
, y no vuelan:
class Ave
def asear
puts 'Me estoy limpiando mis plumas.'
end
def volar
puts 'Estoy volando.'
end
end
class Pinguino < Ave
def volar
puts 'Lo siento, no soy capaz de volar.'
end
end
p = Pinguino.new
p.asear
p.volar
Se ha sobrescrito el método volar. La gran ventaja que aporta el uso de la herencia de clases, se llama programación diferencial: vamos de lo más general a lo más particular, añadiendo y modificando donde sea necesario.
Los dos ejemplos anteriores son traducciones de la guía online "Ruby User's Guide".
class Bicicleta
attr_reader :marchas, :ruedas, :asientos # se hablará de attr_reader
def initialize(marchas = 1)
@ruedas = 2
@asientos = 1
@marchas = marchas
end
end
class Tandem < Bicicleta
def initialize(marchas)
super
@asientos = 2
end
end
t = Tandem.new(2)
puts t.marchas
puts t.ruedas
puts t.asientos
b = Bicicleta.new
puts b.marchas
puts b.ruedas
puts b.asientos
Cuando uno usa super dentro de un método, Ruby manda un mensaje a la clase madre del objeto al que pertence el método, buscando un método con el mismo nombre. Si:
super()
, no se pasan argumentos al método de la clase madre.super(a, b, c)
, se mandand los argumentos a, b, c.En este caso, se usa super en el método initialize
de Tandem, lo que provoca el uso del initialize de Bicicleta para crear instancias de Tandem. La salida es:
2
2
2
1
2
1
RAILS: la herencia de clases es una de las claves en el desarrollo de RAILS