Python: how to override type hint on an instance attribute in a subclass?
You could provide the something_special
method on Something
too, and raise a NotImplementedError
class Something:
def __init__(self):
self.attr = 0
def something_special(self):
raise NotImplementedError()
This resolves your type hinting issue, although functionally it will raise an exception at the same point (if you managed to get a Something
somehow and try to call something_special
, just will be NotImplementedError
instead of AttributeError
).
Maybe in some situations you might want to just pass
instead, depending on what something_special
actually is.
class Something:
def __init__(self):
self.attr = 0
def validate(self):
# doesn't want to perform validation
pass
class SubclassOfSomething(Something):
def __init__(self):
Something.__init__(self)
def validate(self):
if self.attr < 0:
raise ValueError()
The important underlying thing is making sure your class hierarchy conforms to a common interface - public methods on subclasses but not on parents goes against that and reduces the polymorphism of objects in your class hierarchy.
Using generics:
from abc import ABC, abstractmethod
from typing import Generic, TypeVar
SomethingT = TypeVar('SomethingT', bound='Something')
...
class Foo(ABC, Generic[SomethingT]):
my_class: SomethingT
def __init__(self):
self.my_class = self.get_something()
@abstractmethod
def get_something(self) -> SomethingT:
pass
class SubclassOfFoo(Foo[SubclassOfSomething]):
def __init__(self):
super().__init__()
def get_something(self) -> SubclassOfSomething:
return SubclassOfSomething()
def do_something_special(self):
# inferred type of `self.my_class` will be `SubclassOfSomething`
self.my_class.something_special()
You can give a type hint on my_class
attribute in the beginning of class definition:
class SubclassOfFoo(Foo):
my_class: SubclassOfSomething # <- here
def get_something(self) -> SubclassOfSomething:
return SubclassOfSomething()
def do_something_special(self):
self.my_class.something_special()
After that there is no warning Unresolved attribute reference 'something_special' for class 'Something'
from PyCharm inspection because now my_class
is known to be SubclassOfSomething
not Something
.