Idea: Lazy upcasting

Marcin Kuszczak aarti at interia.pl
Tue Mar 27 14:55:04 PDT 2007


Mitja Slenc wrote:

> 
> OK, let me try to restate the problem, to see if I get it - some methods
> always return this, so that several invocations on the same object can
> be chained together : foo.a().b().c(). But, if one defines an inherited
> class and doesn't override those methods to indicate the new return
> type, calling base class' methods results in losing information about
> the derived type, so neither can the object be assigned to references of
> the derived type, nor can new methods of the derived class be called
> after calling base methods.

Yes. That is exactly the problem I was writing about....

> 
> The problem with your suggestion of 'lazy upcasting' is that it's quite
> impossible for the compiler to verify whether all the methods in fact
> return this (for example, the source file could've been compiled
> previously and its source is no longer available), so it can't tell
> whether to do the usual thing (use the declared return type) or not (use
> the derived type).

You are probably right. I was also thinking about problems with automatic
type inference with 'auto' - in this case compiler really can not know what
returned type is. For object type it can be any class which is possible to
create it. Knowing just method signature tells nothing about returned type.
Without knowledge of function source code compiler can do nothing...


> 
> A better idea would be to use a special keyword for the return type to
> indicate what is going on:
> 
> class Base
> {
> return_this foo(int i) { ... }
> }
> 
> class Derived : Base
> {
> return_this bar(int i) { ... }
> }
> 
> void main()
> {
> Derived d = (new Derived).foo(1).bar(2); // currently an error
> }
> 

Wow... IMHO it is stike home! This looks like it solves problem cleanly.
(Main problem, as it not helps Object.factory() case, but it is probably
not so easy solvable if at all).

I would just propose other syntax:

class Base {
        this foo(int i) { return this; } // function declared as returning "this" 
                                         // in base class

        this other() { return this; }    // same as above
}

class Derived : Base {
        this foo(int i) { return this; } // function overriding base class 
                                         // returns Derived
        this bar(int i) { return this; } // another function which will return this
        Base foo1() {} // foo1 returns always Base class instance
        Derived bar() {} // always returns Derived
        // in derived class method 'other' from base class is also available. 
        // it returns Derived.
}

void main() {
        // hopefully it will compile with 
        // DMD 1.xxx > DMD 1.010   :-)
        Derived d = (new Derived).foo(1).bar(2).other; 
}

It looks like really good replacement for clumsy covariance return type
feature. (In case of covariance return type it's difficult to see why
function in derived class with totally different return type should
override method in base class; and of course there is still problem with
what I have pointed out at the beginning...).

Return type 'this' should be just another special return type, like 'void'
type is currently. This special type shows precisely what will be returned
from function. It is possible to say exactly what return type will be just
seeing method (in class) declaration. It's consistent and looks good. It's
also probably even easier to work with it for compiler.

I wish it would be implemented. Walter, can you comment on this?

> 
> Another idea would be to treat void methods as if they implicitly
> returned this, though I'm quite sure there are hidden dangers in doing
> so. But, method definitions could certainly be cleaner and more obvious
> (it's not always clear whether the object returned is supposed to be a
> new one, or the called one), and I guess relatively many temporary
> variables serve only the purpose of being able to call more than one
> method on a given object (without fetching it twice from somewhere), and
> those would often no longer be needed, as well.
> 
> 
> xs0


-- 
Regards
Marcin Kuszczak (Aarti_pl)
-------------------------------------
Ask me why I believe in Jesus - http://zapytaj.dlajezusa.pl (en/pl)
Doost (port of few Boost libraries) - http://www.dsource.org/projects/doost/
-------------------------------------




More information about the Digitalmars-d mailing list