Ary Borenszweig wrote:
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!

class MultiTask {
        this(Object[] tasks) {this.tasks = tasks;}
        Object[] tasks;
}
(new JamesBond).drive(new MultiTask([new Truck, new HotGirl]));

He can do both at once!

Reply via email to