digitalmars.D.learn - structs inheriting from and implementing interfaces
- Mike Franklin (51/51) Dec 29 2017 In C#, structs can inherit from and implement interfaces.
- Seb (6/58) Dec 29 2017 I think it simply hasn't been implemented, but I am not sure here
- rikki cattermole (3/3) Dec 29 2017 Structs are structs, classes are classes.
- Mike Franklin (8/12) Dec 29 2017 I'm talking about interfaces, which are neither structs nor
- Jonathan M Davis (14/19) Dec 29 2017 Interfaces are related to classes and not structs. Structs do not have
- Nicholas Wilson (7/59) Dec 29 2017 The problem is that interfaces are a runtime thing (e.g. you can
- rjframe (7/14) Dec 29 2017 I've actually thought about doing this to get rid of a bunch of if
- rikki cattermole (2/19) Dec 29 2017 Or we could get signatures, which are even better still!
- Basile B. (5/33) Dec 29 2017 I was about to answer that interfaces could be used to define
- Mengu (3/20) Dec 29 2017 +6666 for SML style signatures!
- Laeeth Isharc (3/23) Jan 01 2018 Atila does something like this
- thedeemon (8/10) Dec 29 2017 It's a design decision.
- Basile B. (8/60) Dec 29 2017 This feature is criticized among the C# community:
- Random D user (38/43) Dec 29 2017 I think it's deliberate, structs are just plain dumb value types.
- Steven Schveighoffer (12/15) Dec 30 2017 It was deliberate, but nothing says it can't actually be done. All an
- flamencofantasy (5/20) Jan 02 2018 Don't forget to implement boxing/unboxing and then write a long
- Meta (2/54) Jan 01 2018 You want wrap: https://dlang.org/phobos/std_typecons.html#wrap
---- using System; interface IPrint { void Print(); } struct MyStruct : IPrint { public void Print() { Console.WriteLine(ToString()); } } public class Program { public static void Main() { MyStruct s = new MyStruct(); s.Print(); } } ---- https://dotnetfiddle.net/lpXR1O But in D it doesn't appear possible. ---- import std.stdio; interface IPrint { void print(); } // Error: base classes are not allowed for struct, did you mean ;? struct MyStruct : IPrint // Error: base classes are not allowed for struct, did you mean ;? { void print() { writeln("MyStruct"); } } void main() { MyStruct s; s.Print(); } ---- https://run.dlang.io/is/j4xwla Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision? Thanks for your insight, Mike
Dec 29 2017
On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote:---- using System; interface IPrint { void Print(); } struct MyStruct : IPrint { public void Print() { Console.WriteLine(ToString()); } } public class Program { public static void Main() { MyStruct s = new MyStruct(); s.Print(); } } ---- https://dotnetfiddle.net/lpXR1O But in D it doesn't appear possible. ---- import std.stdio; interface IPrint { void print(); } // Error: base classes are not allowed for struct, did you mean ;? struct MyStruct : IPrint // Error: base classes are not allowed for struct, did you mean ;? { void print() { writeln("MyStruct"); } } void main() { MyStruct s; s.Print(); } ---- https://run.dlang.io/is/j4xwla Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision? Thanks for your insight, MikeI think it simply hasn't been implemented, but I am not sure here because you could simply insert a `static assert` in there (and probably have something like `hasInterface!(Interface, YourStruct)`. Similarly multiple `alias this` is a request that often comes up.
Dec 29 2017
Structs are structs, classes are classes. C++ had the mixed model similar to what you suggested, we got it right and kept it nice and separate. This was done on purpose.
Dec 29 2017
On Friday, 29 December 2017 at 12:11:46 UTC, rikki cattermole wrote:Structs are structs, classes are classes.I'm talking about interfaces, which are neither structs nor classes.C++ had the mixed model similar to what you suggested, we got it right and kept it nice and separate. This was done on purpose.demonstrates. Mike
Dec 29 2017
On Friday, December 29, 2017 12:18:57 Mike Franklin via Digitalmars-d-learn wrote:On Friday, 29 December 2017 at 12:11:46 UTC, rikki cattermole wrote:Interfaces are related to classes and not structs. Structs do not have inheritance and do not implement interfaces in any way shape or form. Classes and interfaces are always references, whereas structs never are, and structs do not have virtual functions. Structs are either directly placed where they are (be it on the stack or inside an object that contains them), or they're placed on the heap and accessed via a pointer. As such, in D, structs are fundamentally different from classes or interfaces. If you want a function to accept multiple types of structs or classes which share the same API, then use templates and use the template constraint to restrict what the template accepts. That's what's done with ranges (e.g. with isInputRange and isForwardRange). - Jonathan M DavisStructs are structs, classes are classes.I'm talking about interfaces, which are neither structs nor classes.
Dec 29 2017
On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote:---- using System; interface IPrint { void Print(); } struct MyStruct : IPrint { public void Print() { Console.WriteLine(ToString()); } } public class Program { public static void Main() { MyStruct s = new MyStruct(); s.Print(); } } ---- https://dotnetfiddle.net/lpXR1O But in D it doesn't appear possible. ---- import std.stdio; interface IPrint { void print(); } // Error: base classes are not allowed for struct, did you mean ;? struct MyStruct : IPrint // Error: base classes are not allowed for struct, did you mean ;? { void print() { writeln("MyStruct"); } } void main() { MyStruct s; s.Print(); } ---- https://run.dlang.io/is/j4xwla Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision? Thanks for your insight, MikeThe problem is that interfaces are a runtime thing (e.g. you can cast a class to an interface) structs implement compile time interfaces via template duck typing (usually enforced via an if()). you could probably write a wrapper that introspected an interface and enforced that all members were implemented.
Dec 29 2017
On Fri, 29 Dec 2017 12:39:25 +0000, Nicholas Wilson wrote:On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote: The problem is that interfaces are a runtime thing (e.g. you can cast a class to an interface) structs implement compile time interfaces via template duck typing (usually enforced via an if()). you could probably write a wrapper that introspected an interface and enforced that all members were implemented.I've actually thought about doing this to get rid of a bunch of if qualifiers in my function declarations. `static interface {}` compiles but doesn't [currently] seem to mean anything to the compiler, but could be a hint to the programmer that nothing will directly implement it; it's a compile-time interface. This would provide a more generic way of doing stuff like `isInputRange`, etc.
Dec 29 2017
On 29/12/2017 12:59 PM, rjframe wrote:On Fri, 29 Dec 2017 12:39:25 +0000, Nicholas Wilson wrote:Or we could get signatures, which are even better still!On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote: The problem is that interfaces are a runtime thing (e.g. you can cast a class to an interface) structs implement compile time interfaces via template duck typing (usually enforced via an if()). you could probably write a wrapper that introspected an interface and enforced that all members were implemented.I've actually thought about doing this to get rid of a bunch of if qualifiers in my function declarations. `static interface {}` compiles but doesn't [currently] seem to mean anything to the compiler, but could be a hint to the programmer that nothing will directly implement it; it's a compile-time interface. This would provide a more generic way of doing stuff like `isInputRange`, etc.
Dec 29 2017
On Friday, 29 December 2017 at 13:08:38 UTC, rikki cattermole wrote:On 29/12/2017 12:59 PM, rjframe wrote:I was about to answer that interfaces could be used to define duck types conformity models but this would be a poor and useless addition, indeed, compared to signatures.On Fri, 29 Dec 2017 12:39:25 +0000, Nicholas Wilson wrote:Or we could get signatures, which are even better still!On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote: The problem is that interfaces are a runtime thing (e.g. you can cast a class to an interface) structs implement compile time interfaces via template duck typing (usually enforced via an if()). you could probably write a wrapper that introspected an interface and enforced that all members were implemented.I've actually thought about doing this to get rid of a bunch of if qualifiers in my function declarations. `static interface {}` compiles but doesn't [currently] seem to mean anything to the compiler, but could be a hint to the programmer that nothing will directly implement it; it's a compile-time interface. This would provide a more generic way of doing stuff like `isInputRange`, etc.
Dec 29 2017
On Friday, 29 December 2017 at 13:08:38 UTC, rikki cattermole wrote:On 29/12/2017 12:59 PM, rjframe wrote:+6666 for SML style signatures!On Fri, 29 Dec 2017 12:39:25 +0000, Nicholas Wilson wrote:Or we could get signatures, which are even better still![...]I've actually thought about doing this to get rid of a bunch of if qualifiers in my function declarations. `static interface {}` compiles but doesn't [currently] seem to mean anything to the compiler, but could be a hint to the programmer that nothing will directly implement it; it's a compile-time interface. This would provide a more generic way of doing stuff like `isInputRange`, etc.
Dec 29 2017
On Friday, 29 December 2017 at 12:59:21 UTC, rjframe wrote:On Fri, 29 Dec 2017 12:39:25 +0000, Nicholas Wilson wrote:Atila does something like this https://code.dlang.org/packages/conceptsOn Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote: The problem is that interfaces are a runtime thing (e.g. you can cast a class to an interface) structs implement compile time interfaces via template duck typing (usually enforced via an if()). you could probably write a wrapper that introspected an interface and enforced that all members were implemented.I've actually thought about doing this to get rid of a bunch of if qualifiers in my function declarations. `static interface {}` compiles but doesn't [currently] seem to mean anything to the compiler, but could be a hint to the programmer that nothing will directly implement it; it's a compile-time interface. This would provide a more generic way of doing stuff like `isInputRange`, etc.
Jan 01 2018
On Tue, 02 Jan 2018 00:54:13 +0000, Laeeth Isharc wrote:On Friday, 29 December 2017 at 12:59:21 UTC, rjframe wrote:Thanks; I actually started skimming through his repositories a couple of days ago, but didn't see this. --RyanOn Fri, 29 Dec 2017 12:39:25 +0000, Nicholas Wilson wrote: I've actually thought about doing this to get rid of a bunch of if qualifiers in my function declarations. `static interface {}` compiles but doesn't [currently] seem to mean anything to the compiler, but could be a hint to the programmer that nothing will directly implement it; it's a compile-time interface. This would provide a more generic way of doing stuff like `isInputRange`, etc.Atila does something like this https://code.dlang.org/packages/concepts
Jan 01 2018
On Tuesday, 2 January 2018 at 00:54:13 UTC, Laeeth Isharc wrote:On Friday, 29 December 2017 at 12:59:21 UTC, rjframe wrote:Glad you brought this up, looks quite useful.On Fri, 29 Dec 2017 12:39:25 +0000, Nicholas Wilson wrote:Atila does something like this https://code.dlang.org/packages/concepts[...]I've actually thought about doing this to get rid of a bunch of if qualifiers in my function declarations. `static interface {}` compiles but doesn't [currently] seem to mean anything to the compiler, but could be a hint to the programmer that nothing will directly implement it; it's a compile-time interface. This would provide a more generic way of doing stuff like `isInputRange`, etc.
Jan 02 2018
On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote:Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision?It's a design decision. Look carefully at structs vs. classes here: https://dlang.org/spec/struct.html There is no virtual methods table (VMT) for structs, no inheritance. Structs have value semantics. A variable with a type of some interface implies it's a pointer, with reference semantics and a VMT.
Dec 29 2017
On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote:---- using System; interface IPrint { void Print(); } struct MyStruct : IPrint { public void Print() { Console.WriteLine(ToString()); } } public class Program { public static void Main() { MyStruct s = new MyStruct(); s.Print(); } } ---- https://dotnetfiddle.net/lpXR1O But in D it doesn't appear possible. ---- import std.stdio; interface IPrint { void print(); } // Error: base classes are not allowed for struct, did you mean ;? struct MyStruct : IPrint // Error: base classes are not allowed for struct, did you mean ;? { void print() { writeln("MyStruct"); } } void main() { MyStruct s; s.Print(); } ---- https://run.dlang.io/is/j4xwla Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision? Thanks for your insight, Mikehttps://blogs.msdn.microsoft.com/abhinaba/2005/10/05/c-structs-and-interface/ no vtable means for example that you cannot back to something after extracting the interface (with classes you can always get back to Object) as in D, struct should really only be used for a custom type with value semantic.
Dec 29 2017
On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote:Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision? Thanks for your insight, MikeI think it's deliberate, structs are just plain dumb value types. If I remember correctly I think Remedy's Binderoo C++ bindings implemented C++ inheritance on top of structs. You might want to look at that. Or you could do C-style "inheritance" and slap some D magic on top of that. Some pseudo code: struct Base { enum SubType subtype; int someBaseField; } struct Child1 { Base base; // Must be first int foo; } struct Child2 { Base base; float bar; } Base b; Child1 c1; Child2 c2; base_doSomething(Base* b); child1_doSomething(Child1* c1); child2_doSomething(Child2* c2); base_doSomething(cast(Base*)&c1); switch(base.subtype) { case Child1: child1_doSomething(cast(Child1*)&b); break; case Child2: child2_doSomething(cast(Child2*)&b); break; } // add some alias this and other d things to smooth things out.
Dec 29 2017
On 12/29/17 7:03 AM, Mike Franklin wrote:Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision?It was deliberate, but nothing says it can't actually be done. All an interface call is, is a thunk to grab the actual object, and then a call to the appropriate function from a static vtable. It's pretty doable to make a fake interface. In fact, I'm pretty sure someone did just this, I have no idea how far back in the forums to search, but you can probably find it. Now, it would be nicer if the language itself supported it. And I don't see any reason why it couldn't be supported. The only issue I think could be an ABI difference between member calls of structs and classes, but I think they are the same. -Steve
Dec 30 2017
On Saturday, 30 December 2017 at 16:23:05 UTC, Steven Schveighoffer wrote:On 12/29/17 7:03 AM, Mike Franklin wrote:Don't forget to implement boxing/unboxing and then write a long blog post on all the dangers and negative effects of using interfaces with structs.Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision?It was deliberate, but nothing says it can't actually be done. All an interface call is, is a thunk to grab the actual object, and then a call to the appropriate function from a static vtable. It's pretty doable to make a fake interface. In fact, I'm pretty sure someone did just this, I have no idea how far back in the forums to search, but you can probably find it. Now, it would be nicer if the language itself supported it. And I don't see any reason why it couldn't be supported. The only issue I think could be an ABI difference between member calls of structs and classes, but I think they are the same. -Steve
Jan 02 2018
On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote:---- using System; interface IPrint { void Print(); } struct MyStruct : IPrint { public void Print() { Console.WriteLine(ToString()); } } public class Program { public static void Main() { MyStruct s = new MyStruct(); s.Print(); } } ---- https://dotnetfiddle.net/lpXR1O But in D it doesn't appear possible. ---- import std.stdio; interface IPrint { void print(); } // Error: base classes are not allowed for struct, did you mean ;? struct MyStruct : IPrint // Error: base classes are not allowed for struct, did you mean ;? { void print() { writeln("MyStruct"); } } void main() { MyStruct s; s.Print(); } ---- https://run.dlang.io/is/j4xwla Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision? Thanks for your insight, MikeYou want wrap: https://dlang.org/phobos/std_typecons.html#wrap
Jan 01 2018