subclassing

Jonathan M Davis jmdavisProg at gmx.com
Tue Nov 2 10:48:00 PDT 2010


On Tuesday, November 02, 2010 09:33:16 Jesse Phillips wrote:
> spir Wrote:
> > * Why does D allow me redefining (data) slots in the subclass OddSquares,
> > which exist in the superclass? (I did this first without noting, by copy
> > & paste ;-)
> 
> This is either a bug or so that you don't have name clashes with all the
> super classes (could really reduce the available names).
> 
> > * There is a bug in function find -- see DEBUG lines in this func and in
> > main. For any reason, the passed range loses its data (.element==0). If
> > I change find's interface to take a range of type OddSquares, then all
> > runs fine. I don't know what more to do to find the bug...
> 
> Nope, the bug is because you redefined element and so Range.element is not
> being assigned. Remove your duplicate declarations from OddSquares and it
> works.
> 
> I am also not sure why you have alias T type. T is already an alias for the
> type, and you never use it so maybe it is just having fun testing out
> alias.
> 
> > PS: I like very much this interface for input ranges :-) Decided to make
> > output data plain state (slots T element & bool continues); only step()
> > is a method. I know this is not true OO for some conception of OO, but
> > it is ok for me.
> 
> This doesn't go against OOP in the least. The specification for a Range
> doesn't prevent the design you have choosen. The benefit to using
> functions is to calculate values instead of storing the state.
> 
> I understand you are trying to discover the benefits through your own
> design, but D Ranges would look something like this.
> 
> class OddSquares(T) {
>     // internal state
>     private T number ;
>     private T max ;
>     // methods
> 
>     @property bool empty() {
>         if (this.number > this.max)
>             return true;
>         return false;
>     }
>     @property int front() {
>         return this.number * this.number ;
>     }
>     void popFront() {
>         this.number += 2 ;
>     }
>     this(T min, T max) {
>         // set initial internal state
>         if (min%2 == 1)
>             this.number = min ;
>         else
>             this.number = min+1 ;
>         this.max = max ;
>     }
> }

I should point out that you forgot the save property, which is required for 
forward ranges (though not input ranges). Without it, any algorithm which 
processes the range will consume it. Also, (though the OP did use a class, so I 
assume that's why you did), ranges are usually done with structs which makes 
passing them around less of an issue since structs are value types while classes 
are reference types. There are several range definitions in Phobos - particularly 
in std.range, std.algorithm, and std.container if the OP wants to look at 
existing ones. And since ranges are heavily used in Phobos and they have to have 
a very specific set of functions to work with functions in Phobos, it would be a 
good idea for the OP to stick to the function names that Phobos uses (as you 
demonstrated) or code isn't going to work with Phobos' facilities, which makes 
ranges a lot less useful. Ranges are for a lot more than just iterating, after 
all.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list