Self-reference in interface definition

Bill Baxter dnewsgroup at billbaxter.com
Sun May 20 12:08:52 PDT 2007


Jason House wrote:
> Chris Nicholson-Sauls wrote:
>> 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 illegal
>>
>> The 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
> 
> 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;
> }

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.

--bb



More information about the Digitalmars-d mailing list