contravariant argument types: wanna?

Jeremie Pelletier jeremiep at gmail.com
Wed Sep 23 08:39:42 PDT 2009


Andrei Alexandrescu wrote:
> Jeremie Pelletier wrote:
>> Yigal Chripun wrote:
>>> On 23/09/2009 03:07, Andrei Alexandrescu wrote:
>>>> Hello,
>>>>
>>>>
>>>> Today, overriding functions have covariant return types:
>>>>
>>>> class A {
>>>> A clone();
>>>> }
>>>>
>>>> class B : A {
>>>> B clone(); // fine, overrides A.clone
>>>> }
>>>>
>>>> That is entirely principled and cool. Now the entire story is that
>>>> overriding function may have not only covariant return types, but also
>>>> contravariant argument types:
>>>>
>>>> class A {
>>>> A fun(B);
>>>> }
>>>>
>>>> class B : A {
>>>> B fun(A); // fine (in theory), overrides A.fun
>>>> }
>>>>
>>>> Today D does not support contravariant arguments, but Walter told me
>>>> once he'd be quite willing to implement them. It is definitely the 
>>>> right
>>>> thing to do, but Walter would want to see a compelling example before
>>>> getting to work.
>>>>
>>>> Is there interest in contravariant argument types? If so, do you 
>>>> know of
>>>> a killer example?
>>>>
>>>>
>>>> Thanks,
>>>>
>>>> Andrei
>>>
>>> consider:
>>>
>>> class Car { ... }
>>> class Truck : Car { ... }
>>>
>>> class Driver {
>>>     void drive (Car c);
>>> }
>>>
>>> class truckDriver : Driver {
>>>     void drive(Truck t); // NOT contra-variant !!
>>> }
>>>
>>> does the above design will be affected by your suggestion?
>>
>> You just described covariant arguments, which is a feature i'd also 
>> like to see. It's different from contravariant arguments, implementing 
>> one does not give the other unfortunately.
> 
> Well there's a good reason for it: contravariant arguments are sound, 
> covariant arguments aren't. My belief is that a design that would need a 
> lot of argument covariance ought to be analyzed.

Have you read my other post in this thread where I show an actual 
example of covariant arguments from my display interface, my I/O 
interfaces also use covariant arguments although they're more friendly 
to generic interface parameters.

The point is, you see covariance all the time in interface programming 
when implementations expect an interface argument to be an object from 
that same implementation. As soon as you use an abstract factory to let 
the world use some implementation without being aware of which one it 
is, you're bound to see covariance at some point. Most people just code 
it explicitly, the mozilla code is *full* of explicit covariant 
interface requests.

While they may not be sound, its still a scenario you're gonna come 
across sooner or later, and a scenario which involves lots of similar 
boilerplate that can easily be generated by the compiler.

Jeremie



More information about the Digitalmars-d mailing list