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中指定的功能/属性?