Reputation: 36311
I am trying to create a method override, and I am not sure how to make it so that the override doesn't throw the following error:
Method "main" overrides class "App" in an incompatible manner
Parameter 2 type mismatch: base parameter is type "object", override parameter is type "Tuple[str, int, int]"
"object" is incompatible with "Tuple[str, int, int]"
I Understand that the two types are different, but since object is a base class shouldn't this be allowed? I have strict turned on, so an error is thrown when I use any
which is what I would like to keep turned on.
class App:
@abstractmethod
def main(self, params: object):
pass
class MyClass(App):
def main(self, params: Tuple[str, int, int]):
# Do something
What is the proper way to override a method and allow a parameter to be of any type (while using strict typing)?
Upvotes: 0
Views: 962
Reputation: 70287
You've got the variance backwards.
class App:
@abstractmethod
def main(self, params: object):
pass
This is a promise. It says "any class which implements App
has a main
which works on all objects. Not some of them. All of them.
Then you come along and write
class MyClass(App):
def main(self, params: Tuple[str, int, int]):
# Do something
So MyClass
has a main
which works on a specific type of parameter, not all of them. Your type checker correctly reports that this is not what you promised earlier. You could do the opposite thing: If App
requires Tuple[str, int, int]
, then MyClass
could implement a version for object
, since that includes Tuple[str, int, int]
and then some.
But for your case, you probably want generics.
from typing import TypeVar, Generic
_T_contra = TypeVar("_T_contra", contravariant=True)
class App(Generic[_T_contra]):
@abstractmethod
def main(self, params: _T_contra) -> None:
pass
class MyClass(App[Tuple[str, int, int]]):
def main(self, params: Tuple[str, int, int]):
# Do something
Now MyClass
doesn't claim to work for all objects. It claims to work for this specific type, so it derives from a specific App
.
For a discussion of why it's _T_contra
(a contravariant type parameter), you can read my other answer where I go into more detail on variance annotations in Python.
Upvotes: 4