contravariant argument types: wanna?

Ary Borenszweig ary at esperanto.org.ar
Wed Sep 23 08:40:37 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.
> 
> I thought more about the car/truck example and I think it can be worked 
> out nicely. The problem right now is that Truck inherits Car. But a 
> truck is not substitutable for a car in all instances, because for 
> example a driver able to drive a car cannot necessarily drive a truck. 
> Here's a design that fixes that:
> 
> class AutoVehicle { ... }
> class Car : AutoVehicle { ... }
> class Truck : AutoVehicle { ... }
> 
> class Driver {
>     // A driver is licensed to drive a car
>     void drive(Car c);
> }
> 
> class TruckDriver : Driver {
>     // A truck driver is licensed to drive a car...
>     override void drive(Car c);
>     // ... and a truck
>     void drive(Truck c);
>     // No contravariance needed yet
> }
> 
> class JamesBond : Driver {
>     // James Bond can drive any auto vehicle
>     // Contravariance needed here
>     override void drive(AutoVehicle c) { ... }
> }
> 
> Now if what you have is a JamesBond and a Truck, you need contravariance 
> to have him drive it. (A HotGirl may or may not be present in the scene.)

So it should be:

class JamesBond : Driver {
   override void drive(Object c) { ... }
}

because JamesBond can even drive a HotGirl!



More information about the Digitalmars-d mailing list