假设以下类层次结构具有基类和一些从基类继承的通用案例类:
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):
优点:干净、明确
缺点:使用不同类的对象时,不同的方法签名可能会导致问题
选项 2:设置默认值并断言其未更改
class SpecialCase2(GeneralCase):
def f(self, a, b=PREDEFINED_VALUE):
assert b == PREDEFINED_VALUE
GeneralCase.f(self, a, PREDEFINED_VALUE)
专业人士:相同的签名
缺点:令人困惑的界面:“为什么我们有参数 b?如果我更改它会发生什么?”
您更喜欢哪种方法?为什么?
最佳答案
它根本不应该是一个子类型(参见里氏替换原则)。
GeneralCase
有一个属性,即:
There's a method
f
with two parameters ... which does yadda yadda yadda
此属性应该适用于 GeneralCase
的所有子类型(或者鸭子类型,任何应该像 GeneralCase
一样嘎嘎叫的东西,无论类关系如何)。如果它不成立,则处理此类对象的所有代码都必须了解它并围绕它编写代码。这是一个 Not Acceptable 负担,而且基本上没有必要。
如果该属性对于某些特殊情况不成立,则该特殊情况不应是子类型。它可能高度相关,但要么您需要更通用的 GeneralCase
,要么它实际上并不是 GeneralCase
的特殊情况。
如果你想重用代码,请使用 mixins。如果有代码可以在 GeneralCase
和 SpecialCase
上运行(例如,因为它不使用该方法),您可以定义一个更通用的接口(interface),但不包含该方法方法(可能是隐式的,我们不需要 interface
关键字),从而避免了上述麻烦。
关于python - 处理冗余函数参数的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9177322/