I want to create the equivalent of this in Python:
static class Event {}
static class MyEvent extends Event {}
interface Filter<E extends Event> {
boolean filter(E event);
}
static class MyFilter implements Filter<MyEvent> {
@Override public boolean filter(MyEvent event) {
return true;
}
}
This is my attempt (mypy-play):
from typing import TypeVar, Protocol
class Event:
pass
class MyEvent(Event):
pass
E = TypeVar("E", bound=Event)
class Filter(Protocol[E]):
def filter(self, event: E) -> bool:
raise NotImplementedError
class MyFilter(Filter):
def filter(self, event: MyEvent) -> bool: # should be ok
raise NotImplementedError
class BadFilter(Filter):
def filter(self, event: object) -> bool: # should fail
raise NotImplementedError
...that fails with main.py:11: error: Invariant type variable 'E' used in protocol where contravariant one is expected. Unless I'm misunderstanding, Java seems to be fine with an invariant one, and this is my idea as well; I don't want various Filters to be compatible with one another. In any case, slapping contravariant=True onto T doesn't work either. So,
Why the protocol needs a contravariant variable? And, how do I make this Python code type check?
BadFilterto fail. The contravariance meansBadFilteris fine. A filter that can filter arbitrary objects can filter events.MyFilterfilters subclasses, andBadFilterfilters superclasses. surely one of these should be failing?