CodeGym /Kursy /Python SELF PL /Dziedziczenie

Dziedziczenie

Python SELF PL
Poziom 15 , Lekcja 6
Dostępny

6.1 Dziedziczenie — to proste

Dziedziczenie — to fundamentalna koncepcja programowania obiektowego (OOP), która pozwala jednej klasie (zwanej klasą dziecka lub podklasą) dziedziczyć pola i metody innej klasy (zwanej klasą rodzica lub superklasą).

Takie podejście pozwala tworzyć bardziej ogólne klasy i ponownie wykorzystywać kod, poprawiając jego organizację i utrzymanie.

Dlaczego potrzebne jest dziedziczenie?

Załóżmy, że musisz napisać kod i zdecydowałeś się zrobić to w formie klasy. Potem dowiadujesz się, że w twoim projekcie już istnieje klasa, która robi prawie wszystko, czego potrzebujesz w swojej klasie. Możesz po prostu skopiować kod tej klasy do swojej i korzystać z niego do woli.

A możesz „jakby skopiować”. Możesz zadeklarować tę klasę jako rodzica swojej klasy, a wtedy Python doda twojej klasie zachowanie klasy rodzica.

Wyobraź sobie, że jesteś naturą i chcesz stworzyć Psa. Co będzie szybsze — stworzyć psa z bakterii w miliard lat czy udomowić wilka w 200 tysięcy lat?

Przykład podstawowego dziedziczenia

Załóżmy, że masz klasę rodzica Animal z polem name:


class Animal:
    def __init__(self, name):
        self.name = name

Chcemy stworzyć 2 klasy-dzieci dla niej — Dog i Cat, a także dodać im obu metodę speak:


class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

W powyższym przykładzie klasy dzieci Dog i Cat dziedziczą od Animal i dodają metodę speak.

Klasa Dog:

  • Dziedziczy atrybut name z Animal.
  • Dodaje metodę speak, zwracającą string specyficzny dla psów.

Klasa Cat:

  • Dziedziczy atrybut name z Animal.
  • Dodaje metodę speak, zwracającą string specyficzny dla kotów.

Ostateczna wersja kodu wygląda tak:


class Animal:
    def __init__(self, name):
        self.name = name
         
class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"
        
class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"
         
dog = Dog("Buddy")
cat = Cat("Whiskers")
        
print(dog.speak())  # Wyświetli: Buddy says Woof!
print(cat.speak())  # Wyświetli: Whiskers says Meow!

W tym przykładzie Animal jest klasą rodzica, a Dog i Cat — klasami dzieci. Klasy dzieci dziedziczą atrybut name i metodę __init__ od klasy rodzica Animal, ale dodają metody speak.

6.2 Pod maską dziedziczenia

Jeśli dodałeś swojej klasie rodzica, to jest to bardzo podobne do tego, jakbyś skopiował kod klasy rodzica do swojej klasy.


class Animal:
    def __init__(self, name):
        self.name = name
         

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)  # Wykonanie konstruktora klasy rodzica
        
    def speak(self):
        return f"{self.name} says Woof!"
        
class Cat(Animal):
    def __init__(self, name):
        super().__init__(name)  # Wykonanie konstruktora klasy rodzica
        
    def speak(self):
        return f"{self.name} says Meow!"
        

dog = Dog("Buddy")
cat = Cat("Whiskers")
        
print(dog.speak())  # Wyświetli: Buddy says Woof!
print(cat.speak())  # Wyświetli: Whiskers says Meow!

To nie jest całkiem dokładny opis, ale jeśli nigdy nie spotkałeś się z koncepcją dziedziczenia, to możesz myśleć o niej w ten sposób. Dalej dodamy tutaj jeszcze kilka szczegółów.

6.3 Hierarchia dziedziczenia

Bardzo często, gdy projektowana jest skomplikowana struktura dużej grupy klas, możesz napotkać całą hierarchię dziedziczenia.

Na przykład, masz klasę Animal — to podstawowa klasa dla wszystkich zwierząt:


class Animal:
    def __init__(self, name):
        self.name = name
        
    def speak(self):
        raise NotImplementedError("Subclass must implement abstract method")

Nawet dodaliśmy mu metodę speak, ale ponieważ abstrakcyjne zwierzę nie mówi, ta metoda po prostu rzuca wyjątek NotImplementedError — to standardowa praktyka.

Następnie dodajemy klasy pośrednie, które odpowiadają kategoriom zwierząt: Mammal — to ssaki i Bird dla ptaków.


class Mammal(Animal):
    def __init__(self, name, fur_color):
        super().__init__(name)  # Wykonanie konstruktora klasy rodzica
        self.fur_color = fur_color
         

class Bird(Animal):
    def __init__(self, name, wing_span):
        super().__init__(name)  # Wykonanie konstruktora klasy rodzica
        self.wing_span = wing_span
        
    def fly(self):
        return f"{self.name} is flying with a wingspan of {self.wing_span} meters."

I w końcu, dopiero na końcowym etapie pojawiają się klasy konkretnych gatunków zwierząt:


class Dog(Mammal):
    def speak(self):
        return f"{self.name} says Woof!"
         
        
class Cat(Mammal):
    def speak(self):
        return f"{self.name} says Meow!"
        
class Parrot(Bird):
    def speak(self):
        return f"{self.name} says Squawk!"

To z nimi zazwyczaj pracuje końcowy kod:


animals = [Dog("Buddy", "brown"), Cat("Whiskers", "white"), Parrot("Polly", 0.5)]
            
for animal in animals:
    print(animal.speak())

print(f"{dog.name} has {dog.fur_color} fur.")  # Wyświetli: Buddy has brown fur.
print(f"{cat.name} has {cat.fur_color} fur.")  # Wyświetli: Whiskers has white fur.
print(parrot.fly())  # Wyświetli: Polly is flying with a wingspan of 0.5 meters.

Chociaż technicznie nie ma zakazów tworzenia hierarchii z dziesiątkami przodków, ważne jest, aby pamiętać, że bez potrzeby lepiej trzymać się prostoty. W prostocie siła.

1
Опрос
Klasy i OOP,  15 уровень,  6 лекция
недоступен
Klasy i OOP
Klasy i OOP
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION