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