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