Вопрос по питону и классам - PullRequest
1 голос
/ 19 апреля 2011

У меня есть базовый класс и несколько производных от Python:

class Base:
   def Foo(self):
      pass

# First derived class
class Der1(Base):
   def OwnFoo(self):
      # Do something 1
   def OwnFoo2(self):
      # Do something 2

   def Foo(self):
      # Do something 3

# Second derived class
class Der2(Base):
   def OwnFoo(self):
      # Do something 1
   def OwnFoo2(self):
      # Do something 2

   def Foo(self):
      # Do something 3

Вопрос:

У меня есть некоторый предопределенный код в Der1.Почти все функции из Der2 делают то же самое.Как я могу написать это с меньшим количеством кода?

Я не могу добавить этот код к родителю.Родительский класс не следует трогать.

Например, Der2.OwnFoo делает то же самое, что и Der1.OwnFoo, возможно, в python есть какая-то конструкция, которая просто вызывает OwnFoo из первого класса и не пишет этот кодснова?


Я не могу изменить родителя Der1 и Der2!Это должно быть Base.

Ответы [ 5 ]

3 голосов
/ 19 апреля 2011

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

# Common code goes in this new class
class DerHelper:
    def __init__(self, parent):
        self._parent = parent
    def OwnFoo(self):
        print 'Do something 1', self._parent
    def OwnFoo2(self):
        print 'Do something 2', self._parent
    def Foo(self):
        print 'Do something 3', self._parent

# First derived class
class Der1(Base):
    def __init__(self):
        # include helper class by composition
        self._helper = DerHelper('Der1')
    def OwnFoo(self):
        self._helper.OwnFoo()
    def OwnFoo2(self):
        self._helper.OwnFoo2()
    def Foo(self):
        self._helper.Foo()

# Second derived class
class Der2(Base):
    def __init__(self):
        # include helper class by composition
        self._helper = DerHelper('Der2')
    def OwnFoo(self):
        self._helper.OwnFoo()
    def OwnFoo2(self):
        self._helper.OwnFoo2()
    def Foo(self):
        self._helper.Foo()

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

Использование:

d = Der1()
d.OwnFoo()
d.OwnFoo2()
d.Foo()

d = Der2()
d.OwnFoo()
d.OwnFoo2()
d.Foo()

Выход:

Do something 1 Der1
Do something 2 Der1
Do something 3 Der1
Do something 1 Der2
Do something 2 Der2
Do something 3 Der2
2 голосов
/ 19 апреля 2011

Сделайте Der2 подклассом Der1, и все готово.

class Base:
   def Foo(self):
      pass

# First derived class
class Der1(Base):
   def OwnFoo(self):
      # Do something 1
   def OwnFoo2(self):
      # Do something 2

   def Foo(self):
      # Do something 3

# Second derived class (subclasses Der1)
class Der2(Der1):
   pass

Любое поведение в пределах Der2, которое вы хотели бы специализировать, может быть добавлено в определение класса.Если вы создадите новый метод с тем же именем в Der2 (например, Der2.OwnFoo()), он перегрузит метод по умолчанию, унаследованный от Der1.

РЕДАКТИРОВАТЬ: Если вы не можете изменить родителя, поместите все поведение, которое вы хотите унаследовать, в базовый класс, имея в виду, что вы можете перегрузить или настроить любой из методов в подклассах.

В коде:

# Base class
class Base:
    def Foo1(self):
        # Do something 1
    def Foo2(self):
        # Do something 2
    def Foo(self):
        # Do something 3

# First derived class, inherits everything from Base
class Der1(Base):
    pass

# Second derived class
class Der2(Base):
    pass  

Существует "хитрость", которую вы можете сделать, чтобы вызвать оригинальный метод, унаследованный от родительского объекта, захватить возвращаемое значение и затем настроить поведение.Это будет работать только в том случае, если метод на самом деле возвращает значение, и может быть опасно, если метод манипулирует атрибутами в классе, если это не то, что вы хотите и ожидаете.

В коде:

# Second derived class, with customized methods
class Der2(Base):
    # Anything that is not explicitly define is inherited from parent
    # as-is.

    def Foo(self):
        # My Foo() overloads Base.Foo() inherited from parent class. 
        # Do something "special" 3

    def Foo1(self):
        # Calls parent Base.Foo1() and then manipulates return data.
        base_output = Base.Foo1(self)
        # Do something "special" 1 with 'base_output'
1 голос
/ 19 апреля 2011

Если Der1 и Der2 совместно используют много кода, то вы должны поместить его в суперкласс; поскольку к Base нельзя прикоснуться, введите класс между:

class Der(Base):
    def OwnFoo(self):
        ...

class Der1(Der):
    ...

class Der2(Der):
    ...

(В зависимости от иерархии вашего класса опция «получить Der2 из Der1», которую рекомендуют другие, также может быть действительной.)

1 голос
/ 19 апреля 2011

Это домашняя работа?

Посмотрите на первую строку Der2:

class Der2(Base):

Что говорит о том, что является его родителем (например, класс, который он наследует и наследует методы и атрибуты)? Как ты мог изменить это?

0 голосов
/ 19 апреля 2011

Как насчет создания Der2 подкласса Der1?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...