views:

78

answers:

3

hi!

imagine there are two interfaces arranged via composite pattern, one of them has a dispose method among other methods:

interface IComponent extends ILeaf {
    ...
    function dispose() : void;
}

interface ILeaf {
    ...
}

some implementations have some more things in common (say an id) so there are two more interfaces:

interface ICommonLeaf extends ILeaf {
    function get id() : String;
}

interface ICommonComponent extends ICommonLeaf, IComponent {
}

so far so good. but there is another interface which also has a dispose method:

interface ISomething {
    ...
    function dispose() : void;
}

and ISomething is inherited by ICommonLeaf:

interface ICommonLeaf extends ILeaf, ISomething {
    function get id() : String;
}

As soon as the dispose method is invoked on an instance which implements the ICommonComponent interface, the compiler fails with an ambiguous reference error because ISomething has a method called dispose and ILeaf also has a dispose method, both living in different interfaces (IComponent, ISomething) within the inheritace tree of ICommonComponent.

I wonder how to deal with the situation if

  • the IComponent, the ILeaf and the ISomething can't change.
  • the composite structure must also work for for the ICommonLeaf & ICommonComponent
  • implementations and the ICommonLeaf & ICommonComponent must conform to the ISomething type.

this might be an actionscript-3 specific issue. i haven't tested how other languages (for instance java) handle stuff like this.

A: 

As far as I'm aware, there's no neat way to deal with this problem in Actionscript.

The only thing I can think of is refactoring your interfaces to avoid name clashes, which, admitedly, it's not always possible.

Don't know about Java, but C# has a way to handle this through explicit interface implementation.

Juan Pablo Califano
+1  A: 

It seems casting solves the ambiguity even though it's far from neat.

class SomeComponent implements ICommonComponent {}

var c : ICommonComponent = new SomeComponent();
trace(ISomething(c).dispose()); //compiles
trace(IComponent(c).dispose()); //compiles
trace(c.dispose());    //fails
maxmc
+2  A: 

You are searching for a solution to the Diamond Problem. C# has an approach to this but basically I would factor the method "dispose" out of your interfaces and create a new "IDisposable".

If the same name like "id" is used twice, it looks like a problem in your code with an ambiguous name. We started to add prefixes to properties and methods. Imagine you have a property "name" that belongs to two different things. Like the "displayName" and the "uniqueName".

This also helps with auto completion. If a DisplayObject is an ILayoutObject and yout type displayObject.layout you get everything layout releated.

Joa Ebert
yes, an IDisposable interface would certainly solve the issue, but unfortunately I don't have access to the IComponent and ISomething interfaces to extract dispose.
maxmc
+1 for the diamond problem hint
maxmc