Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility of method parameters of subclasses #424

Closed
spkersten opened this issue Sep 7, 2014 · 3 comments
Closed

Compatibility of method parameters of subclasses #424

spkersten opened this issue Sep 7, 2014 · 3 comments
Labels

Comments

@spkersten
Copy link
Contributor

Consider these classes:

class X:
        pass
class Y(X):
        pass
class Z(Y):
        pass

class A:
        def f(self, x: Y) -> None:
                pass

class B(A):
        def f(self, x: Z) -> None:
                pass

Here mypy, correctly, gives a type error, saying that, in class B, the first argument of f is incompatible with supertype A.

Now consider this class:

class C(A):
        def f(self, x: X) -> None:
                pass

mypy reports the same type error as for B. Is that correct? In a statically typed language, the definition of C should be okay. I'm still not completely familiar with gradual typing, so maybe I'm missing something again.

@JukkaL
Copy link
Collaborator

JukkaL commented Sep 7, 2014

Yeah, we could allow argument types to vary contravariantly, i.e. a subclass could override a method with more general argument types. This would actually be pretty useful, especially together with union types.

This is not supported currently due to this being potentially confusing when used with overloading. However, overloading is no longer needed that often, since union types are often a better alternative to overloading. Overloading with contravariance could still be supported as long the variants in an overload are not overlapping and they retain the order of the overridden definition.

For example, this should be fine:

class A:
    @overload
    def f(self, x: int) -> int: return 0
    @overload
    def f(self, x: str) -> str: return ''

class B(A):
    @overload
    def f(self, x: Union[int, slice]) -> int: return 1
    @overload
    def f(self, x: Union[str, bytes]) -> str: return 'x'

@JukkaL
Copy link
Collaborator

JukkaL commented Sep 7, 2014

Actually, after some contemplation I now feel that this should almost definitely be supported.

@JukkaL
Copy link
Collaborator

JukkaL commented Sep 8, 2014

Note that I haven't thought in much detail about how this works with multiple inheritance, but I don't see any problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants