Наследование в ООП на Python. Урок 4

Методическая разработка урока
Элективный курс: Введение в объектно-ориентированное программирование на Python
Уровень: Программирование для начинающих

Одной из важнейших особенностей ООП является возможность наследования объектами атрибутов классов, а также наследование одними классами атрибутов других классов. На самом деле с наследованием мы уже сталкивались, когда создавали любой объект в Python: объекты наследуют атрибуты класса, хотя могут иметь и индивидуальные.

class Things:
     def __init__(self,n,t):
          self.namething = n
          self.total = t
 
th1 = Things("table", 5)
th2 = Things("computer", 7)
 
print (th1.namething,th1.total) # Вывод: table 5
print (th2.namething,th2.total) # Вывод: computer 7
 
th1.color = "green" # новое свойство объекта th1
 
print (th1.color) # Вывод: green
print (th2.color) # ОШИБКА: у объекта th2 нет свойства color!

Здесь оба объекта имеют свойства namething и total, однако только у первого объекта есть свойство color. Все просто: атрибуты класса наследуются объектами, созданными на его основе; однако атрибуты конкретного объекта не зависят от атрибутов других объектов и представляют собственное пространство имен объекта. Последнее позволяет объектам одного класса иметь различные значения атрибутов, а если потребуется и различный набор атрибутов.

Задание. Спишите код, выполните его с помощью интерпретатора Python. Как можно исправить код, чтобы не было ошибки? Исправьте.

На самом деле, наследование более широкое понятие, чем просто взаимосвязь между классами и объектами. Один класс может быть подклассом другого, дополняя его. Пояснить это можно проведя аналогию с реальным миром. Например, все столы имеют общие характерные черты («класс»), при этом они имеют разное назначение («подклассы»), хотя продолжают наследовать общие черты. В результате того, что есть такой механизм как наследование можно избежать избыточность кода, просто описав общие свойства и методы в надклассах.

По поводу терминологии. Классы, атрибуты которых наследуются другими классами, могут называть как надклассами так и суперклассами. Классы, которые наследуют атрибуты других классов, часто называют подклассами.

Класс, являющийся надклассом по отношению к одному классу, сам может быть подклассом по отношению к другому. Другими словами, может существовать целая цепочка наследования.

При обращении к атрибуту объекта (obj.prop) сначала просматривается на наличие этого атрибута сам объект, затем его класс, на основе которого он создан. Если в классе не будет найден атрибут, то его поиск продолжится в суперклассе, к которому относится класс.

Суперклассы класса указываются в скобках в заголовке инструкции class.

Рассмотрим такой пример:

class Table:
     def __init__(self,l,w,h):
          self.long = l
          self.width = w
          self.height = h
     def outing(self):
          print (self.long,self.width,self.height)
 
class Kitchen(Table):
     def howplaces(self,n):
          if n < 2:
               print ("It is not kitchen table")
          else:
               self.places = n
     def outplases(self):
          print (self.places)
 
t_room1 = Kitchen(2,1,0.5)
t_room1.outing()
t_room1.howplaces(5)
t_room1.outplases()
 
t_2 = Table(1,3,0.7)
t_2.outing()
t_2.howplaces(8) # ОШИБКА

Здесь создается два класса: Table и Kitchen. Второй является подклассом первого и наследует все его атрибуты (методы __init__ и outing). Далее создаются два объекта: t_room1 и t_2. Первый объект принадлежит к классу Kitchen и наследует атрибуты этого класса и его суперкласса. Второй объект принадлежит классу Table; к классу Kitchen он никакого отношения не имеет и поэтому не может обращаться к методам howplaces и outplases. В данном примере также можно увидеть, что объекты можно создавать как на основе классов так и суперклассов.

Задание. Расширьте программу, представленную выше, создав второй подкласс класса Table (например, Worker), содержащий пару методов, отличающихся от методов класса Kitchen().

Класс может иметь не один, а несколько суперклассов, которые перечисляются друг за другом в скобках в строке заголовка. Такое наследование называется множественным. Потребность во множественном наследовании возникает в случае, если объекты класса предполагают использование свойств и методов различных суперклассов.

Практическая работа

Напишите программу, где класс «геометрические фигуры» (figure) содержит свойство color с изначальным значением white и метод для изменения цвета фигуры, а его подклассы «овал» (oval) и «квадрат» (square) содержат методы __init__ для задания начальных размеров объектов при их создании.

Решение практической работы

class figure:
    color = "white"
    def changecolor(self, newcolor ):
        self.color = newcolor
 
class oval(figure):
    def __init__(self, r):
        self.luc = r
 
class square(figure):
    def __init__(self, a, b):
        self.dlina = a
        self.shirina = b
 
f = figure()
o = oval(15)
 
s = square(25, 4)
s.changecolor("green")
 
print(o.color, o.luc)
print(s.color, s.dlina, s.shirina)
 
мое прелиминарное решение практической работы :)

А есть смысл создавать обьект

А есть смысл создавать обьект класса фигуры? Мы то используем сам класс, а не обьект..

у квадрата одинаковые стороны

у квадрата одинаковые стороны

Просто изначяльно делал как

Просто изначяльно делал как квадрат, но по ходу переквалифицировал в прямоугольник :)) думаю, что это не столь сушественно.

Хорошая статья, но заметил

Хорошая статья, но заметил один недочет в названии класса:

class Kitchen(Table)

Судя по контексту мы создаем кухонный стол. Но если судить из названия класса - получается казус, так как мы наследуем целую кухню из стола =)

А вложеных классов может быть

А вложеных классов может быть бесконечное колличество)?

и как сделать например 3 класса?
например:

class klass1:
 class klass2(klass1):
  class klass3(???):

а что у трейтьего класса писать? писать class klas3(klass2): или все надклассы перечислить? class klass3(klass1,klass2):

Классы не вкладывают друг в

Классы не вкладывают друг в друга. Если klass1 является родителем для klass2, а klass2 родителем для klass3, то делают так:

...
 
def klass1:
    ...
 
def klass2(klass1):
    ...
 
def klass3(klass2):
    ...
 
...

Классы можно вкладывать друг

Классы можно вкладывать друг в друга, но это достаточно редко используется.