Thread overview
Array of objects and their inheritance
May 14, 2015
tired_eyes
May 14, 2015
Adam D. Ruppe
May 15, 2015
tired_eyes
May 14, 2015
Hi.
I'm having a hard time understanding D's inheritance. Consider the following code:


class Parent {
    public int x = 10;
}

class Child : Parent {
    public int y = 20;
}

void main() {
    import std.stdio;

    Parent[] array;

    auto obj1 = new Parent();
    auto obj2 = new Child();

    array ~= obj1;
    array ~= obj2;

    writeln(array[0]); // prints "Parent", as expected
    writeln(array[1]);  // prints "Child", so I assume that if it's a Child, we can access Child's fields

    writeln(array[0].x); // 10
    writeln(array[1].y); // Error: no property 'y' for type 'Parent'
}


First, I don't understand why we see array[2] as 'Child'. While it is a 'Child', shouldn't it be shown as a 'Parent' due to we explicitly create an array of 'Parents'?

Well, if it's still a 'Child', why we can't access it's fields? And what is the proper way of storing a collection of inherited objects without losing access to their fields and methods?

Please point me in the right direction. I'm (still) relatively new to D, and will appreciate any help.
May 14, 2015
On Thursday, 14 May 2015 at 19:00:16 UTC, tired_eyes wrote:
> First, I don't understand why we see array[2] as 'Child'. While it is a 'Child', shouldn't it be shown as a 'Parent' due to we explicitly create an array of 'Parents'?

It is getting the name through a virtual interface (a hidden one that has typeinfo).

class Base {
   string getName() { return "Base"; }
}

class Derived : Base {
   override string getName() { return "Derived"; }
}

Base b = new Derived();
b.getName() == "Derived"; // because the virtual function can still be called through an interface

> Well, if it's still a 'Child', why we can't access it's fields?

It is a Child object, but you are talking to it through the Parent interface, so only functions+members available on Parent can be accessed without casting it.

> And what is the proper way of storing a collection of inherited objects without losing access to their fields and methods?

Best you can do is say

if(child = cast(Child) parentArray[0]) {
   // it is a child, now use child to access that
}


Though often a better way is to add an interface method that does it in the parent and is overridden in the child, just like with the getName above.
May 15, 2015
Thank you for the explanation