使用Derived类覆盖属性。

时间:2014-08-25 14:54:40

标签: c# oop inheritance

我正在尝试将我所拥有的大班级分成3个单独的班级:

具有共享功能的基类

仅具有服务器功能的服务器类

仅具有客户端功能的客户端类

我遇到的问题是我无法使用派生类重载属性。

下面我准备了基类及其服务器对应的代码示例。

我离开了某个地方,但我希望能够调用“基类”函数,并且它们可以使用重写的派生类。

public class Battlefield
{
    public Tile[,] Tiles { get; set; }
    public virtual Game Game { get; set; }

    public Battlefield(int sizeX, int sizeY, Game game)
    {
        Tiles = new Tile[sizeX, sizeY];
        Game = game;
    }

    public Tile GetTile(int x, int y)
    {
        return Tiles[x, y];
    }
}

public class ServerBattleField : Battlefield
{
    public override ServerGame Game  { get; set; }

    public ServerBattleField(int sizeX, int sizeY, ServerGame game) : base(sizeX, sizeY, game)
    {
    }

    public void DoSomethingServerSpecific()
    {
        Game.DoSomethingServerSpecialWithTile(10,5);
    }
}

public class Game
{
    public virtual Battlefield Battlefield {get;set;}

    public Game(int sizeX, int sizeY)
    {
        Battlefield = new Battlefield(sizeX,sizeY,this);
    }

    public void DoSomethingWithTile(int x, int y)
    {
        Battlefield.GetTile(x,y).DoSomethingWithTile();
    }


}

public class ServerGame : Game
{
    public override ServerBattleField Battlefield {get;set;}

    public ServerGame(int sizeX, int sizeY)
        : base(sizeX, sizeY)
    {
    }

    public void DoSomethingServerSpecialWithTile(int x, int y)
    {
        Battlefield.GetTile(x, y).DoSomethingWithTile();
        Battlefield.GetTile(x, y).DoSomethingSpecialWithTile();
    }

}

public class Tile {
    public void DoSomethingWithTile() { }
    public void DoSomethingSpecialWithTile() { }
}

4 个答案:

答案 0 :(得分:3)

您的ovveriden属性必须尊重基类属性的完全签名。

在您的具体情况下,您需要

public class ServerBattleField : Battlefield
{
    public override ServerGame Game  { get; set; } //CHANGE TO RETURN TYPE GAME

    ....
}

喜欢:

public class ServerBattleField : Battlefield
{
    public override Game Game  { get; set; } //CHANGE TO RETURN TYPE GAME

    ....
}

请注意,它与属性名称本身重叠:不好,最好更改它以避免将来在命名方面造成混淆

答案 1 :(得分:1)

问题是Tigran在财产签名中解释的。如果要为每个派生类自定义类型,可以使用泛型。

public class ServerBattleField : Battlefield<GameType>
{
}

Battlefield的位置:

public class Battlefield<T>
{
    public T Game { get; set; }
}

您可以强制T从基础Game类或接口派生。

不再需要派生该属性。

答案 2 :(得分:1)

使用Generics是一种很好的方法,你的战地类将如下所示:

public class Battlefield<T> where T: Game
{
    public Tile[,] Tiles { get; set; }
    public T Game { get; set; }

    public Battlefield(int sizeX, int sizeY, T game)
    {
        Tiles = new Tile[sizeX, sizeY];
        Game = game;
    }

    public Tile GetTile(int x, int y)
    {
        return Tiles[x, y];
    }
}

public class ServerBattleField : Battlefield<ServerGame> 
{

    public ServerBattleField(int sizeX, int sizeY, ServerGame game)
        : base(sizeX, sizeY, game)
    {
    }

    public void DoSomethingServerSpecific()
    {
        Game.DoSomethingServerSpecialWithTile(10, 5);
    }
}

答案 3 :(得分:0)

你不能重载只有返回类型不同的东西。这就是原因:

ServerGame oServer = new ServerGame();
BattleField oBF = oServer.BattleField; //No way to know which BattleField property to return.

您可以覆盖具有相同签名的内容,并且由于ServerBattleField继承自BattleField,因此返回类型为ServerBattleField的对象没有问题BattleField属性。如果需要ServerBattleField功能,使用它的代码只需知道将其强制转换为正确的类型。

另请注意,访问ServerGame BattleField属性的任何代码,即使它被定义为返回BattleField对象,使用任何派生类的覆盖功能。