digitalmars.D - Self-reference in interface definition
- Jason House (12/12) May 15 2007 While the code below does not compile, I believe that it should be
- Chris Nicholson-Sauls (15/29) May 15 2007 The problem is specifically with the X in opAssign's parameters. One of...
- Jason House (21/58) May 20 2007 The code below is more what I'm trying to do. Obviously, the sample
- Bill Baxter (14/73) May 20 2007 Object 'a' is not a B, so that's not going to work generally.
- Jason House (26/102) May 20 2007 That's why I want to be able to assign any instance of X to b. I'll
While the code below does not compile, I believe that it should be allowed. Requiring something that implements an interface to accept other objects conforming to the interface should always be allowed. The specific problem below makes perfect sense to disallowed for classes, but does not for interfaces. == test.d == interface X{ X opAssign(X); } == gdc output == test.d:2: function test.X.opAssign identity assignment operator overload is illegal
May 15 2007
Jason House wrote:While the code below does not compile, I believe that it should be allowed. Requiring something that implements an interface to accept other objects conforming to the interface should always be allowed. The specific problem below makes perfect sense to disallowed for classes, but does not for interfaces. == test.d == interface X{ X opAssign(X); } == gdc output == test.d:2: function test.X.opAssign identity assignment operator overload is illegalThe problem is specifically with the X in opAssign's parameters. One of the restrictions on assignment operator overloading is that any type X cannot have an overloaded assignment for X or a derivative of X. From the specs: """The assignment operator cannot be overloaded for rvalues that can be implicitly cast to the lvalue type.""" Nor may an opAssign have more than one parameter. I assume your intention was to have code like: X x1 = new A; X x2 = new B; x1 = x2; Where the assignment at the end copies data from x2 to x1 rather than making them the same reference. For that you will need an explicit copy(X) method instead. Or maybe you wanted something else, but that was what first came to mind. -- Chris Nicholson-Sauls
May 15 2007
Chris Nicholson-Sauls wrote:Jason House wrote:The code below is more what I'm trying to do. Obviously, the sample code is a gross simplification. A and B are optimized for two different types of usage (and may add extra accessors and manipulators), but fundamentally represent the same type of data. Even though algorithms will get written to use A or B explicitly, I want to be able to share data between them. Converting A to B and B to A makes a lot of sense. I wanted the interface to require that functionality of anything that extends the interface... And requiring explicit knowledge of all classes that extend the interface isn't generic enough for me. == test.d == interface X{} class A:X{} class B:X{} int main(char[][] args){ A a = new A(); B b = a; } == gdc output == test.d:7: Error: cannot implicitly convert expression (a) of type test.A to test.BWhile the code below does not compile, I believe that it should be allowed. Requiring something that implements an interface to accept other objects conforming to the interface should always be allowed. The specific problem below makes perfect sense to disallowed for classes, but does not for interfaces. == test.d == interface X{ X opAssign(X); } == gdc output == test.d:2: function test.X.opAssign identity assignment operator overload is illegalThe problem is specifically with the X in opAssign's parameters. One of the restrictions on assignment operator overloading is that any type X cannot have an overloaded assignment for X or a derivative of X. From the specs: """The assignment operator cannot be overloaded for rvalues that can be implicitly cast to the lvalue type.""" Nor may an opAssign have more than one parameter. I assume your intention was to have code like: X x1 = new A; X x2 = new B; x1 = x2; Where the assignment at the end copies data from x2 to x1 rather than making them the same reference. For that you will need an explicit copy(X) method instead. Or maybe you wanted something else, but that was what first came to mind. -- Chris Nicholson-Sauls
May 20 2007
Jason House wrote:Chris Nicholson-Sauls wrote:Object 'a' is not a B, so that's not going to work generally. It sounds what you want may be better handled by object composition. Let X be the thing that represents the core data and just make it a member of A and B. class X {} class A { X x; } class B { X x; } Then you can add a method to change A or B's X member. If you also need to be able to treat A and B polymorphically, then you can make a simple hasX interface that exposes X's basic attributes. But I didn't see anywhere that you said you needed to do so. Or you could make X the base class for both A and B. --bbJason House wrote:The code below is more what I'm trying to do. Obviously, the sample code is a gross simplification. A and B are optimized for two different types of usage (and may add extra accessors and manipulators), but fundamentally represent the same type of data. Even though algorithms will get written to use A or B explicitly, I want to be able to share data between them. Converting A to B and B to A makes a lot of sense. I wanted the interface to require that functionality of anything that extends the interface... And requiring explicit knowledge of all classes that extend the interface isn't generic enough for me. == test.d == interface X{} class A:X{} class B:X{} int main(char[][] args){ A a = new A(); B b = a; }While the code below does not compile, I believe that it should be allowed. Requiring something that implements an interface to accept other objects conforming to the interface should always be allowed. The specific problem below makes perfect sense to disallowed for classes, but does not for interfaces. == test.d == interface X{ X opAssign(X); } == gdc output == test.d:2: function test.X.opAssign identity assignment operator overload is illegalThe problem is specifically with the X in opAssign's parameters. One of the restrictions on assignment operator overloading is that any type X cannot have an overloaded assignment for X or a derivative of X. From the specs: """The assignment operator cannot be overloaded for rvalues that can be implicitly cast to the lvalue type.""" Nor may an opAssign have more than one parameter. I assume your intention was to have code like: X x1 = new A; X x2 = new B; x1 = x2; Where the assignment at the end copies data from x2 to x1 rather than making them the same reference. For that you will need an explicit copy(X) method instead. Or maybe you wanted something else, but that was what first came to mind. -- Chris Nicholson-Sauls
May 20 2007
Bill Baxter wrote:Jason House wrote:That's why I want to be able to assign any instance of X to b. I'll leave it up to B to use the access methods of the X instance to build its internal representation.Chris Nicholson-Sauls wrote:Object 'a' is not a B, so that's not going to work generally.Jason House wrote:The code below is more what I'm trying to do. Obviously, the sample code is a gross simplification. A and B are optimized for two different types of usage (and may add extra accessors and manipulators), but fundamentally represent the same type of data. Even though algorithms will get written to use A or B explicitly, I want to be able to share data between them. Converting A to B and B to A makes a lot of sense. I wanted the interface to require that functionality of anything that extends the interface... And requiring explicit knowledge of all classes that extend the interface isn't generic enough for me. == test.d == interface X{} class A:X{} class B:X{} int main(char[][] args){ A a = new A(); B b = a; }While the code below does not compile, I believe that it should be allowed. Requiring something that implements an interface to accept other objects conforming to the interface should always be allowed. The specific problem below makes perfect sense to disallowed for classes, but does not for interfaces. == test.d == interface X{ X opAssign(X); } == gdc output == test.d:2: function test.X.opAssign identity assignment operator overload is illegalThe problem is specifically with the X in opAssign's parameters. One of the restrictions on assignment operator overloading is that any type X cannot have an overloaded assignment for X or a derivative of X. From the specs: """The assignment operator cannot be overloaded for rvalues that can be implicitly cast to the lvalue type.""" Nor may an opAssign have more than one parameter. I assume your intention was to have code like: X x1 = new A; X x2 = new B; x1 = x2; Where the assignment at the end copies data from x2 to x1 rather than making them the same reference. For that you will need an explicit copy(X) method instead. Or maybe you wanted something else, but that was what first came to mind. -- Chris Nicholson-SaulsIt sounds what you want may be better handled by object composition. Let X be the thing that represents the core data and just make it a member of A and B. class X {} class A { X x; } class B { X x; }The simplest way to implement interface X is as a pair of integers. While this would work, certain applications can be implemented much more quickly by using only one... But how to map it down to one is fundamentally different. When lots of manipulation is done, the streamlined implementations provide a significant performance gain for specific classes of implementations. I want to allow optimized implementations. Embedding a basic implementation of X inside (in addition to an optimized implementation) only increases the work of maintaining it and defeats the purpose.Then you can add a method to change A or B's X member. If you also need to be able to treat A and B polymorphically, then you can make a simple hasX interface that exposes X's basic attributes. But I didn't see anywhere that you said you needed to do so. Or you could make X the base class for both A and B.if A and B extend a base class X, the data associated with X will go completely unused and both A and B will need to override X's member functions to do alternate behavior. Rather than have X contain data and function implementations that go unused by those that extend it, I'm using an interface. Besides, if X is a base class or an interface, generically forcing everything that extends X (A and B in the example) to be constructed from an X is impossible... You can't define a (copy) constructor of X that accepts X as an input. It's possible to do workarounds such as defining extra classes and interfaces to trick the compiler, but I really hate having to trick a compiler. I did enough of that in C++!
May 20 2007