Idea: Lazy upcasting
Reiner Pope
some at address.com
Tue Mar 27 15:12:13 PDT 2007
Reiner Pope wrote:
> Marcin Kuszczak wrote:
>> Hello!
>>
>> Recently I have tried to achieve chaining a few calls to setters. I mean
>> something like below:
>>
>> //-------------------------------------------
>>
>> abstract class Storage {
>> Storage param1(int p1) {
>> this.p1 = p1;
>> return this;
>> }
>> private:
>> int p1;
>> }
>>
>> class SpecificStorage : Storage {
>> public:
>> SpecificStorage param2(bool p2) {
>> this.p2=p2;
>> return this;
>> }
>> private:
>> bool p2;
>> }
>>
>> void main() {
>> // ...ok... ...ok... ...ups!
>> SpecificStorage1 s1 = (new SpecificStorage).param2(true).param1(5);
>> }
>>
>> //-------------------------------------------
>
> How about:
>
> interface Storage
> {
> Storage param1(int);
> }
>
> abstract class StorageImpl(T) : Storage {
> static assert(is(typeof(this) == T));
>
> T param1(int p1)
> {
> this.p1 = p1;
> return cast(T)this;
> }
> private int p1;
> }
>
> class SpecificStorage : StorageImpl!(SpecificStorage) {
> SpecificStorage param2(bool p2) {
> this.p2 = p2;
> return this;
> }
> private bool p2;
> }
>
> That should already work.
>
> Cheers,
>
> Reiner
PS. The reason I needed to add the extra interface was that D's type
system doesn't think StorageImpl!(Derived) is-a StorageImpl!(Base)
It makes sense, because there are times when such a conversion is dangerous:
List!(Square) a;
List!(Shape) b = a;
b.add(new Triangle); /// Ooops
But Java and Nemerle support this kind of casting in a safe way (I
think). What you need to do is specify something in the template
parameters at the top, which says, "You can cast down from this" or "you
can cast up from this". The general rule is that the "you can cast down
from this" types may only be used as return values, and the "you can
cast up from this" types may only be used as parameters:
interface Reader(T) // you can cast down from this
{
T read();
}
// Reader!(Derived) is-a Reader!(Base)
interface Writer(T) // you can cast up from this
{
void write(T);
}
// Writer!(Base) is-a Writer!(Derived)
D runs into problems because of the fact that templates can do more than
simple type substitution; things like static if. I don't know what the
solution to this is, but it seems like something here has been kept in
mind for a while, given that the Future page on digitalmars says
'template inheritance.'
Cheers,
Reiner
More information about the Digitalmars-d
mailing list