www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - what is the proper syntax to inherit a pair of nested classes using

I am needing pairs of specific nested classes with already-coded 
collection management; eg: classComputers having nested 
classComputer as following (as seen by client code that is):




- classComputer ← objComputers.first
- classComputer ← objComputers.last
- classComputer ← objComputers[2].previous
- classComputer ← objComputers[2].next
- string ← objComputers[2].name
- string ← objComputers["ID2"].name
- classComputer ← objComputers["ID2"].next
- classComputer ← objComputers["ID2"].previous
- size_t ← objComputers.count
- bool ← objComputers.empty
- bool ← objComputers.remove("ID3")
- bool ← objComputers.removeAll()
- classComputers ← objComputers.filterByWhatever("...") ... 
extended functionality like this specifically implemented 
on-demand by client code

... so classComputers should inherit the collection management 
infrastructure (ie: the store itself and associated 
properties/methods to handle it) while classComputer should 
inherit collection access with this.outer (or the like) ... now 
let's see my implementation:

```d
abstract public class classCollectionItems(
    typeItems,
    typeItem
    ) {

    /// (1) given type for collection items; eg: classComputers
    /// (2) given type for collection item;  eg: classComputer

    typeItems lhs;
    typeItems rhs;

    int opApply(int delegate(typeItem) dg) { /// boilerplate code 
to handle the class's default collection

       int lintResult = 0; /// must find a better name

		foreach (lobjItem; items) { /// looping over the computers 
starting in current node

			lintResult = dg(lobjItem); /// passing single object to the 
loop body

			if (lintResult != 0) { break; }

		}

       if (lintResult != 0 && lhs ! is null) { lintResult = 
lhs.opApply(dg); } /// recursing child nodes
       if (lintResult != 0 && rhs ! is null) { lintResult = 
rhs.opApply(dg); } /// recursing child nodes

       return lintResult;

    }

    final public typeItem add(in string lstrID) { return false; };
    final public bool remove(in string lstrID) { return false; };
    final public bool removeAll() { this.items.length = 
cast(size_t) 0; return this.items.length == cast(size_t) 0; };

    final public  property const bool empty() { return 
this.items.empty; }
    final public  property const size_t count() { return 
this.count1; }
    final public  property const size_t count0() { return 
this.items.empty ? cast(size_t) 0 : this.items.length - 
cast(size_t) 1; }
    final public  property const size_t count1() { return 
this.items.empty ? cast(size_t) 0 : this.items.length; }

    final public  property typeItem first() { return null; }
    final public  property typeItem last() { return null; }

    abstract public class classCollectionItem {

       private size_t pintPosition0 = cast(size_t) 0; /// keep in 
mind that array positions are zero-based

       final public  property const size_t position0() { return 
this.pintPosition0; }
       final public  property const size_t position1() { return 
this.pintPosition0 + cast(size_t) 1; }

       final public  property const size_t countAbove() { return 
this.outer.items.empty ? cast(size_t) 0 : this.pintPosition0; }
       final public  property const size_t countBelow() { return 
this.outer.items.empty ? cast(size_t) 0 : this.outer.length - 
this.pintPosition0 - cast(size_t) 1; }

       /// eg: for position0=0 → countAbove=0=(position0=0) & 
countBelow=2=(length=3)-(position0=0)-1
       /// eg: for position0=1 → countAbove=1=(position0=1) & 
countBelow=1=(length=3)-(position0=1)-1
       /// eg: for position0=2 → countAbove=2=(position0=2) & 
countBelow=0=(length=3)-(position0=2)-1

       final public  property typeItem first() { return 
this.outer.items.empty ? null : this.outer.items[cast(size_t) 0]; 
}
       final public  property typeItem previous() { return 
this.outer.items.empty || this.countAbove == cast(size_t) 0 ? 
null : this.outer.items[this.pintPosition0 - cast(size_t) 1]; }
       final public  property typeItem next() { return 
this.outer.items.empty || this.countBelow == cast(size_t) 0 ? 
null : this.outer.items[this.position0 + cast(size_t) 1]; }
       final public  property typeItem last() { return 
this.outer.items.empty ? null : 
this.outer.items[this.outer.items.length - cast(size_t) 1]; }

    }

}
```

... so far so good, now, when I code my specific classes I am 
**not sure which is the correct syntax to inherit the base pair**:

```d
public class classComputers : 
classCollectionItems!(classComputers, 
classComputers.classComputer) { /// seems logical to me

    public class classComputer {}
    public class classComputer : classCollectionItem {}
    public class classComputer : 
classCollectionItems!(classComputers, 
classComputers.classComputer).classCollectionItem {}

}
```
Jun 10 2021