On Thursday, 9 June 2016 at 22:19:33 UTC, Stretto wrote:
I have some class like

class bar { }
class foo : bar
{
    bar[] stuff;
}

and have another class

class dong : bar
{
   int x;
}


Now sometimes stuff will contain dong's, but I cannot access its members it without a cast.

fooo.stuff[0].x // invalid because bar doesn't contain x;

Hence,

((cast(dong)foo.stuff[0]).x is the normal way with a possible type check.

But in my case I will never mix different types in stuff and will always use it properly or do type checking in the cases I might mix.


That's just the nature of working with class hierarchies. A Derived is always a Base, but a Base might not be a Derived. If your Bar array in Foo will always hold only one type of Bar, then you can parameterize Foo with a type:

###########################
class Bar { }

// Only accept types that are implicitly convertible to Bar
class Foo(T : Bar) : Bar
{
    T[] stuff;
}

class Dong : Bar
{
   int x;
   this(int x) { this.x = x; }
}

void main()
{
    import std.stdio;
    auto foo = new Foo!Dong();
    foo.stuff ~= new Dong(10);
    writeln(foo.stuff[0].x);
}

###########################

Another option is to use a parameterized getter, which is somewhat cleaner than a cast.

###########################
class Foo : Bar
{
    Bar[] stuff;
    T get(T : Bar)(size_t index)
    {
        return cast(T)stuff[index];
    }
}

void main()
{
    import std.stdio;
    auto foo = new Foo();
    foo.stuff ~= new Dong(10);
    writeln(foo.get!Dong(0).x);
}

###########################

Reply via email to