How to do "inheritance" in D structs

cym13 via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Oct 12 02:30:48 PDT 2016


On Wednesday, 12 October 2016 at 02:33:20 UTC, lobo wrote:
> On Wednesday, 12 October 2016 at 02:18:47 UTC, TheFlyingFiddle 
> wrote:
>> On Wednesday, 12 October 2016 at 01:22:04 UTC, lobo wrote:
>>> Hi,
>>>
>>> I'm coming from C++ and wondered if the pattern below has an 
>>> equivalent in D using structs. I could just use classes and 
>>> leave it up to the caller to use scoped! as well but I'm not 
>>> sure how that will play out when others start using my lib.
>>>
>>> Thanks,
>>> lobo
>>>
>>>
>>> module A;
>>>
>>> class Base1 {
>>>     int ival = 42;
>>> }
>>> class Base2 {
>>>     int ival = 84;
>>> }
>>>
>>> module B;
>>>
>>> class S(ABase) : ABase {
>>>     string sval = "hello";
>>> }
>>>
>>> module C;
>>>
>>> import A;
>>> import B;
>>>
>>> void main() {
>>>     auto s= scoped!(S!Base1); // scoped!(S!Base2)
>>> }
>>
>> You could use "alias this" to simulate that type of 
>> inheritence.
>>
>> module A;
>> struct Base1
>> {
>>     int ival = 42;
>> }
>>
>> module B;
>>
>> struct Base2
>> {
>>     int ival = 84;
>> }
>>
>> module C;
>> import A, B;
>>
>> struct S(Base) if(is(Base == struct))
>> {
>>     Base base;
>>     alias base this;
>>     string sval = "Hello ";
>> }
>>
>> void foo(ref ABase base)
>> {
>>     base.ival = 32;
>> }
>>
>> void main()
>> {
>>     S!Base1 a;
>>     S!Base2 b;
>>     writeln(a.sval, a.ival);
>>     writeln(b.sval, b.ival);
>>     foo(a);
>>     writeln(a.sval, a.ival);
>> }
>
> This approach works nicely although it feels clumsy but that's 
> probably just because I'm so used to C++. It also handles 
> private members as I'd expect, i.e. they're not accessible 
> outside module scope through the alias struct instance, but 
> there is no protected. Protected appears to behave the same way 
> as private.
>
> I think I can live with that because I usually try to avoid 
> protected anyway.
>
> Thanks,
> lobo

Note that alias this is not inheritance, it's subtyping. What 
happens when doing:

struct P { int val = 42; }
struct S { P p; alias p this; }
assert(S().val == 42);

is that S tries to find “ this.val ”. First it looks in its scope 
without success. Then it uses the alias to transform “ this.val ” 
into “ p.val ”, but the type S isn't linked to the type P. When 
using attributes of p you are really dealing with a real object 
of type P. It also means that implicit conversion of S in P will 
just copy the p member:

struct P {
     int val = 42;
}

struct S {
     P p;
     alias p this;
     int val = 1234;
}

void main(string[] args) {
     P p = S();
     assert(p.val == 42);
}

Assert this is a great feature but it has to be well understood.


More information about the Digitalmars-d-learn mailing list