Is it ok to reference an abstract class in interface?

171 Views Asked by At

I am trying to write a little Entity-Component based game framework for myself. I just encountered an logic problem with my base class system.

The thing is I have an two things, Entities ( that can contain other entities and component ), and Components ( they are attached to certain entity ).

So I made two interfaces :

interface IEntity
interface IComponent

And I made a abstract classes for each

public class Component implements IComponent
public class Entity extends Sprite implements IEntity, IComponent

The problem is that in IEntity interface I have an function:

function addComponent( e:Entity )

The reason the argument type i Entity, is because then in Component I need to reference to the entity functions that it inherits from Sprite ( I cannot do that with IEntity type ).

But it seems that Flash Develop treats it as an error ( implementation of this function in Entity class ). Am I doing something wrong?

EDIT :

This are the interfaces:

public interface IComponent
{
    function get parentGameObject() : IEntity;
    function set parentGameObject( v:IEntity ) : void;
    function init() : void;
    function dispose() : void;
}

public interface IEntity
{
    function addComponent( c:IComponent ) : IComponent;
    function removeComponent( c:IComponent ) : Boolean;
    function getComponent( type:Class ) : IComponent;
    function hasComponentOfType( type:Class ) : Boolean;
    function addGameObject( child:Entity ) : void;  
}

Then my abstract Entity class implements both of this interfaces + extends from DisplayObjectContainer because each Entity needs the functionality of rendering itself and its child Entities.

The problem is that :

public function addGameObject( e:Entity ) : void {
    m_components.push( v );

    this.addChild( v );
    v.gameObject = this;
    v.init();
}

seems to be invalid, and the error is : interface method addGameObject in interface IEntity is implemented with incompatibile signature in class Entity.

And the reason I want to use e:Entity and not e:IEntity is because I am using this.addChild( v ), which belongs to DisplayObjectContainer.

Hope that clears my question.

2

There are 2 best solutions below

1
On

I still can't see why this error is thrown, the implementation of addGameObject looks ok so far (I assume the usage of v is a problem that just exist in the example code?), though the parameter name differs from the interface definition where it's child instead of e, however AFAIK this is valid in AS3, nonetheless try using the name as defined in the interface.

And regarding the actual question, of course the answer depends. Generally you can reference whatever classes you like in an interface, the only problem here should be design patterns.

If you want to continue programming against interfaces, then you could simply create an game object interface that forces to implement the addChild method, something like this:

import flash.display.DisplayObject;

public interface IGameObject extends IComponent, IEntity
{
    function addChild(child:DisplayObject):DisplayObject;
}

Change your IEntity interface, your addGameObject and Entity implementation accordingly and you should be good to go:

public interface IEntity
{
    ...
    function addGameObject( child:IGameObject ) : void;  
}
public function addGameObject( child:IGameObject ) : void {
    ...
}
public class Entity extends Sprite implements IGameObject 

Though you might want to rename Entity to something like GameObject in order to avoid confusion.

0
On

This is how I solved this problem for now:

Three basic interfaces for each GameObject functionallity:

public interface IComponent
{
    function get gameObject() : IGameObject;
    function set gameObject( v:IGameObject ) : void;
    function init() : void;
    function dispose() : void;  
}

public interface IDisplayObjectContainer
{
    function get displayContainer() : DisplayObjectContainer;
}

public interface IEntity
{
    function addComponent( c:IComponent ) : IComponent;
    function removeComponent( c:IComponent ) : Boolean;
    function getComponent( type:Class ) : IComponent;
    function hasComponentOfType( type:Class ) : Boolean;    
}

And my compound GameObject interface for now is extending all of this functionallity:

public interface IGameObject extends IEntity, IComponent, IDisplayObjectContainer
{
        function addGameObject( g:IGameObject ) : void;
}