Method overloading of Callable parameters #10658
|
Hi, please help me understand the following: from collections.abc import Callable
class CallableClass:
def __call__(self) -> None:
return
class Parent:
def test(self, callable: Callable[..., None]) -> None:
return
Parent().test(CallableClass()) # works
class Child(Parent):
# error: Method "test" overrides class "Parent" in an incompatible manner
def test(self, callable: CallableClass) -> None:
returnThank you in advance! Edit: From my understanding, Pyright does indeed infer that |
Replies: 1 comment 1 reply
|
The problem is that the parent class accepts any object that is callable and can be passed any list of arguments. By the Liskov Substitution Principle (LSP), any subclass must also accept an object that is callable and can be passed any list of arguments. However, the child class in this case is much more restrictive. It requires that the Why is this a problem? Consider the following: class Child(Parent):
def test(self, callable: CallableClass) -> None:
assert isinstance(callable, CallableClass)
def test_parent(p: Parent, c: Callable[..., None]):
p.test(c)
test_parent(Child(), lambda: None)It's important to keep in mind that method parameters are implicitly contravariant. That means it's OK for a child to override a parameter if the type of that parameter is a supertype of the same parameter in the parent's method. For example: class Parent:
def test(self, o: float) -> None: ...
class Child(Parent):
def test(self, o: int) -> None: ... # Error: int is a subtype of float, not a supertypeIn your code sample, you're trying to override the |
The problem is that the parent class accepts any object that is callable and can be passed any list of arguments. By the Liskov Substitution Principle (LSP), any subclass must also accept an object that is callable and can be passed any list of arguments. However, the child class in this case is much more restrictive. It requires that the
callableparameter is an instance of a specific class (CallableClass).Why is this a problem? Consider the following:
It's impor…