On Tuesday, 8 June 2021 at 02:37:44 UTC, someone wrote:
On Tuesday, 8 June 2021 at 02:05:27 UTC, Paul Backus wrote:
Your module and class are both named `classComputers`, with an
`s` at the end. You should change one of the to have a
different name so that there's no ambiguity.
Although I am still not being able to solve the import issue for
the child code on my nested-classes (low priority by the time
being), I have now a more pressing issue.
But first and foremost: almost sure you'll find my code style
noisy given the heavily-used attribue/function properties, but
this is solely to remind me how things work in a new language,
what will be obvious to an experienced D developer (default
attributes) it is not obvious to me right now ... spare me the
style, will you ?
I moved all the boilerplate code to manage the collection to
classCollectionItems which also has a nested child
classCollectionItem (since I'll be widely using them as the basis
for hierarchical class models) and from then on I inherit the
class on my final classComputers/classComputer code which is my
first test-bed app in D.
Before moving the code to the new generic abstract classes the
code below worked flawlessly, and still works albeit for a minor
detail:
I now **have an issue accessing the collection** (previously
defined in the base classCollectionItems) through my derived
classComputers class: please, look for the comment block marked
with +++ below.
The base classCollectionItems will always have a collection named
items, and each derived class I will make from it should have a
reference to it renamed accordingly; eg: computers in the case of
my classComputers class. Later I will plan to make an interface
to hide all the inner details and hide the items property of the
base class once and for all, leaving each new derived class' own
renamed property publicly accessible). So when the issue first
appeared on my new refactored code I **started playing with alias
to no avail** -and even making a new computers property
initialized with items (but then I figured it out that this will
be copying the array -not referencing it, so this will be a
no-go).
Some advice please ?
```d
#!/bin/dmd
module dmclassescomputers;
import std.string;
abstract private class classCollectionItems {
classCollectionItems lhs;
classCollectionItems rhs;
int opApply(int delegate(classCollectionItem) 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;
}
public @property classCollectionItem[] items; alias items
this; /// ie: default property
final public @property const long count0() { return
this.items.empty ? 0L : this.items.length - 1L; }
final public @property const long count1() { return
this.items.empty ? 0L : this.items.length; }
final public @property const long count() { return
this.count1; }
final public @property const bool empty() { return
this.items.empty; }
abstract public bool add(in string lstrID) { return false; }
abstract public bool remove(in string lstrID) { return false; }
abstract public bool removeAll() { return false; }
abstract class classCollectionItem {
private ulong pintPosition0 = 0L; /// keep in mind that
array positions are zero-based
final public @property const ulong position0() { return
this.pintPosition0; }
final public @property const ulong position1() { return
this.pintPosition0 + 1L; }
final public @property const ulong countAbove() { return
this.outer.items.empty ? 0L : this.pintPosition0; }
final public @property const ulong countBelow() { return
this.outer.items.empty ? 0L : this.outer.length -
this.pintPosition0 - 1L; }
/// 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 classCollectionItem first() { return
this.outer.items.empty ? null : this.outer.items[0L]; }
final public @property classCollectionItem previous() {
return this.outer.items.empty || this.countAbove == 0L ? null :
this.outer.items[this.pintPosition0 - 1L]; }
final public @property classCollectionItem next() { return
this.outer.items.empty || this.countBelow == 0L ? null :
this.outer.items[this.position0 + 1L]; }
final public @property classCollectionItem last() { return
this.outer.items.empty ? null :
this.outer.items[this.outer.items.length - 1L]; }
}
}
final private class classComputers : classCollectionItems {
private string pstrNetwork;
final public @property const string network() { return
this.pstrNetwork; }
final public @property void network(in string lstrNetwork) {
this.pstrNetwork = lstrNetwork.strip(); }
this(
in string lstrNetwork = null
) {
if (lstrNetwork ! is null) { this.network = lstrNetwork; }
}
/// +++ Error: no property `ID` for type
`dmclassescomputers.classCollectionItems.classCollectionItem`
/// +++ alias computers = this;
/// +++ alias computers = this.items;
/// +++ alias computers = classCollectionItems;
/// +++ alias computers = classCollectionItems.items; alias
computers this; /// it seems to me something like this should be
the correct one but obviously it is not :(
/// +++ alias computers = classCollectionItems.items[];
/// +++ public @property classCollectionItem[] computers =
this.items;
/// +++ checked: https://dlang.org/spec/declaration.html#alias
/// +++ checked: http://ddili.org/ders/d.en/alias_this.html
final public bool add(in string lstrID, in string lstrName) {
return false; }
override final public bool add(in string lstrID) { return
false; }
override final public bool remove(in string lstrID) { return
false; }
override final public bool removeAll() { return false; }
final class classComputer : classCollectionItem { /// should:
import dmclassescomputer;
private string pstrID; final @property const string ID() {
return this.pstrID; }
private string pstrName; final @property const string
name() { return this.pstrName; }
final public @property void name(in string lstrName) {
this.pstrName = lstrName.strip(); }
this(
in string lstrID,
in string lstrName = null
) {
this.pintPosition0 = this.outer.items.length;
if (lstrID ! is null) { this.pstrID = lstrID.strip(); }
if (lstrName ! is null) { this.pstrName =
lstrName.strip(); }
}
}
unittest {
dmclassescomputers.classComputers lobjComputers;
lobjComputers = new dmclassescomputers.classComputers;
assert(lobjComputers.network is null);
lobjComputers = new
dmclassescomputers.classComputers(null);
assert(lobjComputers.network is null);
lobjComputers = new
dmclassescomputers.classComputers(r"lab"c);
assert(lobjComputers.network == r"lab"c);
assert(lobjComputers.count0 == 0);
assert(lobjComputers.count1 == 0);
assert(lobjComputers.count == 0);
bool lbolComputers = false;
foreach(lobjComputer; lobjComputers) { /// testing access
to the empty collection: should never get within the body of the
loop
lbolComputers = true;
}
assert(lbolComputers == false);
lobjComputers ~= lobjComputers.new classComputer(r"WS1"c,
r"dell"c); /// adding the first computer
assert(lobjComputers.count == 1L);
assert(lobjComputers.count1 == 1L);
assert(lobjComputers.count0 == 0L);
with (lobjComputers[0L]) {
assert(countAbove == 0L);
assert(countBelow == 0L);
assert(first ! is null && first.ID == r"WS1"c);
assert(previous is null);
assert(next is null);
assert(last ! is null && last.ID == r"WS1"c);
}
lobjComputers ~= lobjComputers.new classComputer(r"WS2"c,
r"ibm"c); /// adding a second computer
assert(lobjComputers.count == 2L);
assert(lobjComputers.count1 == 2L);
assert(lobjComputers.count0 == 1L);
with (lobjComputers[1L]) {
assert(countAbove == 1L);
assert(countBelow == 0L);
assert(first ! is null && first.ID == r"WS1"c);
assert(previous ! is null && previous.ID == r"WS1"c);
assert(next is null);
assert(last ! is null && last.ID == r"WS2"c);
}
lobjComputers ~= lobjComputers.new classComputer(r"WS3"c,
r"apple"c); /// adding a third computer
assert(lobjComputers.count == 3L);
assert(lobjComputers.count1 == 3L);
assert(lobjComputers.count0 == 2L);
with (lobjComputers[2L]) {
assert(countAbove == 2L);
assert(countBelow == 0L);
assert(first ! is null && first.ID == r"WS1"c);
assert(previous ! is null && previous.ID == r"WS2"c);
assert(next is null);
assert(last ! is null && last.ID == r"WS3"c);
}
with (lobjComputers[1L]) {
assert(countAbove == 1L);
assert(countBelow == 1L);
assert(first ! is null && first.ID == r"WS1"c);
assert(previous ! is null && previous.ID == r"WS1"c);
assert(next ! is null && next.ID == r"WS3"c);
assert(last ! is null && last.ID == r"WS3"c);
}
with (lobjComputers[0L]) {
assert(countAbove == 0L);
assert(countBelow == 2L);
assert(first ! is null && first.ID == r"WS1"c);
assert(previous is null);
assert(next ! is null && next.ID == r"WS2"c);
assert(last ! is null && last.ID == r"WS3"c);
}
lobjComputers[1L].name = r"lenovo"c;
assert(lobjComputers[1L].name == r"lenovo"c);
assert(lobjComputers[0L].position1 == 1L);
assert(lobjComputers[1L].position1 == 2L);
assert(lobjComputers[2L].position1 == 3L);
assert(lobjComputers[0L].position0 == 0L);
assert(lobjComputers[1L].position0 == 1L);
assert(lobjComputers[2L].position0 == 2L);
foreach(lobjComputer; lobjComputers) { /// testing access
to the collection
assert(lobjComputer.outer.network == r"lab"c); ///
testing parent class' properties
}
}
}
```