2016-12-17 57 views
0

我想创建两个A类和B类,其中B是A的一个轻微但显着的变体,然后创建第三个类C,它可以继承A或B并添加功能给他们。问题是,我如何告诉C根据我的偏好继承A或B?Python - 选择要继承的类

为了让事情更加清楚,假设我有这样的代码:

class A: 

    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

    def first(self): 
     return do_something(1) 

    def second(self): 
     return do_something(2) 

    def third(self): 
     return do_something(3) 

    def start(self): 
     self.first() 
     self.second() 
     self.third() 

class B(A): 

    def __init__(self, x, y, z): 
     super().__init__(x, y) 
     self.z = z 

    def second(self): 
     super().second() 
     do_stuff() 

    def third(self): 
     do_other_stuff() 

这是我使用的代码的一个非常简化的版本。特别地,A代表制造系统的模拟器,而B代表相同制造系统的模拟器,并修改主机床的行为。

现在,我想要的是添加代码来计算一些统计数据。它的作用是这样的:

class C(A): 

    def __init__(self, *args): 
     super().__init__(*args) 
     self.stat = 0 

    def second(self): 
     super().second() 
     self.stat += 1 

    def third(self): 
     super().third() 
     self.stat *= 3 

的问题是,C类作品完全相同的方式是否如果我继承了A类(如前面的列表)或B类(完全相同的代码,以作为第一行class C(B):

我该怎么做?或者我使用的是不可行的方法?我认为一个理想的解决方案是能够在初始化C时选择继承A或B的类。或者,也许,能够传递给C类继承的类。

我做了一些研究,并且我发现了聚合的可能性(我不知道befo重新),但我没有看到它真的有用。作为最后一点,请注意A类可能有多达20-30个方法,并且当我使用类CI时,希望类A(或B,取决于它继承的内容)与之前的C中添加的块完全一样工作。

P.S.我正在寻找一个可能优雅,没有代码沉重,“pythonic”的方式来做到这一点。我也非常期待在你认为可以做得更好的事情上提供建议。最后,我可以完全修改C类,但A类和B类必须保持(除了小的变化)相同。

+2

为什么你通过继承来做到这一点?为什么不使用* composition *,使'C'成为'A'或'B'中的一个封装器,然后在运行时传递给你需要的任何一个?你能否给出一个你想要实现的东西的抽象例子? – jonrsharpe

+0

我会尽力解释一下:我正在制作一个下一个事件模拟器,其中有N个AGV携带一部分由两个机床进行焊接。我有基本版本A(正如我所说,它可以有20-30个方法)和一个修改版本B,其中机床1的行为是不同的。我想要C做的是运行模拟器(A或B),但是当发生某些事件时(即当一个零件进入机床1开始计时,并且当相同的零件退出机床时,工具2停止计算时间,以获得平均制造时间) –

+0

我无法在Python中胜任,但在纯粹的OOP注释中:您是否考虑过装饰模式? https://en.m.wikipedia.org/wiki/Decorator_pattern – korolar

回答

1

您可以使用新款式及其方法分辨率订单

考虑这些定义:

class A(object): 
    def __init__(self, x): 
     pass 

    def foo(self): 
     print "A" 

class B(object): 
    def __init__(self, x, y): 
     pass 

    def foo(self): 
     print "B" 

你可以建立旨在将功能添加到AB一个mixin:

class Cmix(object): 
    def foo(self): 
     super(Cmix, self).foo() 
     print "mix" 

和来自CmixA(或B,分别)继承:

class CA(Cmix, A): 
    pass 

class CB(Cmix, B): 
    pass 

最后,您可以编写一个方便的功能基础上的参数个数CACB之间做出选择:

def C(*args): 
    if len(args) == 1: 
     return CA(*args) 
    else: 
     return CB(*args) 

现在我们有

C(1).foo() 
# A 
# mix 
C(1, 2).foo() 
# B 
# mix 

注意C是不是一个真正的类和你例如,在isinstance中不能将其用作第二个参数。