## Covariant Return and Contravariant Arguments

As we know, to a variable of function type may be assigned a closure with compatible return type and compatible argument types. "Compatible return type" means that the type is either the same as in function type or is a subclass of this type (return types are covariant).

```  { => Number } p1 =
{ => Integer.valueOf(19) };  // Integer is a subclass of Number
{ => Number } p2 =
{ => Double.valueOf(1.25) };  // Double is a subclass of Number
```

"Compatible argument type" means that the argument type is either the same as in function type or is a superclass of this type (argument types are contravariant).

```  { String => void } p =
// Object is a superclass of String
{ Object o => System.out.println(o); };
```

We can combine covariant return with contravariant arguments:

```  { String => Number } p = { Object o => Integer.valueOf(o.hashCode()) };
System.out.println(p.invoke("haf"));
```

These rules define hierarchy on function types. So a function type might be a subtype or supertype of another function type. For example, `{ => Integer }` is a subtype of `{ => Number }` and `{ String => void }` is a supertype of `{ Object => void }`. As for class types, to a variable of function type may be assigned an object (closure) of its type or any subtype.

What is meant by covariant and contravariant?
Let S and T be two types (classes or function types) such that S is a subtype of T. If method m of T is overridden in S, then the corresponding types from the m's signature can either preserve the relationship between S and T (i.e. the type used in S is a subtype of the corresponding type in T), reverse this relationship (i.e. the type used in S is a supertype of that in T), or neither preserve nor reverse this relationship. If they preserve the relationship of S and T, we say they are covariant, and if they reverse the relationship of S and T, we say they are contravariant.

Hamlet D'Arcy said...

The covariant works fine for me unless I specify an Object as the type.... then my closure starts yielding null all the time.

Is there a forum to discuss this on?

Do you know why the following produces 19, 19, null?

public class Example {

public static void main(String[] args) {
{ => Integer } one = { => Integer.valueOf(19) };
System.out.println(one.invoke());

{ => Number } two = { => Integer.valueOf(19) };
System.out.println(two.invoke());

{ => Object } three = { => Integer.valueOf(19) };
System.out.println(three.invoke());
}
}

Zdeněk Troníček said...

It works under the previous version (2007-11-30) so it is probably a bug in the latest version.

Neal Gafter said...

Hamlet: thanks for the bug report. Now fixed.

hbrednek said...

I don't understand this. In particular, the statement is made that argument types must be contravariant. As I understand this then if I specify, for example, that an argument should be of type javax.naming.directory.SearchResult because I expect to invoke its member function getAttributes() in the closure, I can pass an actual instance of javax.naming.NameClassPair which is a supertype of SearchResult. This makes no sense, as NameClassPair has no getAttributes() method to invoke. HELP!

Zdeněk Troníček said...

Hi Mike,

"contravariant arguments" are not used when you call the closure but when you assign a closure to a variable of function type.

For example, the p variable is a reference to a closure that has a single argument of type String:

{ String => void } p;

And we are allowed to assign to p a closure that takes an argument of type Object:

p = { Object o => System.out.println(o); };

Why? Because String is Object. So, when you call a closure with a String argument, this argument can be safely passed to the referenced closure.

Alat Bantu Romantis Warga pria wanita said...

kami penyededia informasi alat bantu sex.
sekaligus jual alat sex wanita.
alat bantu sex pria.
sex toys terbaru.

Alat Bantu Romantis Warga pria wanita said...

nie job.

Anonymous said...
Unknown said...

Very much useful article. Kindly keep blogging

Java Training in Chennai

Java Online Training India

klinik aborsi said...

Jual Obat Aborsi Asli | Obat Cytotec Asli | 082241083319
jual obat aborsi pills cytotec asli manjur untuk menggugurkan kandungan usia 1 - 6 bulan gugur tuntas.CYTOTEC OBAT ASLI sangat efektif mengatasi TELAT DATANG BULANdan menjadikan anda gagal hamil , CYTOTEC adalah OBAT ABORSI 3 JAM BERHASIL GUGUR TUNTAS dengan kwalitas terbaik produk asli pfizer nomor 1 di dunia medis
JUAL OBAT ABORSI DI PURBALINGGA
JUAL OBAT ABORSI DI PURWOREJO
JUAL OBAT ABORSI DI REMBANG
JUAL OBAT ABORSI DI SEMARANG
JUAL OBAT ABORSI DI UNGARAN
JUAL OBAT ABORSI DI SRAGEN
JUAL OBAT ABORSI DI SUKOHARJO