2016-07-04 21 views
0

我有一种情况,基类方法(Python中的__init__方法)做了很多工作。派生类覆盖__init__以简单地设置对象变量,然后委托给基类__init__。这工作正常,但现在我有一种情况。所有派生类都使用的基类方法除了一个

我有一些代码,非常适合在基类__init__,所有其他派生类除了一个(称之为A)需要使用。想象一下,如果基类__init__是这样的。

def __init__(self): 
    Action 1... 
    Action 2... 

现在,所有的派生类直接委托给这个。但是,A应该只有行动2在其__init__。现在这个观点很难看。我可以将Action 1和Action 2分成两个独立的函数,并让基类简单地调用Action2。然后大多数类会有他们的init这样的东西。

def __init__(self): 
    self.Action1() 
    Other init code... 
    super().__init__() 

A类,这将是

def __init__(self): 
    Some init code.... 
    super().__init__() 

但是你可以看到,有一段代码(调用self.Action1说)我在最派生类的重复。这不好。我不确定如何用最少的重复代码优雅地编写代码,并且需要一些关于如何去做的建议。

+1

典型的回答是_maybe A不是一个子类really_。考虑把A作为父类(在层次结构中更高,而不是更低) – Aganju

+0

在调用super()函数后''''''''''''你可以*撤销*''' )'''? – wwii

+0

@Aganju A是一个孩子。基类包含很多通用代码。子类实现了一些方法,使它们适合更大的框架。 –

回答

3

最明显的解决办法是使用默认参数:类

class Base: 
    def __init__(self, *, doAction1=True): 
     if doAction1: 
      Action 1... 
     Action 2... 

然后A你可以有:

def __init__(self): 
    Some init code.... 
    super().__init__(doAction1=False) 
+0

这看起来不错。我做了类似的事情,但不是参数,而是设置了基类所依赖的对象属性。 –

+0

除非另有建议,我接受这个答案。它看起来是最简单的做法。 –

0

类的属性,可以被覆盖 - 类似默认参数在__init__ 。 (Python v2.7类定义)。

class Foo(object): 
    action1 = True 
    action2 = True 
    def __init__(self): 
     if self.action1: 
     print('action1') 
     if self.action2: 
     print('action2') 

class Bar(Foo): 
    def __init__(self): 
     super(Bar, self).__init__() 
     print('Bar') 

class Baz(Foo): 
    action2 = False 
    def __init__(self): 
     super(Baz, self).__init__() 
     print('Baz') 
+0

这可行,但我认为@ ecatmur的解决方案更清洁。 –

+0

@NoufalIbrahim ...我upvoted ecatmur的解决方案,然后决定发布此*对比*。 – wwii

0

在做出设计决策时,往往值得考虑继承是否是正确的选择。仔细想想你是否真的需要继承,或者它是否会让事情变得复杂。

如果您决定实际上并不需要继承(您正在询问的当前问题可能会 - 也可能不是 - 这表明是这种情况),在诉诸继承之前,我建议您探索解决您的问题使用这样的事情:

def Action1(obj): 
    <do Action 1> 

def Action2(obj): 
    <do Action 2> 

def Action1and2(obj): 
    Action1(obj) 
    Action2(obj) 

class A: 
    def __init__(self): 
     Action2(self) 

class Other: 
    def __init__(self): 
     Action1and2(self) 

注意,对于Other对象,你仍然只有1行代码,而你完全避免继承。

如果您决定需要继承 - 也就是说,您创建的父对象不仅仅是通过某些操作(它们提供附加功能或访问数据)进行设置 - 您可以尝试解决您的问题使用组合物代替,如下所示:

class Action1Doer: 
    def __init__(self,obj): 
     <do Action 1> 

class Action2Doer: 
    def __init__(self,obj): 
     <do Action 2> 

class Action1and2Doer: 
    def __init__(self,obj): 
     self.a1 = Action1Doer(obj) 
     self.a2 = Action2Doer(obj) 

class A: 
    def __init__(self): 
     self.thing2 = Action2Doer(self) 

class Other: 
    def __init__(self): 
     self.thing1and2 = Action1and2Doer(self) 

请注意,同样,每个初始化方法中只有一行代码。顺便说一下,在编码世界中以这种方式去做事iscertainlynothingnew

你也可以的东西混合在一起:

def Action1(obj): 
    <do Action 1> 

class Action2Doer: 
    def __init__(self,obj): 
     <do Action 2> 

class Action1and2Doer: 
    def __init__(self,obj): 
     Action1(obj) 
     self.a2 = Action2Doer(obj) 

class A: 
    def __init__(self): 
     self.thing2 = Action2Doer(self) 

class Other: 
    def __init__(self): 
     self.thing2 = Action1and2Doer(self).a2 
+0

我想这是可能的,但“Action1and2Doer”听起来颇为人为。没有? –

+0

这基本上就是你已经使用的基类,对吧?我只是给它一个描述性的名字来解释清楚。 –

相关问题