forbid field name conflict in class hierarchy

Dmitry Olshansky dmitry.olsh at gmail.com
Tue Nov 16 04:47:25 PST 2010


On 16.11.2010 14:40, spir wrote:
> On Tue, 16 Nov 2010 05:37:52 -0500
> bearophile<bearophileHUGS at lycos.com>  wrote:
>
>> spir:
>>
>>> (and bug-prone, because sometimes the absence of a fields seems not caught, for any reason), so I add fields to the top type.
>> What do you mean? Do you have an example?
>> (Adding fields to the top type doesn't look like a good idea, generally).
>>
>> Bye,
>> bearophile
> For instance, I have 2 sub-classes of nodes: one leaf kind with element (here called slice), one branch kind with an array of (child) nodes. They are exclusive, and none of the data fields should appear on the top Node type. But everywhere the Node class must be used, since a branch (as the top tree) can indifferently hold leaves or sub-branches, right?
> Each time I need to post-process results, since I apparently get Nodes (even if I know they are actually of one or the other type), I would first have to down-cast each node to the proper kind before doing anything. Else, I would get compiler errors, or plain bugs, for not having the proper field. So, I ended up setting fake fields on Node (and remove them from the sub-classes). And yes, I agree it's A Bad Thing to do. Just tell me of an elegant solution, and I apply it at once.
>
Looks like a good question for D.learn.
That's what opApply is made for. Namely: internal iteration.

Idea - basically what you need is apply some block of code (delegate) on 
each element.
If you provide in your node-like classes function opApply with signature:
int opApply(int delegate(ref A)); //where A is your data-type

foreach(a; node){
     writeln(a);//here a is element of data not Node or some such
}

Is rewritten as
node.opApply((ref a){ writeln(a); return 0;});
compiler rewrites code with breaks and so on to return 1, while at the 
normal end of flow to return 0

To get that idea better, try this example program

import std.stdio;
class Node{
     abstract int opApply(int delegate(ref int));
}
class Leaf: Node{
     this(int _data){
         data = _data;
     }
     int data;
     int opApply(int delegate(ref int) dg){
         return dg(data);
     }
}
class Branch: Node{
     Node[] nodes;
     this(Node[] _nodes...){
         nodes = _nodes.dup;
     }
     int opApply(int delegate (ref int) dg){
         Node[] n = nodes;
         while(n.length){
             int result = n[0].opApply(dg);
             if(result) return result; ///to handle breaks
             n = n[1..$];
         }
         return 0;
     }
}
void main(){
     Branch b = new Branch(new Leaf(17), new Leaf(19));
     Node n = new Branch(new Leaf(10),new Leaf(20),b);
     foreach(val;n){
         if(val == 17)//try playing around with break
             break;
         writeln(val);

     }

}

Also check the section 12.10 in TDPL if you have one, it goes in great 
detail about it.
> Denis
> -- -- -- -- -- -- --
> vit esse estrany ☣
>
> spir.wikidot.com
>


-- 
Dmitry Olshansky



More information about the Digitalmars-d mailing list