2016-12-09 1 views
2

Я ищу совет о том, как построить проект, над которым я буду работать.Композиционное наследование в python

У меня есть базовый класс, с некоторыми методами.

class Base(object): 
    def method1(self): 
    # some code 
    def method2(self): 
    # some code 
    def method3(self): 
    # some code 
... and some other methods 

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

У меня есть несколько требований, которые могут быть активированы или нет. В зависимости от заданной конфигурации. То есть Я хотел бы иметь возможность переопределять методы method1(), method2(), method3() или любую их комбинацию.

Одним из вариантов является создание нескольких наследующих классов.

class Child1(Base): 
    def method1(self): 
    # some code 

class Child2(Base): 
    def method2(self): 
    # some code 

class Child3(Base): 
    def method3(self): 
    # some code 

А затем, возможно, используйте множественное наследование, чтобы применить любой их состав. Однако этот подход не будет хорошо масштабироваться для покрытия всех возможных комбинаций .. (например, что произойдет, если у меня будет Child4()?)

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

class Child(Base): 
    def method1(self): 
    if not self.override1: 
     # call super 
    else: 
     # some code 

    def method2(self): 
    if not self.override2: 
     # call super 
    else: 
     # some code 

    def method3(self): 
    if not self.override3: 
     # call super 
    else: 
     # some code 

Я больше в пользу на эту альтернативу, но я чувствую, что должен быть лучше OO подход для этого.

Любые мысли или предложения?

Большое спасибо

PS: Я вынужден Python 2.7, а так как я планирую поделиться код, я предпочел бы иметь решение, которое легко понять, в среднем питона программиста (и не только передовые программисты).

+0

Вопрос, вероятно, слишком широк.Если степень модификации заставляет экземпляр вести себя значительно иначе, чем экземпляры без этой модификации, - до такой степени, что его можно считать другой вещью, хотя и связанной, то я бы сказал, что ваше последнее решение неверно, и вам, вероятно, понадобится множественный подход наследования/микрин. – wwii

ответ

2

Мне нравится первый выбор это кажется управляемым, без дублирования кода:

class A: 
    def one(self): 
     return 'one |' 
    def two(self): 
     return 'two |' 
    def three(self): 
     return 'three |' 
    def four(self): 
     return 'four |' 

class B(A): 
    def one(self): 
     return 'one foo |' 

class C(A): 
    def two(self): 
     return 'two foo |' 

class D(A): 
    def three(self): 
     return 'three foo |' 

class BC(B, C): 
    pass 
class CD(C, D): 
    pass 
class BD(B, D): 
    pass 

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

>>> bc = BC() 
>>> isinstance(bc, A) 
True 
>>> isinstance(bc, CD) 
False 
>>> isinstance(bc, BC) 
True 

И вы обнаружите, что Вы забыли что-то и легко добавить:

#oops now I need this 
class X(A): 
    def four(self): 
     pass 
# and this $#%^!* 
class B1(A): 
    def one(self): 
     return 'one bar |' 
1

Хранить в помните, что определения классов выполняются кодом. Вы можете условно определить или проигнорировать метод в своем дочернем классе:

class Child(Base): 
    if something: 
     def method1(self, etc): 
      pass 

Вот пример. Обратите внимание, что установка состояние должно произойти перед определением класса - это не динамический параметр:

#!python3 
import sys 

special = False 

if "--special" in sys.argv: 
    special = True 


class Base: 
    def method1(self): 
     print("Base method1") 


    def method2(self): 
     print("Base method2") 

class Child(Base): 
    def method3(self): 
     print("Child method3") 

    if special: 
     def method1(self): 
      print("Child method1") 


ch = Child() 
ch.method1() 
ch.method2() 
ch.method3() 

Выход:

$ python test.py --special 
Child method1 
Base method2 
Child method3 

$ python test.py 
Base method1 
Base method2 
Child method3 
+0

Ницца! Значит, я могу только основывать условие на sys.argv? Или есть другая альтернатива? – yuval

+1

Есть определенные альтернативы. Я основывал условие на argv, потому что это демо. Вы можете настроить его на любое другое условие, которое вы хотите, до тех пор, пока вы не сможете завершить значение до того, как вы определите класс. В этом случае вы можете поместить определение класса внутри функции и вызвать его для возврата класса ... –

Смежные вопросы