Скрытие методов суперкласса от пользователя дочернего класса

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

Например, предположим, что у меня есть реализация связанного списка. Затем я основываю реализацию стека ADT на нем, наследуя (не уверен, что это хороший дизайн...). Следовательно, я хочу «скрыть» методы класса LinkedList от пользователя класса Stack.

Связанный список:

class LinkedList(object):
    class Node(object):
        """
        Inner class of LinkedList. Contains a blueprint for a node of the LinkedList
        """
        def __init__(self, v, n=None):
            """
            Initializes a List node with payload v and link n
            """
            self.value=v
            self.next=n

    def __init__(self):
        """
        Initializes a LinkedList and sets list head to None
        """
        self.head=None

    def insert(self, v):
        """
        Adds an item with payload v to beginning of the list
        in O(1) time 
        """
        Node = self.Node(v, self.head)
        self.head = Node
        print("Added item: ", Node.value, "self.head: ", self.head.value)

    def size(self):
        """
        Returns the current size of the list. O(n), linear time
        """
        current = self.head
        count = 0
        while current:
            count += 1
            current = current.next
        return count

    def search(self, v):
        """
        Searches the list for a node with payload v. Returns the node object or None if not found. Time complexity is O(n) in worst case.
        """
        current = self.head
        found = False
        while current and not found:
            if current.value == v:
                found = True
            else:
                current = current.next
        if not current:
            return None
        return current

    def delete(self, v):
        """
        Searches the list for a node with payload v. Returns the node object or None if not found. Time complexity is O(n) in worst case.
        """
        current = self.head
        previous = None
        found = False
        while current and not found:
            if current.value == v:
                found = True
            else:
                previous = current
                current = current.next
        # nothing found, return None
        if not current:
            return None
        # the case where first item is being deleted
        if not previous:
            self.head = current.next
        # item from inside of the list is being deleted    
        else:
            previous.next = current.next

        return current

    def __str__(self):
        """
        Prints the current list in the form of a Python list            
        """
        current = self.head
        toPrint = []
        while current != None:
            toPrint.append(current.value)
            current = current.next
        return str(toPrint)

Куча:

from PythonADT.lists import LinkedList

class Stack(LinkedList):
    def __init__(self):
        LinkedList.__init__(self)

person MadPhysicist    schedule 02.03.2017    source источник
comment
Нет, это, вероятно, не лучший дизайн. Если вы не хотите предоставлять один и тот же интерфейс, создавайте не наследуйте.   -  person jonrsharpe    schedule 02.03.2017
comment
Если Stack не собирается выполнять обещания интерфейса, которые дает LinkedList, он не должен расширять LinkedList.   -  person user2357112 supports Monica    schedule 03.03.2017
comment
Как описано в официальной документации Python 9.6. Частные переменные, можно защитить метод внутри class. Просто объявите эту функцию, назвав ее, начиная с двойного подчеркивания (например: __private_search(self):).   -  person J. Piquard    schedule 03.03.2017
comment
@jonrsharpe ты предлагаешь что-то подобное? class Stack(object): def __init__(self): self.items = LinkedList(), после чего я приступил к реализации Stack ADT, но за кулисами использовал LinkedList.   -  person MadPhysicist    schedule 03.03.2017
comment
Да, именно так. Или self._items, чтобы указать, что сам список также не является частью открытого интерфейса стека.   -  person jonrsharpe    schedule 03.03.2017
comment
@jonrsharpe Это пример композиции? То есть когда класс создает экземпляр другого класса для своего использования?   -  person MadPhysicist    schedule 04.03.2017
comment
@jonrsharpe Я также использовал указанную выше строку как self.__items = LinkedList(), чтобы скрыть поле items от просмотра пользователем класса Stack. Так это делается в Python?   -  person MadPhysicist    schedule 04.03.2017


Ответы (1)


Вот официальный синтаксис для объявления защищенного и закрытого методов в классе.

  1. Защищенный метод, объявленный в родительском классе, можно будет вызывать из дочернего класса.
  2. Приватный метод, объявленный в родительском классе, будет скрыт от дочернего класса.

Поднятое исключение:

# AttributeError: '<ChildClass>' object has no attribute '__<private_function>'

Шаг 1 – объявите как закрытый, так и защищенный метод в файле class Parent.

class Parent(object):
    # a private method starts by 2 '_'
    def __parent_private(self):
        print('inside __parent_private()')

    # a protected method starts by 1 '_'
    def _parent_protected(self):
        print('inside _parent_protected()')

Шаг 2 — объявить функцию для вызова обеих функций из файла class Child.

class Child(Parent):

    def call__parent_private(self):
        self.__parent_private()

    def call_parent_protected(self):
        self._parent_protected()

Шаг 3. Создайте экземпляр class Child для проверки частного и защищенного доступа.

myChild = Child()

Проверка защищенного метода из класса Child ==> Доступ разрешен

# internal access of protected method
myChild.call_parent_protected()

Вывод: "inside _parent_protected()"

# direct access of protected method
myChild._parent_protected()

Вывод: "inside _parent_protected()"

Проверка приватного метода из класса Child ==> Доступ запрещен

# internal access of private method
myChild.call__parent_private()

Ошибка: "AttributeError: 'Child' object has no attribute '_Child__parent_private'"

# direct access of private method
myChild.__parent_private()

Ошибка: "AttributeError: 'Child' object has no attribute '__parent_private'"

person J. Piquard    schedule 02.03.2017