Ruby Language
Dziedzictwo
Szukaj…
Składnia
- klasa SubClass <SuperClass
Refaktoryzacja istniejących klas pod kątem dziedziczenia
Powiedzmy, że mamy dwie klasy, Cat
i 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
Metoda eat
jest dokładnie taka sama w tych dwóch klasach. Chociaż to działa, trudno jest utrzymać. Problem pogorszy się, jeśli będzie więcej zwierząt z tą samą metodą eat
. Dziedziczenie może rozwiązać ten problem.
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
Stworzyliśmy nową klasę, Animal
, i przenieśliśmy naszą metodę eat
do tej klasy. Następnie sprawiliśmy, że Cat
i Dog
odziedziczyli tę nową powszechną nadklasę. Eliminuje to potrzebę powtarzania kodu
Wielokrotne dziedziczenie
Wielokrotne dziedziczenie to funkcja, która umożliwia jednej klasie dziedziczenie z wielu klas (tj. Więcej niż jednego rodzica). Ruby nie obsługuje wielokrotnego dziedziczenia. Obsługuje tylko pojedyncze dziedziczenie (tzn. Klasa może mieć tylko jednego rodzica), ale możesz użyć kompozycji do budowania bardziej złożonych klas za pomocą modułów .
Podklasy
Dziedziczenie pozwala klasom zdefiniować określone zachowanie w oparciu o istniejącą klasę.
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!'
W tym przykładzie:
-
Dog
dziedziczy odAnimal
, co czyni go podklasą . -
Dog
zyskuje zarównosay_hello
ieat
metodyAnimal
. -
Dog
zastępuje metodęsay_hello
z inną funkcjonalnością.
Mixiny
Mixiny to piękny sposób na osiągnięcie czegoś podobnego do wielokrotnego dziedziczenia. Pozwala nam dziedziczyć, a raczej włączać metody zdefiniowane w module do klasy. Metody te można uwzględnić jako metody instancji lub metody klasy. Poniższy przykład przedstawia ten projekt.
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"
Co jest dziedziczone?
Metody są dziedziczone
class A
def boo; p 'boo' end
end
class B < A; end
b = B.new
b.boo # => 'boo'
Metody klasowe są dziedziczone
class A
def self.boo; p 'boo' end
end
class B < A; end
p B.boo # => 'boo'
Stałe są dziedziczone
class A
WOO = 1
end
class B < A; end
p B::WOO # => 1
Ale uwaga, można je zastąpić:
class B
WOO = WOO + 1
end
p B::WOO # => 2
Zmienne instancji są dziedziczone:
class A
attr_accessor :ho
def initialize
@ho = 'haha'
end
end
class B < A; end
b = B.new
p b.ho # => 'haha'
Uwaga: jeśli zastąpisz metody inicjujące zmienne instancji bez wywoływania super
, będą one zerowe. Kontynuując z góry:
class C < A
def initialize; end
end
c = C.new
p c.ho # => nil
Zmienne instancji klasy nie są dziedziczone:
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
Zmienne klasowe nie są tak naprawdę dziedziczone
Są one dzielone między klasą podstawową i wszystkimi podklasami jako 1 zmienna:
class A
@@foo = 0
def initialize
@@foo += 1
p @@foo
end
end
class B < A;end
a = A.new # => 1
b = B.new # => 2
Kontynuując z góry:
class C < A
def initialize
@@foo = -10
p @@foo
end
end
a = C.new # => -10
b = B.new # => -9