Ответ 1
Python разрешит это, но если method1()
предназначен для выполнения из внешнего кода, вам может потребоваться пересмотреть это, поскольку он нарушает LSP и поэтому выиграл Всегда работайте правильно.
Скажем, у меня
class Super():
def method1():
pass
class Sub(Super):
def method1(param1, param2, param3):
stuff
Это правильно? Будет ли вызов метода1 всегда переходить к подклассу? Мой план состоит в том, чтобы иметь 2 под класса каждый метод переопределения1 с разными параметрами
Python разрешит это, но если method1()
предназначен для выполнения из внешнего кода, вам может потребоваться пересмотреть это, поскольку он нарушает LSP и поэтому выиграл Всегда работайте правильно.
В python все методы класса являются "виртуальными" (с точки зрения С++). Итак, в случае вашего кода, если вы хотите называть 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 ответ: Методы с тем же именем и разными аргументами являются запахом кода.
Вы можете сделать что-то подобное, если использовать аргументы по умолчанию:
>>> 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
Python разрешает "переопределять" методы с разными сигнатурами, но вы никогда не можете иметь два метода с одинаковыми именами в одном классе, если их сигнатуры различны (т.е. нет перегрузки методов). В случае переопределения метода, Python выдаст ошибку, если вы вызываете методы с неправильными параметрами, которые не определены в объекте. Помните, что методы Python - это просто пары "ключ-значение" в словаре, присоединенном к объекту, и "переопределение" равнозначно простой замене значения в этом словаре, изначально скопированного из словаря базового класса для того же ключа.
Часто существуют сценарии, в которых вы хотите, чтобы метод производного класса имел дополнительные параметры, чем базовый класс. Чтобы сделать это в Python, сохраняя при этом LSP, вы можете использовать следующую технику:
class Base():
def hello(self, name, **kwargs):
print("Hello", name)
class Derived(Base):
def hello(self, name, **kwargs):
super(Derived, self).hello(name, **kwargs)
print('Your age is ', kwargs.get('age', None))
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
Да. Звонки на "method1" всегда будут попадать в подкласс. Подпись метода в Python состоит только из имени, а не списка аргументов.