2017-07-05 146 views
1

Python 3.6Python继承结构

我刚刚发现自己编程这种类型的继承结构(下面)。子类正在调用对象的方法和属性的父类has

在我的使用情况下,我将在class A代码,否则将丑class B

几乎像一个反向继承来电或东西,这似乎不是个好主意......(Pycharm似乎并不喜欢它)

有人请解释什么是最好的做法在这种情况下?

谢谢!

class A(object): 

    def call_class_c_method(self): 
     self.class_c.do_something(self) 

class B(A): 

    def __init__(self, class_c): 
     self.class_c = class_c 
     self.begin_task() 

    def begin_task(self): 
     self.call_class_c_method() 

class C(object): 

    def do_something(self): 
     print("I'm doing something super() useful") 

a = A 
c = C 
b = B(c) 

输出:

I'm doing something super() useful 
+0

为什么你有类C,当你可以把do_something直接放在类A中? – Kishan

+0

“在我的使用情况下,我把在A类代码,否则将在B类丑” –

+0

有什么理由会做这样的事?这是一个反模式的定义。你正在调用类B的 – zwer

回答

2

没有什么错在A类实现一个小功能,并使用它作为一个基类B。这种模式在Python中被称为mixin。如果您想重复使用A或希望从许多此类可选功能组成B,这是非常有意义的。

但确保你的mixin本身是完整的!

class A的原始实现依赖于派生类来设置成员变量。这是一个特别丑陋的方法。更好地界定class_cA成员需要用到它:

class A(object): 

    def __init__(self, class_c): 
     self.class_c = class_c 

    def call_class_c_method(self): 
     self.class_c.do_something() 

class B(A): 

    def __init__(self, class_c): 
     super().__init__(class_c) 
     self.begin_task() 

    def begin_task(self): 
     self.call_class_c_method() 

class C(object): 
    def do_something(self): 
     print("I'm doing something super() useful") 

c = C() 
b = B(c) 
+0

干杯,我可以看到这显然更好。 –

1

我发现,减少这样的情况下,事情抽象字母就更难我推理的相互作用是否有意义。 实际上,你问的是一个类(A)是否合理依赖于符合给定接口的成员(C)。答案是,有些情况下很明显。 作为一个例子,考虑Web应用程序设计中的模型 - 视图 - 控制器模式。 你可能会碰到这样的

class Controller: 

    def get(self, request) 
     return self.view.render(self, request) 

或相似。然后在其他地方你会有一些代码发现视图并在控制器中填充self.view。典型的例子包括一些路由查找或包括具有与控制器相关的特定视图。虽然不是Python,但Rails web框架完成了很多工作。

当我们有具体的例子时,理解抽象是否有意义要容易得多。

在上面的例子中,控制器接口依赖于有权访问视图接口的某个实例来完成它的工作。控制器实例封装实现该视图接口的实例。

这里有一些评估这种设计时要考虑:

  • 你能清楚地说明每个接口/类的边界?也就是说,你能解释一下管理者的工作是什么以及视图的工作是什么?

  • 请问您决定封装的情况下同意那些范围?

  • 执行接口和类范围似乎是合理的,当你想想未来的可扩展性和减少有关的代码更改范围有多大?

+0

是的,你解释了我想要达到的目标,这样做更有意义。我会接受kazemakase的答案,因为它解释了如何实现这样的事情。虽然,这篇文章给了我一些东西在我自己的时间里带走和理解。谢谢! –