面向对象编程正确使用界面

时间:2014-01-03 15:45:46

标签: c# oop

我正在尝试为游戏设计几个课程,但我不确定我做得对。

我有两个课程:ActorBuilding。 它们有几个子类:PolicemanFiremanPoliceStationFireStation

我希望能够将所有这些项放在一个列表中以便稍后迭代,所以我添加了一个基类:GameEntity
所以我拥有的是:

public abstract class GameEntity: 
{
    public GameEntity()
    {

    }       
}

public class Actor: GameEntity
{
    public int _speed;
    public TileSprite _UI;

    public Actor()
    {

    }

    public bool CollidesWith(Vector2 pos)
    {
        //Do stuff here
    }

    public virtual void OnClick()
    {
        //Do stuff here
    }

    public void DoActing()
    {

    }
}

public class Policeman: Actor
{
    public Policeman()
    {
        _speed = 10;
    }

    public override void OnClick()
    {
        //Do stuff
    }
}

public class Building: GameEntity
{
    public TileSprite _UI;

    public Building()
    {

    }

    public bool CollidesWith(Vector2 pos)
    {
        //Do stuff here
    }

    public virtual void OnClick()
    {
        //Do stuff here
    }

    public void DoBuilding()
    {

    }
}

public class PoliceStation: Building
{
    public PoliceStation()
    {

    }

    public override void OnClick()
    {
        //Do stuff
    }
}

现在,我希望能够做到这一点:

List<GameEntity> Entities = new List<GameEntity>();

Actor a1 = new PoliceMan();
Building b1 = new PoliceStation

Entities.Add(a1);
Entities.Add(b1);

foreach(GameEntity ent in Entities)
{
    if (ent.CollidesWith(something))
    {
        ent.OnClick();

        //If Actor then do 
        ent.DoActing();

        //If Building then do
        ent.DoBuilding();
    }
}

现在,为了做最后一点,我最好是实现一个包含OnClickCollidesWith的接口,还是可以继承? 如果是这样,我该怎么做?

干杯。

4 个答案:

答案 0 :(得分:2)

这只是为了给你一个想法,我想这就是你需要的。

 public interface IGameEntity
    {
        bool CollidesWith();
        void OnClick();
        void DoActing();
    }
  public class Actor : IGameEntity { //Interface implemented }
  public class Building: IGameEntity { //Interface implemented }
  public class Policeman: IGameEntity { //Interface implemented }
  public class Fireman: IGameEntity { //Interface implemented }
  public class FireStation: IGameEntity { //Interface implemented }

在您的客户端对象中,只需执行以下操作:

List<IGameEntity> entities = new List<IGameEntity>()
{
    new Actor(), 
    new Building(), 
    new Policeman(), 
    new Fireman(), 
    new Fireman()
};
foreach (IGameEntity entity in entities)
{
    entity.CollidesWith();
    entity.OnClick();
    entity.DoActing();
}

答案 1 :(得分:1)

将虚拟doStuff()添加到GameEntity并将其覆盖在子类中,而不是使用DoActingDoBuilding之类的唯一方法名称,然后从循环中调用它应该执行你想要什么。

答案 2 :(得分:1)

去这里的方法数量。 如果可以单击所有GameEntities,则可以将OnClick事件属性添加到基类。

如果不是,那么我将有一个接口IClick,然后在可点击的实体上实现它。

碰撞,取决于。 建筑物不会移动,因此它们不会与任何物体发生碰撞,但它们可能会发生碰撞,因此您可能需要做一个损坏程序,然后建议一个破坏的,例行的修理例程。

没有正确答案,但是 三个代码气味将是一个 没有任何内容的基类。

非常深的继承层次结构(我的书中有两个以上的级别引起怀疑) 所以如果你开始看到GameEntity - &gt; BuildingEntity - &gt; ActiveBuildingEntity - &gt;可修复的建筑实体,你将陷入混乱,即将变得更加混乱。

最重要的是一个没有做任何方法的基类只存在,因为你需要在某些后代中添加行为(覆盖)。

不要害怕拥有一些接口。 IClick,ICollision,IDamage,IRepair等。这比暗示建筑物可能撞到汽车更好。

答案 3 :(得分:1)

你可以这样做:

    public interface IGameEntity
    {
        void OnClick();
        bool CollidesWith(Vector2 pos);
        void Do();
    }

    public abstract class Actor: IGameEntity
    {
        public int _speed;
        public TileSprite _UI;

        public virtual bool CollidesWith(Vector2 pos)
        {
            //Do stuff here
        }

        // can be marked virtual with implementation if you want a default
        // this way base classes will be forced to implement their own implementation
        public abstract void OnClick();

        // can be marked virtual with implementation if you want a default
        // this way base classes will be forced to implement their own implementation
        public abstract void Do();
    }

    public class Policeman: Actor
    {
        public Policeman()
        {
            _speed = 10;
        }

        public override void OnClick()
        {
            //Do stuff
        }

        public override void Do()
        {
            //Do Acting for Police
        }
    }

    public abstract class Building: IGameEntity
    {
        public TileSprite _UI;

        public bool CollidesWith(Vector2 pos)
        {
            //Do stuff here
        }

        public abstract void OnClick();

        public abstract void Do();
    }

    public class PoliceStation: Building
    {
        public PoliceStation()
        {

        }

        public override void OnClick()
        {
            //Do stuff
        }

        public override void Do()
        {
            // Do Building
        }
    }

如果游戏实体只是一个界面,则无需将其作为抽象类。如果Actor和Building永远不能作为一个独立的对象存在,那么它们应该是抽象的。如果DoActing,DoBuilding和OnClick必须被基类覆盖,那么你可以在actor和Building中将它们标记为抽象。

我遵循norlesh的建议只有一种方法Do.你也可以让Actor和Building有自己的抽象方法,而IGameEntity则没有Do.然后你会放一个if语句并检查每个对象是否属于类型构建器,然后他们将运行构建,如果是类型actor,则运行act。

我认为使用一种方法的方法更好,因为你消除了一步。从设计的角度来看,我不确定,但无论如何对我来说都是一样的。

List<IGameEntity> Entities = new List<IGameEntity>();

Actor a1 = new PoliceMan();
Building b1 = new PoliceStation();

Entities.Add(a1);
Entities.Add(b1);

foreach(IGameEntity ent in Entities)
{
    if (ent.CollidesWith(something))
    {
        ent.OnClick();

        ent.Do();
    }
}