www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is it ok to inherit multiple times same templated interface?

reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
Good day,

Given following code example, where a templated interface Wr, and 
an implementation Im is present:
interface Wr(T) {
     T get();
}

class Im(T : ubyte) : Wr!ubyte, Wr!ushort, Wr!string {
     public T t;

     ubyte get() {
         return cast(ubyte) this.t;
     }

     ushort get() {
         return cast(ushort) this.t;
     }

     string get() {
         import std.conv;
         return this.t.to!string ~ " with testings";
     }
}

void main() {
     auto i = new Im!ubyte;
     i.t = 20;

     assert((cast(Wr!ubyte) i).get == 20);
     assert((cast(Wr!ushort) i).get == 20);
     assert((cast(Wr!string) i).get == "20 with testings");
}

Is it ok (not undefined behavior), to have Im implementing 
multiple times interface Wr, with different template arguments?
Or doing so, will eventually lead to subtle bugs?

Currently doing so is allowed, though, it is impossible to call 
implemented methods directly from implementation.
Only by casting i to different implemented interfaces (Wr!ubyte, 
Wr!ushort, and Wr!string), is possible to call each implemented 
get method.

Thanks.
Jan 15 2017
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On Sunday, 15 January 2017 at 20:33:30 UTC, Alexandru Ermicioi 
wrote:
 Good day,

 Given following code example, where a templated interface Wr, 
 and an implementation Im is present:
From the standpoint of the compiler they are 3 distinct interfaces, so all is good.
 interface Wr(T) {
     T get();
 }

 [...]
Jan 15 2017
prev sibling next sibling parent reply Ryan <clumsycodemonkey gmail.com> writes:
On Sunday, 15 January 2017 at 20:33:30 UTC, Alexandru Ermicioi 
wrote:
 Good day,

 Given following code example, where a templated interface Wr, 
 and an implementation Im is present:
 interface Wr(T) {
     T get();
 }

 class Im(T : ubyte) : Wr!ubyte, Wr!ushort, Wr!string {
     public T t;

     ubyte get() {
         return cast(ubyte) this.t;
     }

     ushort get() {
         return cast(ushort) this.t;
     }

     string get() {
         import std.conv;
         return this.t.to!string ~ " with testings";
     }
 }

 void main() {
     auto i = new Im!ubyte;
     i.t = 20;

     assert((cast(Wr!ubyte) i).get == 20);
     assert((cast(Wr!ushort) i).get == 20);
     assert((cast(Wr!string) i).get == "20 with testings");
 }

 Is it ok (not undefined behavior), to have Im implementing 
 multiple times interface Wr, with different template arguments?
 Or doing so, will eventually lead to subtle bugs?

 Currently doing so is allowed, though, it is impossible to call 
 implemented methods directly from implementation.
 Only by casting i to different implemented interfaces 
 (Wr!ubyte, Wr!ushort, and Wr!string), is possible to call each 
 implemented get method.

 Thanks.
How would overloading work? Overload resolution works based on function/method parameters, not return types. In the example you gave the 3 get functions are indistinguishable. If the template parameter was used for a method parameter type, then they would be distinguishable. See overloading functions here [0]. I think yours only works with the cast because function parameters, including the _this_ pointer is taken into account. [0] https://dlang.org/spec/function.html#function-overloading
Jan 15 2017
parent Meta <jared771 gmail.com> writes:
On Sunday, 15 January 2017 at 23:25:25 UTC, Ryan wrote:
 How would overloading work?

 Overload resolution works based on function/method parameters, 
 not return types. In the example you gave the 3 get functions 
 are indistinguishable. If the template parameter was used for a 
 method parameter type, then they would be distinguishable.
Since the functions all have the same signature and interfaces can't store internal state, it doesn't matter which one is called.
Jan 16 2017
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 15 January 2017 at 20:33:30 UTC, Alexandru Ermicioi 
wrote:
 Currently doing so is allowed, though, it is impossible to call 
 implemented methods directly from implementation.
You should be able to do obj.Wr!(ubyte).get() too.
Jan 15 2017