interfaces and contracts - new pattern

Adam D. Ruppe destructionator at gmail.com
Tue Dec 3 15:25:19 UTC 2019


On Tuesday, 3 December 2019 at 15:12:46 UTC, Ola Fosheim Grøstad 
wrote:
> But I was thinking of contravariant/covariant parameters on 
> virtual functions.

those too. I mostly use it with things like a clone method:

interface Cloneable {
     Cloneable clone();
}

class MyClass : Cloneable {
     override MyClass clone() { return new Myclass(); }
}


That is fairly intuitive for return values - MyClass is an 
instance of the interface so of course you should be able to 
return it! It just lets you specialize.


On the parameters side it is a little more confusing, but it 
still makes sense:

abstract class Generic {
     void generic(Generic g);
}

class Specialized : Generic {
     override void generic(Specialized g) {}
}


There you can see the obvious problem:

Generic g = new Specialized();
Generic other = new SomethingElse();
g.generic(other); // uh oh, interface allows it but 
specialization doesn't



But that's also why you can loosen.

class Specialized : Generic {
     override void generic(Object g) {}
}

since Generic implicitly casts back to Object, it is clear 
anything from the interface can also go to the child, so you're 
fine.

And if you do call the `super.generic`, you get the explicit cast 
requirement which is OK, since it happens in the implementation's 
body.

And then contracts follow the same rules...


It does make sense if you think about it, just it is weird if you 
don't.


More information about the Digitalmars-d-announce mailing list