Module (23%)
Section (63%)

Объектный подход: стек с нуля (продолжение)

Теперь давайте пойдем немного дальше. Давайте добавим новый класс для обработки стеков.

Новый класс должен иметь возможность оценивать сумму всех элементов, хранящихся в данный момент в стеке.

Мы не хотим изменять ранее определенный стек. Он уже достаточно хорош в своих приложениях, и мы не хотим, чтобы это каким-либо образом изменилось. Мы хотим новый стек с новыми возможностями. Другими словами, мы хотим создать подкласс уже существующего класса Stack.

Первый шаг прост: просто определите новый подкласс, указывающий на класс, который будет использоваться в качестве суперкласса.

Вот как это выглядит:

class AddingStack(Stack): pass

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

Это то, что мы хотим от нового стека:

  • мы хотим, чтобы метод push не только помещал значение в стек, но и добавлял значение в переменную sum;
  • мы хотим, чтобы функция pop не только извлекала значение из стека, но и вычитала значение из переменной sum.

Во-первых, давайте добавим новую переменную в класс. Это будет cкрытая переменная, такая как список стеков. Мы не хотим, чтобы кто-либо манипулировал значением sum.

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

class AddingStack(Stack): def __init__(self): Stack.__init__(self) self.__sum = 0

Вторая строка тела конструктора создает свойство с именем __sum - оно будет хранить сумму всех значений стека.

Но строка перед этим выглядит иначе. Что она делает? Это действительно необходимо? Да, это так.

 

В отличие от многих других языков, Python заставляет Вас явно вызывать конструктор суперкласса. Пропуск этой точки будет иметь пагубные последствия - объект будет лишен списка __stackList. Такой стек не будет работать должным образом.

Это единственный раз, когда Вы можете явно вызывать любой из доступных конструкторов - это можно сделать внутри конструктора суперкласса.

 

Обратите внимание на синтаксис:

  • Вы указываете имя суперкласса (это класс, конструктор которого Вы хотите запустить);
  • Вы ставите точку (.) после него;
  • Вы указываете имя конструктора;
  • Вы должны указать на объект (экземпляр класса), который должен быть инициализирован конструктором - вот почему Вы должны указать аргумент и использовать переменную self здесь; примечание: вызов любого метода (включая конструкторы) извне класса никогда не требует, чтобы Вы поместили аргумент self в список аргументов - вызов метода изнутри Класс требует явного использования аргумента self, и он должен быть первым в списке.
 

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



Code

class Stack:
def __init__(self):
self.__stack_list = []

def push(self, val):
self.__stack_list.append(val)

def pop(self):
val = self.__stack_list[-1]
del self.__stack_list[-1]
return val


class AddingStack(Stack):
def __init__(self):
Stack.__init__(self)
self.__sum = 0
{{ dockerServerErrorMsg }} ×
{{ errorMsg }} ×
{{ successMsg }} ×