Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用派生类重写属性。_C#_Oop_Inheritance - Fatal编程技术网

C# 使用派生类重写属性。

C# 使用派生类重写属性。,c#,oop,inheritance,C#,Oop,Inheritance,我试着把我上过的一个大班分为三个班: 具有共享功能的基类 具有仅服务器功能的服务器类 具有仅客户端功能的客户端类 我遇到的问题是我不能用派生类重载属性 public class Battlefield { public Tile[,] Tiles { get; set; } public virtual Game Game { get; set; } public Battlefield(int sizeX, int sizeY, Game game) {

我试着把我上过的一个大班分为三个班:

具有共享功能的基类

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

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

我遇到的问题是我不能用派生类重载属性

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() { }
}
下面,我准备了一个基类及其对应服务器的代码示例

我离某个地方很远,但我希望能够调用“基类”函数,并将它们用于重写的派生类

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

    ....
}
请注意,它与属性名称本身重叠:不好,最好更改它以避免将来在命名时出现混淆

您的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

    ....
}

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

问题如Tigran在属性签名中所述。如果您想自定义每个派生类的类型,可以使用泛型

public class ServerBattleField : Battlefield<GameType>
{
}
您可以强制
T
从基本
游戏
类或接口派生


不再需要派生该属性。

问题如Tigran在属性签名中解释的那样。如果您想自定义每个派生类的类型,可以使用泛型

public class ServerBattleField : Battlefield<GameType>
{
}
您可以强制
T
从基本
游戏
类或接口派生


不再需要派生该属性。

使用泛型是一种很好的方法,您的战场类将如下所示:

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);
    }
}
T:游戏所在的公共级战场
{
公共磁贴[,]磁贴{get;set;}
公共T博弈{get;set;}
公共战场(智力游戏,智力游戏,T游戏)
{
瓷砖=新瓷砖[sizeX,sizeY];
游戏=游戏;
}
公共磁贴GetTile(int x,int y)
{
返回瓷砖[x,y];
}
}
公共类:战场
{
公共服务器战场(int-sizeX、int-sizeY、ServerGame游戏)
:base(sizeX、sizeY、game)
{
}
public void DoSomethingServerSpecific()
{
游戏。dosomethingserverSpecialWithile(10,5);
}
}

使用泛型是一种很好的方法,您的战场类如下所示:

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);
    }
}
T:游戏所在的公共级战场
{
公共磁贴[,]磁贴{get;set;}
公共T博弈{get;set;}
公共战场(智力游戏,智力游戏,T游戏)
{
瓷砖=新瓷砖[sizeX,sizeY];
游戏=游戏;
}
公共磁贴GetTile(int x,int y)
{
返回瓷砖[x,y];
}
}
公共类:战场
{
公共服务器战场(int-sizeX、int-sizeY、ServerGame游戏)
:base(sizeX、sizeY、game)
{
}
public void DoSomethingServerSpecific()
{
游戏。dosomethingserverSpecialWithile(10,5);
}
}
您不能重载仅按返回类型不同的内容。原因如下:

ServerGame oServer = new ServerGame();
BattleField oBF = oServer.BattleField; //No way to know which BattleField property to return.
您可以覆盖具有相同签名的内容,并且由于
serverbattle
继承自
battle
,因此从
battle
属性返回类型为
serverbattle
的对象没有问题。如果使用它的代码特别需要
serverbattle
功能,则只需知道如何将其转换为正确的类型即可

另外,请注意,任何访问
ServerGame
battled
属性的代码,即使定义为返回
battled
对象,它也将使用任何派生类的重写功能。

不能重载仅按返回类型不同的内容。原因如下:

ServerGame oServer = new ServerGame();
BattleField oBF = oServer.BattleField; //No way to know which BattleField property to return.
您可以覆盖具有相同签名的内容,并且由于
serverbattle
继承自
battle
,因此从
battle
属性返回类型为
serverbattle
的对象没有问题。如果使用它的代码特别需要
serverbattle
功能,则只需知道如何将其转换为正确的类型即可


另外,请注意,任何访问
ServerGame
battle
属性的代码,即使它定义为返回
battle
对象,它将使用任何派生类的重写功能。

对不起,我应该发布我看到它们必须匹配的错误,我只是不太确定该如何操作。如果
ServerGame
继承自
Game
,您仍然可以返回
ServerGame
的实例,但它将作为
Game
返回。以您的示例为例,那么,这不允许我使用在ServerGame中声明的函数而不使用强制转换吗?您可以返回ServerGame的实例,因为它是从游戏派生的,它将被上强制转换为基类类型而没有问题。所以我需要使用(ServerGame)ServerGame中要使用的游戏以及ServerGame中指定的函数/属性的名称?很抱歉,我应该发布我看到它们必须匹配的错误,我只是不太确定如何使其工作。如果
ServerGame
继承自
Game
,您仍然可以返回
ServerGame
的实例,但它将作为
Game
返回。以您的示例为例,这不允许我使用在ServerGame中声明的函数而不强制执行吗?您可以返回ServerGame的实例,因为它是从Game派生的,它将被上级强制执行为基类类型而没有问题。因此我需要使用(ServerGame)ServerGame中要使用的游戏以及ServerGame中指定的功能/属性?