subclassing

Jesse Phillips jessekphillips+D at gmail.com
Tue Nov 2 09:33:16 PDT 2010


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 also like in this design the fact that the constructor sets the range's initial state -- or is supposed to -- so that we can use the range at once, without calling step() once to initialise it.

Ah, but you do call step at the very end of the constructor. This prevents it from entering user code and is generally all that matters. You will notice I acutally removed that call for the range above.

I guess you could say that the real complaint was due to the desire to time how long it took to load the data (build the ranges) and how long it took to do the filtering. That meant I was separating the initialization phase from the construction of the range itself. Any way you rarely see this creep into user code.

So the only other piece to inform you of (to help you learn D) is that find is found in std.algorithm and does exactly what you have demonstrated, with a slightly different call:

auto element = find!((int e){return (e>200 && e<250))(range);

or

auto element = find!("a>200 && a<250")(range);

And will return a range starting at the element found, however it will not stop when over 250. For that you use filter instead.

auto element = filter!("a>200 && a<250")(range);



More information about the Digitalmars-d-learn mailing list