strettosis at tutanota.com

Mike Parker via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jun 9 18:16:50 PDT 2016


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);
}

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


More information about the Digitalmars-d-learn mailing list