简体   繁体   English

用Derived类覆盖属性。

[英]Override property with Derived class.

I'm trying to separate out a big classes I had into 3 separate classes: 我正在尝试将一个大类分成3个单独的类:

A base class with shared functionality 具有共享功能的基类

A server class with server only functionality 具有仅服务器功能的服务器类

A client class with client only functionality 具有仅客户端功能的客户端类

The problem I'm having is I cannot overload properties with a derived class. 我遇到的问题是我无法使用派生类重载属性。

Below I've prepared a code sample of a base classes and their server counterparts. 下面,我准备了基类及其对应服务器的代码示例。

I'm way off somewhere but I was expecting to be able to call "base class" functions and them to work with the overridden derived class. 我离某处很远,但是我希望能够调用“基类”函数,并且它们可以与重写的派生类一起使用。

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() { }
}

Your ovveriden property must respect exact signature of the base class property. 您的ovveriden属性必须尊重基类属性的确切签名。

In your specific case, you need 在您的特定情况下,您需要

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

    ....
}

like: 喜欢:

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

    ....
}

note that it overlaps with the property name itself: not good , better to change it to avoid future confusion in naming 请注意,它与属性名称本身重叠: 不好 ,最好更改它以避免将来在命名上造成混淆

The problem is as Tigran explained in the signature of the property. 正如提格伦在物业签名中所解释的那样。 If you want to custom-type it per derived class you can use generics. 如果要为每个派生类自定义类型,则可以使用泛型。

public class ServerBattleField : Battlefield<GameType>
{
}

Where Battlefield is: Battlefield在哪里:

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

You could force T to derive from a base Game class or interface. 您可以强制T从基本Game类或接口派生。

There is no need to derive that property any more. 不再需要继承该属性。

Using Generics is a good approach, your Battlefield classes will look like this: 使用泛型是一种很好的方法,您的Battlefield类将如下所示:

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);
    }
}

You cannot overload something that differs only by return type. 您不能重载仅返回类型不同的内容。 Here's why: 原因如下:

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

You can override something with an identical signature, and since ServerBattleField inherits from BattleField , there is no issue with return an object of type ServerBattleField from the BattleField property. 您可以覆盖具有相同签名的内容,并且由于ServerBattleField继承自BattleField ,因此从BattleField属性返回类型为ServerBattleField的对象没有问题。 The code that uses it will just have to know to cast it to the correct type if it needs ServerBattleField functionality specifically. 如果特别需要ServerBattleField功能,则使用它的代码仅需知道将其转换为正确的类型即可。

Also, note that any code that accesses ServerGame 's BattleField property, even though it's defined as returning a BattleField object, it will use the any derived class's overriden functionality. 另外,请注意,任何访问ServerGameBattleField属性的代码,即使被定义为返回BattleField对象,也使用任何派生类的重写功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM