Covariant return type

Chris Nicholson-Sauls ibisbasenji at gmail.com
Thu Mar 22 12:25:43 PDT 2007


Aarti_pl wrote:
> 
> 
> Jarrett Billingsley napisał(a):
>> "Aarti_pl" <aarti at interia.pl> wrote in message 
>> news:ettjqu$14jb$1 at digitalmars.com...
>>> Hello!
>>>
>>> Shouldn't code below work?:
>>>
>>> //-------------------------------------------
>>>
>>> abstract class Storage {
>>>     Storage get() {
>>>         return this;
>>>     }
>>> }
>>>
>>> class SpecificStorage : Storage {
>>>     void print() {}
>>> }
>>>
>>> void main() {
>>>     SpecificStorage s = (new SpecificStorage).get();
>>>     s.print;
>>> }
>>>
>>> //-------------------------------------------
>>>
>>> Unfortunately currently you have to add overridden implementation of 
>>> get() in SpecificStorage, like below (what is a little bit tedious 
>>> work):
>>>
>>>     SpecificStorage get() {
>>>         return this;
>>>     }
>>>
>>>
>>> But my intuition about that would be that "this" pointer from method 
>>> get from Storage class will point to "SpecificStorage" when there is 
>>> instantiated SpecificStorage. But it looks that in fact this points 
>>> to "Storage".
>>
>> Sounds like it's behaving correctly to me.  When you call .get on a 
>> SpecificStorage, the only override of it is the one that returns a 
>> Storage in the base class, and you can't cast from Storage to 
>> SpecificStorage implicitly.  The language will not implicitly define 
>> covariantly returning versions of your methods for you; that's up to you.
>>
> 
> Yes, but in fact I don't want to loose type information and upcast to 
> Storage. I just want to return 'this' as it is when return is invoked.
> 
> Such a behavior seems a little bit nonsense when there is covariance 
> return type feature in programming language. To get covariance I have 
> many time reimplement same code in every inherited class just to trigger 
> proper behaviour.
> 
> I think that it should not break anything when instead of making 
> upcasting during return compiler just return concreate type and probably 
> later make upcast when e.g. assigning to Storage variable. It should 
> also not break visibility as I return SpecificStorage - If I would want 
> to return Storage I can make upcast before return even in base class:
> 
> Storage get() {
>     return cast(Storage)this;
> }
> 
> ....
> 
> But maybe I am wrong... Do you think it would be enhancement for 
> language to have something like this? Or it can break something?...
> 
> I get to this problem with few simple, guarded setters methods in base 
> class, which should return 'this' to achieve chaining. They should 
> behave exactly same in all derived classes and currently the only way is 
> to copy slightly modified implementation to derived classes...
> 
> If you think it could be useful I will fill enhancement on bugzilla... 
> Or maybe it should be putted for discussion to main D forum? (as it 
> doesn't look like error according to answer)...
> 
> BR
> Marcin Kuszczak
> (aarti_pl)

In full truth, the type information is not completely lost.

SpecificStorage s = cast(SpecificStorage)( (new SpeceficStorage).get() );

Or, something more likely to be found:

SpecificStorage s;
if (auto ref = cast(SpecificStorage)( someObj.foo() )) {
   s = ref;
}
else {
   throw new Exception(...);
}

And when the new D comes to us...

macro Blarg (cls, var, expr, msg) {
   cls var;
   if (auto ref = cast(cls)( expr )) {
     var = ref;
   }
   else {
     throw new Exception(msg);
   }
}

// and in code...
Blarg(SpecificStorage   , s, someObj.foo(), "...");
Blarg(AlternativeStorage, a, someObj.bar(), "...");


Assuming I understand the upcoming macros right...  Which if I do, I can't wait for this.

-- Chris Nicholson-Sauls


More information about the Digitalmars-d-learn mailing list