Успадкування атрибутів класа
Дочірній клас успадковує атрибути базового класа.
Розглянемо на прикладі:
>>> class Base:
... def __init__(self):
... self.attr = 'Атрибут базового класа'
... def method(self):
... print('Це метод з класа Base')
... print(f'У екземпляра класа Base є атрибут {self.attr=}')
...
>>> class Child(Base):
... def child_method(self):
... print('Це метод з класа Child')
... print(f'У екземпляра класа Child є атрибут {self.attr=}')
...
>>>
Подивимось що тут відбувається:
- Клас
Child
не має власного ініціалізатора, отже він успадкує його від класаBase
- Клас
Child
успадкує від класаBase
методmethod()
- Клас
Child
має свій власний метод:child_method()
- При створенні екземпляра класа
Child
буде викликано успадкований ініціалізатор - В ініціалізаторі буде для екземпляра буде створено атрибут
attr
Перевіримо на практиці:
>>> object_of_child = Child()
>>> object_of_child.method()
Це метод з класа Base
У екземпляра класа Base є атрибут self.attr='Атрибут базового класа'
>>> object_of_child.child_method()
Це метод з класа Child
У екземпляра класа Child є атрибут self.attr='Атрибут базового класа'
>>> object_of_child.attr
'Атрибут базового класа'
>>>
Успадкування і приватні атрибути
Як нам вже відомо,
атрибути, які починаються з двох символів підкреслення (але не закінчуються ними)
є приватними атрибутами класа.
Поза видимістю класа до таких атрибутів застосовується механізм name mangling
(спотворення імені),
тобто такі атрибути "поза класом" будуть мати інші імена (клас+атрибут),
у тому числі і в успадкованих класах.
Використання приватних атрибутів дозволяє "приховати" внутрішню реалізацію базового класа для дочірніх класів. Тобто у дочірньому класі приватні атрибути базового класа не успадковуються:
>>> class Base:
... def __init__(self):
... self.__attr = 'Атрибут базового класа'
... def method(self):
... print('Це метод з класа Base')
... print(f'У екземпляра класа Base є атрибут {self.__attr=}')
...
>>> class Child(Base):
... def child_method(self):
... print('Це метод з класа Child')
... print(f'У екземпляра класа Child є атрибут {self.__attr=}')
...
>>> object_of_child = Child()
>>> object_of_child.method()
Це метод з класа Base
У екземпляра класа Base є атрибут self.__attr='Атрибут базового класа'
>>> object_of_child.child_method()
Це метод з класа Child
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in child_method
AttributeError: 'Child' object has no attribute '_Child__attr'
>>>
З метода method()
"видно" атрибут __attr
тому що вони знаходяться в одному класі Base
.
"Розгорнуте" ім'я атрибута буде _Base__attr
.
Якщо ж ми звертаємось до атрибута __attr
у методі child_method()
,
то тоді "розгорнуте" ім'я такого атрибута буде _Child__attr
.
А клас Child
не має свого власного приватного атрибута __attr
.