Python Method overriding, does signature matter?

穿精又带淫゛_ 提交于 2019-11-28 21:02:47

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

Play with this code

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() 
quasistoic

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!