Abstract Classes vs Interfaces

Jonathan M Davis jmdavisprog at gmail.com
Wed Jul 7 14:07:39 PDT 2010


On Wednesday, July 07, 2010 11:38:09 Robert Jacques wrote:
> On Wed, 07 Jul 2010 13:36:16 -0400, Jonathan M Davis
> 
> <jmdavisprog at gmail.com> 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


More information about the Digitalmars-d mailing list