On Wed, 07 Jul 2010 17:07:39 -0400, Jonathan M Davis <[email protected]> wrote:

On Wednesday, July 07, 2010 11:38:09 Robert Jacques wrote:
On Wed, 07 Jul 2010 13:36:16 -0400, Jonathan M Davis

<[email protected]> wrote:
>> Consider the following:
>>
>> interface A { final void foobar() { writeln("A"); } }
>> interface B { final void foobar() { writeln("B"); } }
>>
>> class C : A, B {}
>>
>> void main(string[] args) {
>>
>>      C c = new C;
>>      c.foobar;
>>
>> }
>>
>> What does foobar print?
>> (This has been filed as bug 4435:
>> http://d.puremagic.com/issues/show_bug.cgi?id=4435)
>
> I believe that per TDPL, you would have to call these with eithe
> c.A.foobar() or
> c.B.foobar() but that c.foobar() is not allowed. If it is allowed at
> present,
> it's definitely a bug. However, it's a bug in the implementation rather
> than the
> language spec.
>
> - Jonathan M Davis

TDPL Page 215-216, mentions function hijacking of a final function by the implementor, which is listed as an error and detected correctly. Function hijacking of static functions by the implementor is not handled correctly.
It also specifically mentions that c.A.foobar() is not the correct, nor
ideal syntax. Indeed, it doesn't currently compile.

That's talking about private final functions in an interface. Read section 6.9.3
on pages 217 - 218.

1. If you have a method x() which is in two different interfaces and non-final in both, then when a class implements both interfaces, it's single method x()
implements both interfaces x() method simultaneously.

interface A { void x(); }
interface B { void x(); }

class C : A, B { void x() { /* implements both */ } }

void main()
{
    C c = new C();
    c.x(); // called like this
}


2. If you have a method x() which is two different interfaces and final in both, then you can't implement x() in a class which implements both interfaces. You also can't call it like c.x() because the compiler wouldn't know which to call.
You have to specify which interface it's being called for.

interface A { final void x() { /*do something*/ }
interface B { final void x() { /*do something else*/; }

class C : A, B { /* cannot implement x()*/ }

void main()
{
    C c = new C();
    c.A.x(); // called like this to get A's version
    c.B.x(); // called like this to get B's version
}


3. The third case is when the method is final in one interface and not in the
other. TDPL doesn't say what happens in this case. C wouldn't be able to
implement x() because it would be final in one of the interfaces, but I'm not sure if that means the other interface's x() would be used in that case or if you couldn't implement both interfaces together. My guess is the latter, but
TDPL doesn't say.

interface A { final void x() { /*do something*/ }
interface B { void x(); }

class C : A, B { /* Is it legal to implement both interfaces in this case? */ }


I don't know what exactly dmd does in all cases at this point, but TDPL is quite clear that if a class implements two interfaces that both have a final method with the same name, then if you're calling that method using the class, you have
to specify which interface's method you're calling.

- Jonathan M Davis

Thanks for the page numbers. (And I'm suddenly lamenting my slow reading of TDPL). Anyways, I think the above makes perfect sense, but none of it is implemented in DMD at this point.

Reply via email to