处理冗余函数参数的正确方法

时间:2012-02-07 13:43:42

标签: python inheritance

假设以下类层次结构具有基类和一些继承自基类的通用案例类:

class BaseClass:
    def f(self, a, b):
        #do something
        pass

class GeneralCase(BaseClass):
    def f(self, a, b):
        BaseClass.f(self, a, b)
        #do something else

现在,假设我们有一个特殊情况,其中(其中)函数f的一个参数是预定且不变的。一 实现这一点的方法是从参数列表中删除此参数,如下所示:

class SpecialCase1(GeneralCase):
    def f(self, a):

Pro:干净,明确

Con's:当使用不同类的对象时,不同的方法签名可能会导致问题

选项2:设置默认值并声明它未被更改

class SpecialCase2(GeneralCase):
    def f(self, a, b=PREDEFINED_VALUE):
        assert b == PREDEFINED_VALUE
        GeneralCase.f(self, a, PREDEFINED_VALUE)

Pro:相同的签名

Con:令人困惑的界面:“为什么我们有参数b?如果我改变它会发生什么?”

你会采取什么方法?为什么?

2 个答案:

答案 0 :(得分:3)

它根本不应该是一个子类型(参见Liskov Substitution Principle)。

GeneralCase的属性,即:

  

有一个方法f有两个参数...... yadda yadda yadda

此属性应该适用于GeneralCase的所有子类型(或者是鸭子类型,任何应该像GeneralCase一样嘎嘎叫的东西,无论类关系如何)。如果它不成立,那么处理这些对象的所有代码都必须知道它并围绕它进行编码。这是一个不可接受的负担,而且基本上没必要。

如果某个特殊情况下该属性不正确,则该特殊情况不应为子类型。它可能是高度相关的,但要么您需要更一般的GeneralCase,要么它不是GeneralCase的特殊情况。

如果您想要重用代码,请使用mixins。如果有代码可以在GeneralCaseSpecialCase上运行(例如因为它不使用该方法),您可以定义一个不包含该方法的更通用的接口(可能含蓄地,我们不需要interface关键字),从而避免上述麻烦。

答案 1 :(得分:0)

怎么样:

class SpecialCase2(GeneralCase):
    def f(self, a, b):
        GeneralCase.f(self, a, PREDEFINED_VALUE)

这样特殊情况2根本不使用b,界面保持不变。