方法默认参数可以被覆盖,看起来是这样的:
>>> 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
这怎么可能?这被认为是不好的风格吗?
方法默认参数可以被覆盖,看起来是这样的:
>>> 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
您可以随意更改重写方法的签名。Python不会介意:
class Base:
def foo(self, x, y):
pass
class Deriv(Base):
def foo(self, blah=100):
pass
但如果你问
这是否被认为是不好的风格?
答案是肯定的,因为它违反了重要的Liskov替换原则:
如果Deriv扩展自Base,则必须能够替换所有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):
这是绝对允许的,但可能会让您的调用者感到非常困惑。他们不应该能够像使用 B
对象一样使用 D
对象吗?