Вам необходимо сделать ваш класс BaseView
родовым по отношению к M
. Итак, вы должны сделать что-то вроде этого:
from typing import TypeVar, Type, Generic
M = TypeVar('M', bound='Model')
# Models
class Model:
@classmethod
def factory(cls: Type[M]) -> M:
return cls()
class ModelOne(Model):
def one(self):
return
class ModelTwo(Model):
def two(self):
return
# Views
# A BaseView is now a generic type and will use M as a placeholder.
class BaseView(Generic[M]):
model: Type[M]
@property
def obj(self) -> M:
return self.model.factory()
def logic(self):
raise NotImplementedError
# The subclasses now specify what kind of model the BaseView should be
# working against when they subclass it.
class One(BaseView[ModelOne]):
model = ModelOne
def logic(self):
self.obj.one()
class Two(BaseView[ModelTwo]):
model = ModelTwo
def logic(self):
self.obj.two()
Одно примечание: я избавился от вашего псевдонима типа TypeModel
. Это отчасти стилистическое и отчасти прагматичное.
Стилистически, когда я смотрю на сигнатуру типа, я хочу иметь возможность сразу определить, использует ли он generics / typevars или нет. Использование псевдонимов типов скрывает, что / я действительно не люблю использовать контекстно-зависимые типы.
Прагматично, и средство проверки типов PyCharm, и mypy, как правило, испытывают небольшие трудности, когда вы чрезмерно используете псевдонимы типов, содержащие typevars.