Ruby Language
Eredità
Ricerca…
Sintassi
- classe Sottoclasse <SuperClass
Rifattorizzare le classi esistenti per utilizzare l'ereditarietà
Diciamo che abbiamo due classi, Cat
and 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
Il metodo eat
è esattamente lo stesso in queste due classi. Mentre funziona, è difficile da mantenere. Il problema peggiorerà se non ci sono più animali con lo stesso eat
metodo. L'ereditarietà può risolvere questo 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
Abbiamo creato una nuova classe, Animal
, e spostato il nostro metodo di eat
in quella classe. Quindi, abbiamo fatto ereditare Cat
e Dog
da questa nuova superclasse comune. Ciò elimina la necessità di ripetere il codice
Eredità multipla
L'ereditarietà multipla è una caratteristica che consente ad una classe di ereditare da più classi (cioè più di un genitore). Ruby non supporta l'ereditarietà multipla. Supporta solo l'ereditarietà singola (cioè la classe può avere solo un genitore), ma puoi usare la composizione per costruire classi più complesse usando i moduli .
sottoclassi
L'ereditarietà consente alle classi di definire un comportamento specifico basato su una classe esistente.
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!'
In questo esempio:
-
Dog
eredita daAnimal
, rendendolo una sottoclasse . -
Dog
guadagna sia ilsay_hello
cheeat
metodi daAnimal
. -
Dog
sovrascrive il metodosay_hello
con diverse funzionalità.
mixins
Le mixine sono un modo meraviglioso per ottenere qualcosa di simile all'ereditarietà multipla. Ci consente di ereditare o meglio includere i metodi definiti in un modulo in una classe. Questi metodi possono essere inclusi come metodi di istanza o classe. L'esempio seguente illustra questo design.
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"
Cosa viene ereditato?
I metodi sono ereditati
class A
def boo; p 'boo' end
end
class B < A; end
b = B.new
b.boo # => 'boo'
I metodi di classe sono ereditati
class A
def self.boo; p 'boo' end
end
class B < A; end
p B.boo # => 'boo'
Le costanti sono ereditate
class A
WOO = 1
end
class B < A; end
p B::WOO # => 1
Ma attenzione, possono essere ignorati:
class B
WOO = WOO + 1
end
p B::WOO # => 2
Le variabili di istanza sono ereditate:
class A
attr_accessor :ho
def initialize
@ho = 'haha'
end
end
class B < A; end
b = B.new
p b.ho # => 'haha'
Attenzione, se si sostituiscono i metodi che inizializzano le variabili di istanza senza chiamare super
, saranno nulli. Continuando dall'alto:
class C < A
def initialize; end
end
c = C.new
p c.ho # => nil
Le variabili di istanza di classe non sono ereditate:
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
Le variabili di classe non sono realmente ereditate
Sono condivisi tra la classe base e tutte le sottoclassi come 1 variabile:
class A
@@foo = 0
def initialize
@@foo += 1
p @@foo
end
end
class B < A;end
a = A.new # => 1
b = B.new # => 2
Quindi continuando dall'alto:
class C < A
def initialize
@@foo = -10
p @@foo
end
end
a = C.new # => -10
b = B.new # => -9