contravariant argument types: wanna?
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Wed Sep 23 08:13:26 PDT 2009
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.)
Andrei
More information about the Digitalmars-d
mailing list