#include <cstdio>
int main()
{
struct TBase { int v; TBase() : v(10) {}; virtual void who() { printf("TBase");} };
struct TObjA: TBase { int v; TObjA() : v(20) {}; virtual void who() { printf("TObjA");} };
struct TObjB: TObjA { int v; TObjB() : v(30) {}; virtual void who() { printf("TObjB");} };
struct TObjC: TObjB { int v; TObjC() : v(40) {}; virtual void who() { printf("TObjC");} };
struct TObjD: TObjC { int v; TObjD() : v(50) {}; virtual void who() { printf("TObjD");} };
TBase* objBase = new(TBase);
TObjA* objA = new(TObjA);
TObjB* objB = new(TObjB);
TObjC* objC = new(TObjC);
TObjD* objD = new(TObjD);
TBase* baseObj[5] = {objBase, objA, objB, objC, objD};
printf("-baseObj-\n");
for (int idx = 0; idx < 5; ++idx) {
baseObj[idx]->who();
printf(" (%d, %d)\n", baseObj[idx]->v, idx);
}
TObjB* bObj[3] = {objB, objC, objD};
printf("-bObj-\n");
for (int idx = 0; idx < 3; ++idx) {
bObj[idx]->who();
printf(" (%d, %d)\n", bObj[idx]->v, idx);
}
TBase* otherObj[3] = {objA, objB, objC};
printf("-otherObj-\n");
for (int idx = 0; idx < 3; ++idx) {
otherObj[idx]->who();
printf(" (%d, %d)\n", otherObj[idx]->v, idx);
}
delete(objBase); objBase = NULL;
delete(objA); objA = NULL;
delete(objB); objB = NULL;
delete(objC); objC = NULL;
delete(objD); objD = NULL;
return 0;
}
-baseObj-
TBase (10, 0)
TObjA (10, 1)
TObjB (10, 2)
TObjC (10, 3)
TObjD (10, 4)
-bObj-
TObjB (30, 0)
TObjC (30, 1)
TObjD (30, 2)
-otherObj-
TObjA (10, 0)
TObjB (10, 1)
TObjC (10, 2)
and the nimrod version...
type
TBase = object of TObject
v: int
TObjA = object of TBase
va: int # cannot be `v`, will not compile
TObjB = object of TObjA
vb: int
TObjC = object of TObjB
vc: int
TObjD = object of TObjC
vd: int
method who(obj:ref TBase) = echo("TBase")
method who(obj:ref TObjA) = echo("TObjA")
method who(obj:ref TObjB) = echo("TObjB")
method who(obj:ref TObjC) = echo("TObjC")
method who(obj:ref TObjD) = echo("TObjD")
var
objBase: ref TBase = new(TBase)
objA: ref TObjA = new(TObjA)
objB: ref TObjB = new(TObjB)
objC: ref TObjC = new(TObjC)
objD: ref TObjD = new(TObjD)
echo "-baseObj-"
var baseObj: array[5, ref TBase] = [objBase, objA, objB, objC, objD]
for obj in baseObj:
obj.who
echo "-bObj-"
var bObj: array[3, ref TObjB] = [objB, objC, objD]
for obj in bObj:
obj.who
echo "-otherObj-"
#Does not compile - results in Error: type mismatch: got (Array constructor[0..2], ref TObjA]) but expected 'array[0..2, ref TBase]'
#var otherObj: array[3, ref TBase] = [objA, objB, objC]
var otherObj: array[3, ref TBase]
otherObj[0] = objA
otherObj[1] = objB
otherObj[2] = objC
for obj in otherObj:
obj.who
Questions / comments based on this example:
Both 'devel' and 'release' branches were used in the example; they produced the same behaviour.
Are the behaviours described intended?
Get some press in Dr. Dobbs, and you wind up with all sorts of annoying nit picky questions thrown at you (plural). The price of fame.
Sounds fine. Name shadowing in particular is a "feature" best left out. As for inheritance, when limited to a few levels deep it has it's place for certain types of problems. But like any tool or technique it can be overused or poorly used, particularly when presented as the idiomatic way to solve all tasks.
When presented with a new environment, a cat or dog will check everything out, find out the bounds of the area, and then either live with it or try to escape. A developer presented with a new language / environment exhibits remarkably similar behaviour.