# Java, strong typing, covariance and contra-variance

While studying for a test in my OOP course, I came upon this question which had an answer I didn't really understand. The question is as follows (translated):

The programming language "Sava" is similar to Java in every way except in the following:

1. It's structurally typed
2. When overriding a method the argument can be contravariant and the return type can be covariant.

Given the following class and interface, is the following assignment legal?

  interface I{
boolean equals(I i){…}
}

class C{
boolean equals(C c){…}
}

I i = new C();


The answer that was given to this question was: The assignment isn't legal. The equals method in C changes the paramater in a covariant way and so it doesn't match the equals method in I.

At first I thought the professor forgot to add "Implements I" but the answer also stated the following: Answers that refereed to the fact that C doesn't implement I weren't accepted because given that it's a Structurally Typed language it doesn't matter if it were a subtype.

I'm not sure I understand how we can refer to these methods as covariant / contravariant if there is no relation of subtyping between C and I.

Can anyone clear this up for me?

• Doesn't C implement I? – Mr. Polywhirl Oct 16 '13 at 21:15
• By "structural typing" your professor assumes the relation of subtyping to be implicit. – Karolis Juodelė Oct 17 '13 at 6:59

"Structurally typed" means that you don't need to write implements I: if your type has all the methods I has, with compatible signatures, it's automatically a subtype of I. However, in this case, C.equals(C) does not implement I.equals(I) (due to variance) and so C isn't a subtype of I.

EDIT:

I'll explain: For C to be structurally equivalent to I we need to know the type hierarchy for the arguments of equals.

Yes, here you have recursive structural types, which complicate the issue quite a bit.

The equals method in C changes the paramater in a covariant way and so it doesn't match the equals method in I.

This is strictly speaking incorrect, this isn't covariant (again, since C isn't a subtype of I). It should instead say e.g. "if we assume C is a subtype of I, then the equals method in C changes the parameter in a covariant way and we get a contradiction". You could claim C and I should be treated as equivalent (i.e. both subtypes of each other), and then there is no contradiction.

Another problem is that definition of C depends on C itself, so you have recursive structural types, which complicate the language quite a bit.

• How can we discuss the issue of variance if there isn't a subtype relation? I'll explain: For C to be structurally equivalent to I we need to know the type hierarchy for the arguments of equals. Since we don't know it shouldn't the answer be "The assignment isn't legal because there isn't a subtype relationship?" – Shookie Oct 17 '13 at 14:25