Ruby Language
Herencia
Buscar..
Sintaxis
- clase Subclase <SuperClase
Refactorizando las clases existentes para usar la herencia.
Digamos que tenemos dos clases, Cat
y Dog
.
class Cat
def eat
die unless has_food?
self.food_amount -= 1
self.hungry = false
end
def sound
puts "Meow"
end
end
class Dog
def eat
die unless has_food?
self.food_amount -= 1
self.hungry = false
end
def sound
puts "Woof"
end
end
El método de eat
es exactamente el mismo en estas dos clases. Si bien esto funciona, es difícil de mantener. El problema empeorará si hay más animales con el mismo método de eat
. La herencia puede resolver este problema.
class Animal
def eat
die unless has_food?
self.food_amount -= 1
self.hungry = false
end
# No sound method
end
class Cat < Animal
def sound
puts "Meow"
end
end
class Dog < Animal
def sound
puts "Woof"
end
end
Hemos creado una nueva clase, Animal
, y hemos movido nuestro método de eat
a esa clase. Luego, hicimos que Cat
y Dog
heredaran de esta nueva superclase común. Esto elimina la necesidad de repetir el código.
Herencia múltiple
La herencia múltiple es una característica que permite que una clase herede de varias clases (es decir, más de un padre). Ruby no admite herencia múltiple. Solo admite herencia simple (es decir, la clase solo puede tener un padre), pero puede usar la composición para crear clases más complejas utilizando módulos .
Subclases
La herencia permite que las clases definan un comportamiento específico basado en una clase existente.
class Animal
def say_hello
'Meep!'
end
def eat
'Yumm!'
end
end
class Dog < Animal
def say_hello
'Woof!'
end
end
spot = Dog.new
spot.say_hello # 'Woof!'
spot.eat # 'Yumm!'
En este ejemplo:
-
Dog
hereda deAnimal
, haciéndolo una subclase . -
Dog
gana tanto elsay_hello
como el deeat
deAnimal
. -
Dog
reemplaza el métodosay_hello
con diferentes funcionalidades.
Mixins
Los mixins son una forma hermosa de lograr algo similar a la herencia múltiple. Nos permite heredar o, más bien, incluir métodos definidos en un módulo en una clase. Estos métodos pueden incluirse como métodos de instancia o de clase. El siguiente ejemplo muestra este diseño.
module SampleModule
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def method_static
puts "This is a static method"
end
end
def insta_method
puts "This is an instance method"
end
end
class SampleClass
include SampleModule
end
sc = SampleClass.new
sc.insta_method
prints "This is an instance method"
sc.class.method_static
prints "This is a static method"
¿Qué se hereda?
Los métodos son heredados
class A
def boo; p 'boo' end
end
class B < A; end
b = B.new
b.boo # => 'boo'
Los métodos de clase son heredados.
class A
def self.boo; p 'boo' end
end
class B < A; end
p B.boo # => 'boo'
Las constantes son heredadas
class A
WOO = 1
end
class B < A; end
p B::WOO # => 1
Pero cuidado, pueden ser anulados:
class B
WOO = WOO + 1
end
p B::WOO # => 2
Las variables de instancia son heredadas:
class A
attr_accessor :ho
def initialize
@ho = 'haha'
end
end
class B < A; end
b = B.new
p b.ho # => 'haha'
Tenga cuidado, si anula los métodos que inicializan las variables de instancia sin llamar a super
, serán nulos. Continuando desde arriba:
class C < A
def initialize; end
end
c = C.new
p c.ho # => nil
Las variables de instancia de clase no se heredan:
class A
@foo = 'foo'
class << self
attr_accessor :foo
end
end
class B < A; end
p B.foo # => nil
# The accessor is inherited, since it is a class method
#
B.foo = 'fob' # possible
Las variables de clase no son realmente heredadas
Se comparten entre la clase base y todas las subclases como 1 variable:
class A
@@foo = 0
def initialize
@@foo += 1
p @@foo
end
end
class B < A;end
a = A.new # => 1
b = B.new # => 2
Continuando desde arriba:
class C < A
def initialize
@@foo = -10
p @@foo
end
end
a = C.new # => -10
b = B.new # => -9