可以说我有
class Super():
def method1():
pass
class Sub(Super):
def method1(param1, param2, param3):
stuff
它是否正确?对method1的调用总是会转到子类吗?我的计划是让2个子类重写方法1,使用不同的参数
Python将允许这样做,但如果method1()
旨在从外部代码执行,那么你可能想重新考虑这一点,因为它违反了LSP,所以不会总是正常工作。
Python允许使用不同签名的“覆盖”方法,但即使它们的签名不同(即没有方法重载),也不能在同一个类中拥有两个具有相同名称的方法。在覆盖方法的情况下,如果要调用为对象定义的参数数量错误的方法,则会出现错误。请记住,Python的方法只是附加到对象的字典中的键值对,而“覆盖”相当于简单地替换最初从基类字典中复制的相同键的字典中的值。
通常情况下,您希望派生类方法具有除基类之外的其他参数。要在Python中执行此操作同时还要保留LSP,您可以使用以下技术:
class Base:
def hello(self, name, *kargs, **kwargs):
print("Hello", name)
class Derived(Base):
def hello(self, name, age=None, *kargs, **kwargs):
super(Derived, self).hello(name, age, *kargs, **kwargs)
print('Your age is ', age)
b = Base()
d = Derived()
b.hello('Alice')
b.hello('Bob', age=24)
d.hello('Rick')
d.hello('John', age=30)
以上将打印:
Hello Alice
Hello Bob
Hello Rick
Your age is None
Hello John
Your age is 30
在python中,所有类方法都是“虚拟的”(就C ++而言)。所以,对于你的代码,如果你想在超类中调用method1()
,它必须是:
class Super():
def method1(self):
pass
class Sub(Super):
def method1(self, param1, param2, param3):
super(Sub, self).method1() # a proxy object, see http://docs.python.org/library/functions.html#super
pass
方法签名很重要。你不能调用这样的方法:
sub = Sub()
sub.method1()
它会工作:
>>> class Foo(object):
... def Bar(self):
... print 'Foo'
... def Baz(self):
... self.Bar()
...
>>> class Foo2(Foo):
... def Bar(self):
... print 'Foo2'
...
>>> foo = Foo()
>>> foo.Baz()
Foo
>>>
>>> foo2 = Foo2()
>>> foo2.Baz()
Foo2
但是,通常不建议这样做。看看S.Lott的答案:Methods with the same name and different arguments are a code smell。
如果可以使用默认参数,你可以这样做:
>>> class Super():
... def method1(self):
... print("Super")
...
>>> class Sub(Super):
... def method1(self, param1="X"):
... super(Sub, self).method1()
... print("Sub" + param1)
...
>>> sup = Super()
>>> sub = Sub()
>>> sup.method1()
Super
>>> sub.method1()
Super
SubX
是。对“method1”的调用将始终转到子类。 Python中的方法签名只包含名称而不是参数列表。