Python 3.6
我发现自己编写了这种类型的继承结构(如下所示)。子类调用父对象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 :(得分:2)
在类A
中实现一个小功能并将其用作B
的基类没有任何问题。这种模式在Python中称为mixin。如果您想重新使用A
或想要从许多此类可选功能中撰写B
,这很有意义。
但请确保您的mixin本身已完整!
class A
的原始实现取决于派生类来设置成员变量。这是一种特别难看的方法。最好将class_c
定义为使用它的A
成员:
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)
答案 1 :(得分:1)
我发现在这种情况下将事物简化为抽象字母会让我更难以推断交互是否有意义。
实际上,您要问一个类(A
)依赖于符合给定接口(C
)的成员是否合理。答案是,有些情况显然会这样。
例如,考虑Web应用程序设计中的模型 - 视图 - 控制器模式。
你可能会有像
class Controller:
def get(self, request)
return self.view.render(self, request)
或类似的。然后在其他地方,你有一些代码可以找到视图并在控制器中填充self.view
。这样做的典型示例包括一些路由查找或包括具有与控制器相关联的特定视图。虽然不是Python,但Rails Web框架可以做很多事情。
当我们有具体的例子时,可以更容易地推断出抽象是否有意义。
在上面的示例中,控制器接口依赖于访问视图接口的某个实例来完成其工作。控制器实例封装了实现该视图接口的实例。
在评估此类设计时,需要考虑以下事项:
您能清楚地阐明每个界面/类的界限吗?也就是说,你能解释一下控制器的工作是什么以及观点的工作是什么吗?
您对封装实例的决定是否与这些范围一致?
在考虑未来的可扩展性和最小化代码更改范围时,接口和类作用域是否合理?