Lets say I have
class Super():
def method1():
pass
class Sub(Super):
def method1(param1, param2, param3):
stuff
Is this correct? Will calls to method1 always go to the sub class? My plan is to have 2 sub classes each override method1 with different params
Python will allow this, but if method1() is intended to be executed from external code then you may want to reconsider this, as it violates LSP and so won't always work properly.
Python permits "overriding" methods with different signatures but you can never have two methods with the same name in the same class even if their signatures are different (i.e. no method overloading). In case of overriding method, if you are calling methods with wrong number of parameters defined for the object, you will get an error. Remember, Python's methods are just key-value pairs in dictionary attached to object and "overriding" amounts to simply replacing value in that dictionary copied initially from base class dictionary for the same key.
There are frequently scenarios where you want derived class method have additional parameters than base class. To do this in Python while also preserving LSP, you can use following technique:
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)
Above will print:
Hello Alice
Hello Bob
Hello Rick
Your age is None
Hello John
Your age is 30
In python, all class methods are "virtual" (in terms of C++). So, in the case of your code, if you'd like to call method1() in super class, it has to be:
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
And the method signature does matter. You can't call a method like this:
sub = Sub()
sub.method1()
It will work:
>>> 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
However, this isn't generally recommended. Take a look at S.Lott's answer: Methods with the same name and different arguments are a code smell.
You could do something like this if it's ok to use default arguments:
>>> 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
Yes. Calls to "method1" will always go to the subclass. Method signature in Python only consist of the name and not the argument list.
来源:https://stackoverflow.com/questions/6034662/python-method-overriding-does-signature-matter