0 знаков
67. Наследование и абстрактные суперклассы в Python
В предыдущем уроке в очередной раз поговорили про атрибуты и методы класса в Python. В этом уроке более детально разберемся с наследованием, способах связывания классов и абстрактными суперклассами.
Наследование
Весь смысл создания классов заключается в последующей возможности их наследования. Наследование в Python происходит на этапе уточнения при поиске в дереве определения атрибутов. При использовании точечной нотации объект.атрибут, в которой объект может являться объектом экземпляра или класса, интерпретатор Python осуществляет поиск в дереве пространств имен снизу вверх, начиная с этого объекта до тех пор, пока не будет обнаружен первый атрибут. Определения, находящиеся ниже в дереве пространств имен переопределяют те, что находятся выше. Так работает наследование в Python.
Вышеописанная модель наследования отлично работает из-за того, что сначала находятся имена в подклассах (в примере SubClass) до проверки суперклассов, за счет чего происходит переопределение атрибутов наследуемых суперклассов. Таким образом можно строить целые иерархии из классов и затем расширять их путем добавления новых подклассов, которые могут:
- замещать унаследованные атрибуты;
- предоставлять новые атрибуты;
- расширять методы суперклассов, с помощью их переопределения.
Далее пример расширения суперкласса:
class SuperClass:
def display(self):
print('Print SuperClass')
class SubClass(SuperClass):
def display(self):
print('Some sort of code')
SuperClass.display(self)
print('And some other code')
x = SubClass()
x.display() # => Some sort of code
# => Print SuperClass
# => And some other code Способы связывания классов
Рассмотрим другие способы связывания с суперклассом.
class SuperClass:
def method(self):
print('Print SuperClass')
def delegate(self):
self.action()
class Inheritor(SuperClass): # просто наследуем методы
pass
class Replacer(SuperClass): # полностью переопределяем метод
def method(self):
print('in Replacer.method')
class Extender(SuperClass): # расширяем поведение метода
def method(self):
print('starting Extender.method')
SuperClass.method(self)
print('ending Extender.method')
class Provider(SuperClass): # заполняем обязательный метод
def action(self):
print('in Provider.action')
if __name__ == '__main__':
for c in (Inheritor, Replacer, Extender):
print('
' + c.__name__ + ':')
c().method()
print('
Provider...')
x = Provider()
x.delegate() Вывод программы:
Inheritor...
Print SuperClass
Replacer...
in Replacer.method
Extender...
starting Extender.method
Print SuperClass
ending Extender.method
Provider...
in Provider.action В примере мы определили пять классов: SuperClass, Inheritor, Replacer, Extender и Provider.
SuperClass- определяет два метода. Методdelegate()ожидает наличие в подклассе методаaction().Inheritor- просто наследует все отSuperClass.Replacer- полностью переопределяет методmethod().Extender- добавляет новый функционал методуmethod().Provider- реализует методaction(), который ожидается методомdelegate()в суперклассе.
В Python все является объектами, поэтому мы создали кортеж (Inheritor, Replacer, Extender) из классов в цикле for и перебрали его. Далее поговорим на основе чего строятся объектно-ориентированные фреймворки в Python.
Абстрактные суперклассы
Абстрактность рассмотрим на примере класса Provider из предыдущего примера. Вот его фрагмент:
class SuperClass:
def method(self):
print('Print SuperClass')
def delegate(self):
self.action()
class Provider(SuperClass):
def action(self):
print('in Provider.action')
if __name__ == '__main__':
print('
Provider...')
x = Provider()
x.delegate() Что происходит с позиции наследования когда мы вызываем метод delegate() через экземпляр Provider? Сначала интерпретатор Python находит метод delegate() в суперклассе SuperClass. Экземпляр x передается в аргументе self как мы говорили ранее. Далее внутри метода delegate() суперкласса метод self.action() инициирует поиск в self и выше. Так как метод self ссылается на экземпляр класса Provider, то метод action() обнаруживается в подклассе Provider. Таким образом обычно строятся объекно-ориентированные фреймворки.
ОпределениеАбстрактный класс - класс, который ожидает от своих подклассов передачу частей своего поведения через наследование.
Чтобы сделать требования к подклассам более очевидными, разработчики используют оператор assert или добавляют генерацию исключения с помощью оператора raise.
class SuperClass:
def method(self):
print('Print SuperClass')
def delegate(self):
self.action()
def action(self):
assert False, 'Метод action должен быть определен!'
class Provider(SuperClass):
pass
# def action(self):
# print('in Provider.action')
if __name__ == '__main__':
x = Provider()
x.delegate() # => AssertionError: Метод action должен быть определен! Сделать заглушку на метод с помощью оператора raise можно следующим образом:
class SuperClass:
# ...
def action(self):
raise NotImplementedError('Метод action должен быть определен!') В этом уроке более детально разобрались с наследованием, способах связывания классов и абстрактными суперклассами. В следующем уроке поговорим про пространство имен и строки документации.
Тест
Похожие уроки Codebra
Подписывайся на наш Telegram-канал!
Новости, полезный материал,
программирование и ИБ
Подписывайся на наш Telegram-канал!
Новости, полезный материал,
программирование и ИБ