Poniższy kod dostępny jest na moim koncie GitHub

Abstrakcja

Tworzymy klasę abstrakcyjną, ponieważ chcemy zakazać tworzenia instancji klasy Animal.

from abc import ABC, abstractmethod


class Animal(ABC):
    def __init__(self, name):
        self.name = name
        
    @abstractmethod # wymuszenie implementacji metody w klasach pochodnych
    def name_of_the_species(self):
        pass
    
    def introduce_yourself(self):
        print("My name is", self.name)

Dziedziczenie

class Elephant(Animal):
    def name_of_the_species(self):
        return "Elephant"
dumbo = Elephant("Dumboo")
dumbo.introduce_yourself() # Elephant dziedziczy metodę z klasy Animal

>>> My name is Dumboo

Przesłanianie

class Dog(Animal):
    def name_of_the_species(self):
        return __class__.__name__
    def introduce_yourself(self):
        print('I am a dog and my name is', self.name)
azor = Dog("Azor")
azor.introduce_yourself() # przesłanianie metody- rezygnacja z metody klasy bazowej i wprowadzenia własnego kodu

>>> I am a dog and my name is Azor
class Cat(Animal):
    def name_of_the_species(self):
        return __class__.__name__
    def introduce_yourself(self):
        super().introduce_yourself() # zwraca instancję klasy bazowej
        print("I am a cat")
filemon = Cat("Filemon")
filemon.introduce_yourself() # przesłanianie metody- nadpisanie metody klasy bazowej

>>> My name is Filemon
>>> I am a cat

Przesłanianie konstruktora, hermetyzacja, dekoratory

class Bear(Animal):
    def __init__(self, name, color): # modyfikacja konstruktora- dodanie nowego parametru
        super().__init__(name) # konstruktor klasy bazowej
        self.color = color # nowy konstruktor

    @property # właściwości
    def color(self):
        return self.__color
    @color.setter
    def color(self, color):
        if color not in ['white', 'black']:
            self.__color = 'colorful'
        else:
            self.__color = color
        
    def name_of_the_species(self):
        return __class__.__name__
    
    def introduce_yourself(self):
        super().introduce_yourself()
        print("My color is", self.color)
ted = Bear("Ted","white")
ted.introduce_yourself()

>>> My name is Ted
>>> My color is white
ted = Bear("Ted","blue")
ted.introduce_yourself()

>>> My name is Ted
>>> My color is colorful

Polimorfizm

Wywołanie tej samej metody na wielu elementach listy, które są instancjami różnych klas dziedziczących.

f"isinstance(dumbo, Elephant): {isinstance(dumbo, Elephant)}"

>>> 'isinstance(dumbo, Elephant): True'
f"isinstance(ted, Elephant): {isinstance(ted, Elephant)}"

>>> 'isinstance(ted, Elephant): False'
def introducing_everyone(animals):
    for animal in animals:
        animal.introduce_yourself()
        print("\t")
        
        
animals = [dumbo, azor, filemon, ted]

introducing_everyone(animals)

>>> My name is Dumboo
	
>>> I am a dog and my name is Azor
	
>>> My name is Filemon
>>> I am a cat
	
>>> My name is Ted
>>> My color is white