DIP66 - Multiple alias this

mw mingwu at gmail.com
Mon Sep 28 20:28:17 UTC 2020


On Monday, 28 September 2020 at 19:41:07 UTC, H. S. Teoh wrote:
> On Mon, Sep 28, 2020 at 06:56:40PM +0000, mw via Digitalmars-d 
> wrote: [...]
>> It's all about resolve name clashing: `alias` means synonyms; 
>> let's just borrow from Eiffel, instead of re-invent the 
>> wheels: the main concepts to solve multiple inheritance are 
>> these 5 keywords:
>> 
>> https://www.eiffel.org/doc/eiffel/Eiffel_programming_language_reserved_words
>> 
>> `rename`
>> `export`
>> `undefine`
>> `redefine`   -- D's override
>> `select`
>
> I don't know Eiffel; could you enlighten me as to how it solves 
> the following instance of the diamond problem?
>
> 	struct Resource {
> 		this(...) { acquireResource(); }
> 		~this() { releaseResource(); }
> 	}
>
> 	class A {
> 		Resource x;
> 	}
>
> 	class B : A {
> 		...
> 	}
>
> 	class C : A {
> 		...
> 	}
>
> 	class D : B, C {
> 		// Should D have one instance of A.x, or two instances
> 		// of A.x? (Putting aside the question of naming for the
> 		// time being -- let's pretend we have a way of
> 		// addressing x somehow in either case.)
> 	}
>
> I can see some situations for which you want two distinct 
> instances of A.x (there should be two distinct resources 
> acquired by D), and some other situations for which you want 
> them to be the same (the same resource should be shared by B 
> and C).  How does Eiffel cater to both cases?


The Resource A.x in your example is what I have shown in my 
example PERSON.addr and PERSON.name here:

https://forum.dlang.org/thread/obqthozmxwzhvrafothw@forum.dlang.org

1) In Eiffel, by default the attribute is shared/joined, meaning 
in your above code as it its, there is only 1 `x` in D; and 
that's the PERSON.name in my example (no special treatment, it's 
just joined in D).


2) If the application do want separate instances of one 
attribute, PERSON.addr in my example, then use `rename` / 
`select` to choose the one the programmer wanted semantics in 
mind. So in this case, your example is:


class B : A {...}
class C : A {...}

// let's suppose the application's semantics want to use C.x, but 
still keep B.x
class D1 : B(rename x as bx)    // (rename ...) is my invented 
Eiffel syntax in D
          , C(select x) {        // (select ...) is my invented 
Eiffel syntax in D
   ...
}


// let's suppose the application's semantics want to use B.x, but 
still keep C.x
class D2 : B(select x)
          , C(rename x as cx) {
   ...
}


// let's suppose the application's semantics want to use B.x, but 
remove C.x
class D3 : B(select x)
          , C(undefine x) {
   ...
}


// let's suppose the application's semantics want to use C.x, but 
remove B.x
class D4 : B(undefine x)
          , C(select x) {
   ...
}


// let's suppose the application's semantics want to remove both 
B.x and C.x
class D5 : B(undefine x)
          , C(undefine x) {
   redefine x;  // need to redefine x
}


// let's suppose the application's semantics want to remove keep 
B.x and C.x
class D6 : B(rename x as bx)
          , C(rename x as cx) {
   redefine x;  // need to redefine x
}


... as you can see, all different application semantics can be 
specified by the programmer.


Please check my previous PERSON.addr example more carefully.

PERSON.addr
UK_RESIDENT(: PERSON).addr
US_RESIDENT(: PERSON).addr
VISITOR(: UK_RESIDENT, US_RESIDENT).addr

https://forum.dlang.org/post/obqthozmxwzhvrafothw@forum.dlang.org



More information about the Digitalmars-d mailing list