I have an abstract class Task
that describes the volume_id
attribute. The int
value is the ID of the volume that the specific task is for. In the case that the task is not for a specific volume (a “general” task), then it’s value is just None
. See example code below:
from abc import ABC, abstractmethod
from typing import Union
class Task(ABC):
volume_id: Union[int, None]
@abstractmethod
def run(self) -> None:
return
class GeneralTask(Task):
volume_id = None
def run(self) -> None:
# Do something without using volume_id
return
class SpecificTask(Task):
volume_id = None
def __init__(self, volume_id: int) -> None:
self.volume_id = volume_id
return
def run(self) -> None:
# Do something that uses volume_id
int(self.volume_id)
return
The problem is that my type checker/static analyser complains in the SpecificTask.run
function that the value of self.volume_id
could potentially be None
. This is only true in the scenario where an instance of the class is created, the value of the attribute is manually changed to None
, and then the run()
function is run. This scenario doesn’t come up in my code base and should be prohibited anyway.
How can I make clear and enforce that the type of volume_id
will not change after running __init__
(it can be an int
or None
, we set it to an int
and it won’t change back)? I tried changing the typehint to Final[int]
in the __init__
function, but then the static analyser complains that I’m overriding the type hint from the abstract class…