6

方法默认参数显然可以被覆盖:

>>> class B:
...     def meth(self, r=True): print r
>>> class D(B):
...     def meth(self, r=False): print r
... D().meth()
False
>>> B().meth()
True

这怎么可能 ?它被认为是不好的风格吗?

4

3 回答 3

12

您可以以任意方式更改覆盖方法的签名。Python 不在乎:

class Base:
    def foo(self, x, y):
        pass

class Deriv(Base):
    def foo(self, blah=100):
        pass

但如果你问

它被认为是不好的风格吗?

答案是肯定的,因为它违反了重要的Liskov 替换原则

如果 Deriv 扩展 Base,您必须能够用 Deriv 替换所有出现的 Base 而不会破坏您的程序。

换句话说,派生类必须履行基类提供的所有契约。特别是,被覆盖的方法必须具有相同的签名和相似的语义。由于 Python 对此没有帮助,因此您必须在 IDE(此处为 Intellij IDEA)的帮助下手动控制:

在此处输入图像描述

要回答您关于覆盖默认参数的具体问题,我想答案是“取决于”。如果参数是一个仅在内部使用并且不影响对象的可观察行为的选项,那么更改它并没有错:

class Buffer:
    def __init__(self, init_size=16):

class BigBuffer(Buffer):
    def __init__(self, init_size=1024):

另一方面,如果参数严重影响语义,它是合同的一部分,不应该被覆盖。例如,这段代码会令人困惑

class Test:
    def test_equal(self, a, b, fail_if_equal=False):

class MyTest(Test):
    def test_equal(self, a, b, fail_if_equal=True):
于 2014-11-22T14:23:41.503 回答
0

这怎么可能 ?
机制是什么?

您只需覆盖派生类中的整个方法。

于 2014-11-22T14:12:36.440 回答
0

这绝对是允许的,但可能会让您的来电者感到非常困惑。他们不应该能够像使用D对象一样使用B对象吗?

于 2014-11-22T13:37:54.693 回答