contravariant argument types: wanna?

Steven Schveighoffer schveiguy at yahoo.com
Thu Sep 24 06:38:24 PDT 2009


On Thu, 24 Sep 2009 09:06:41 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> Steven Schveighoffer wrote:
>> On Wed, 23 Sep 2009 11:13:26 -0400, Andrei Alexandrescu  
>> <SeeWebsiteForEmail at erdani.org> wrote:
>>> 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.)
>>  Your example just triggered a possible problem with contravariance.   
>> Consider this class:
>>  class Bad : TruckDriver {
>>    override void drive(AutoVehicle c) { ...}
>> }
>>  What does this override, drive(Truck) or drive(Car), or both?  What if  
>> you didn't want to override both?  My instinct is that this should be  
>> an error, to keep things simple.  But it might be very annoying for  
>> some designs...
>
> It should override both. It is already the case that one method  
> overrides several others (e.g. with multiple inheritance of interfaces).
>

Yes, but interfaces have no implementation -- it's clear you want to  
override both because there's no alternative.

Here is another example:

class RaceCar : Car {...}

class RaceCarDriver : Driver
{
    alias Driver.drive drive;
    void drive(RaceCar c) {...} // doesn't override Driver.drive(Car),  
because he drives normal cars in a different way
}

class BadDriver : RaceCarDriver // drives all cars like a race car
{
    override void drive(Car c) {...}
}

Should this override RaceCarDriver.drive(RaceCar)?

Currently, this is valid code (tested on 1.046) and results in different  
behavior than what you propose.  Although it's likely in my example you  
*want* to override both, but there could be cases where you do not.

-Steve



More information about the Digitalmars-d mailing list