Вот ситуация до аннотаций. Проблема заключается в том, как правильно аннотировать getOther(), чтобы средства проверки статического типа правильно определяли тип возвращаемого значения для всех подклассов, без необходимости переопределять его для подклассов SubB1 и SubB2.
Кроме того, SubB1 и SubB2 должны оставаться подклассами из Б.
Код: Выделить всё
class A:
def __init__(self, a:int) -> None:
self.a:int = a
class SubA1(A): ...
class SubA2(A): ...
class B:
_otherClass = A
def __init__(self, b:int) -> None:
self.b:int = b
def getOther(self): # type checker: SubA1
b2.getOther() # Returns SubA2(2) => type checker: SubA2
1. Сделать B универсальным классом:
Код: Выделить всё
from typing import TypeVar, Generic
class A:
def __init__(self, a:int) -> None:
self.a:int = a
class SubA1(A): ...
class SubA2(A): ...
Aclass = TypeVar('Aclass')
class B(Generic[Aclass]):
_otherClass = A
def __init__(self, b:int) -> None:
self.b:int = b
def getOther(self) -> Aclass:
return self._otherClass(a = self.b)
class SubB1(B[SubA1]):
_otherClass = SubA1
class SubB2(B[SubA2]):
_otherClass = SubA2
Код: Выделить всё
B
Код: Выделить всё
b0 = B(0)
b1 = SubB1(1)
b2 = SubB2(2)
_ = b0.getOther() # Type checker => Any, Not OK
_ = b1.getOther() # Type checker => SubA1, OK
_ = b2.getOther() # Type checker => SubA2, OK
< /code>
[b] 2. Отдельный общий класс для getother
Вторая попытка состояла от него с использованием множественного наследования: < /p>
Код: Выделить всё
...
class _GenericB(Generic[Aclass]):
def getOther(self) -> Aclass:
return self._otherClass(a = self.b)
class B(_GenericB[A]):
_otherClass = A
def __init__(self, b:int) -> None:
self.b:int = b
class SubB1(B, _GenericB[SubA1])
class SubB1(B, _GenericB[SubA2])
Код: Выделить всё
b0 = B(0)
b1 = SubB1(1)
b2 = SubB2(2)
_ = b0.getOther() # Type checker => A, OK
_ = b1.getOther() # Type checker => A, Not OK
_ = b2.getOther() # Type checker => A, Not OK
Код: Выделить всё
TypeError: Cannot create a consistent method resolution order (MRO) for bases _GenericB, B'
Код: Выделить всё
...
class SubB1(_GenericB[SubA1], B) # B after _GenericB raises MRO resolution TypeError
class SubB1(_GenericB[SubA2], B) # B after _GenericB raises MRO resolution TypeError
< /code>
[b] 3. Отдельные базовые классы [/b]
Третья попытка, которую я предпринял, - это разделить общую и не общая часть класса B
Это, однако, нарушает отношения наследования:
Код: Выделить всё
...
class _NongenericB:
def __init__(self, b:int) -> None:
self.b:int = b
class _GenericB(Generic[Aclass]):
def getOther(self) -> Aclass:
return self._otherClass(a = self.b)
class B(_NongenericB, _GenericB[A]):
_otherClass = A
class SubB1(_NongenericB, _GenericB[SubA1]):
_otherClass = SubA1
class SubB2(_NongenericB, _GenericB[SubA2]):
_otherClass = SubA2
< /code>
Однако: < /p>
_ = b0.getOther() # Type checker => A, OK
_ = b1.getOther() # Type checker => SubA1, OK
_ = b2.getOther() # Type checker => SubA2, OK
assert isinstance(b0, B) # OK
assert isinstance(b1, B) # Assertion error
assert isinstance(b2, B) # Assertion error
Я немного не в себе. Что мне делать? Возможно, так как может быть много методов, работающих с этим механизмом.
Использование метода, определяемого в базовом классе раз и навсегда, будет идеальным решением. < /p>
Есть идеи? < / p>
Спасибо! < /p>
Подробнее здесь: https://stackoverflow.com/questions/793 ... rning-reci