我觉得自己像整个笨蛋。我有一段时间以来一直是编码器,我之前没有遇到过这种语言,我想,我总是用“额外的”东西来覆盖构造函数。所以,我正在截断一些类的说明:
public enum Flags : ushort
{
Item = 1,
Player = 2
}
public class Item
{
private Flags _flags;
private int _owner;
private String _pwd;
public Item(Flags flags, int owner, String pwd = null)
{
_owner = owner;
_flags = flags;
_pwd = pwd;
}
}
public class Connection
{
... stuff irrelevant to question
}
因此,当玩家登录时,我希望能够接受Item
的后代,其类型为Player
,并且具有连接 - 实际上它只是一个项目。
所以我做了一个首发:
public class Player : Item
{
public Connection Conn;
}
它说:
Item不包含带0参数的构造函数
嗯,在我眼里,我从来没有说过它。玩家永远不会被“创造”只从项目中复制,现有项目,我正在添加它,一个额外的属性(不是这就是留下来的作为我的代码,但这是一个起点)..所以,我不想手动将实际的20多个属性从一个复制到另一个。实际上我希望能够使用
Player p = (Player)item_wanted;
然后为其分配连接..永远不会直接创建p Player
。我不希望将连接分配给Item,因为它只是活动的玩家,技术上玩家可以有多个连接。
当然,第一个愚蠢的想法是
的构造函数Public Payer(Item i)
{
this = (Player) i;
}
可悲的是,不能那样做,我们可以吗? :(但实际上,这几乎就是我想要的!
在你问之前,我确实考虑过将物品添加到连接......但从逻辑上讲,你不会想到这样的话......
那么,我该如何绕过它呢?我想添加一个属性并将其称为其他内容......
好吧,我明白为什么它说教师,很失望它没有与原班上的可用教练一致,但很好,我明白了。但是,由于原始项目已经存在,我不想要副本。我想添加功能......我放弃了。这个问题可以关闭。**
答案 0 :(得分:3)
第一个问题:Item具有私有属性,因此后代将无法访问_flags。如果您声明它们是受保护的,则后代将具有访问权限,但您将无法使用这样的构造函数:
public Player(Item i) : base(i._flags,i._owner,i._pwd)
因此,如果您将Item属性设为公共,那么这将起作用:
public enum Flags : ushort
{
Item = 1,
Player = 2
}
public class Item
{
public Flags _flags;
public int _owner;
public String _pwd;
public Item(Flags flags, int owner, String pwd = null)
{
_owner=owner;
_flags=flags;
_pwd=pwd;
}
}
public class Connection
{
public Connection()
{
}
}
public class Player : Item
{
public Connection Conn;
public Player(Item i) : base(i._flags,i._owner,i._pwd)
{
// and add your "additional thing"
// This calls the base constructor, and then you can add codes...
}
}
所以,你可以这样做:
Item p = new Item(Flags.Item,12); // Item is something existing
Player x = new Player(p);
注意,Player x和Item p不一样。播放器x是从Item p创建的,因此修改p。不会影响x .. 所以代码:
Item p = new Item(Flags.Item,12);
Player x = new Player(p); // instead of: Player p = (Player)item_wanted;
p._owner = 20;
将显示20(作为p._owner)和12(作为x._owner)。在基于项目创建新玩家后,您可以“忘记”该项目。
答案 1 :(得分:2)
原因是您的子类构造函数隐式调用父类的默认构造函数。在您的父类中,您没有定义任何带有0参数的构造函数,这就是您收到此错误的原因。
虽然您尚未为Player
类定义任何构造函数。它将假定一个默认构造函数,如下面的调用。
Player() : base()
{
}
要解决此问题,您可以在基类Item
中创建一个空的默认构造函数,或者使用构造函数在子类中使用关键字base
调用特定的构造函数。
Public Payer(Item i) :base(arg1,arg2,arg3)
{
}
在派生类中,如果未调用基类构造函数 显式使用base关键字,然后是默认构造函数if 有一个,被称为隐式。
答案 2 :(得分:2)
如果您继承自Item
,则需要从Player
调用其构造函数:
public Player(Flags flags, int owner, String pwd = null) : base(flags, owner, pwd)
{
// Do something else
}
或者你必须在Item
上定义一个没有参数的构造函数。
答案 3 :(得分:1)
将一个构造函数添加到Item of:
public Item() { };
答案 4 :(得分:1)
如果您希望Player
从Item
复制属性,则继承可能不是最佳选择。你可以使用组合:
class Player
{
Item item;
public Player(Item item)
{
this.item = item; // store reference to item here, it will point to the same object you used for construction, no copying needed later
}
}
您也不必将item
公开为公共属性来调用player.Item.Flags
等,您可以为Player
类创建包装器属性:
class Player
{
Item item;
public Player(Item item)
{
this.item = item; // store reference to item here, it will point to the same object you used for construction, no copying needed later
}
public string Name { get { return item.Name; } } // etc...
}
答案 5 :(得分:1)
public class A
{
private int _p;
public A(int param) { _p = param;}
}
public class B : A
{
public B(int param) : base(param)
{
}
public int x { get; set; }
}
如果您有A(var item = new A(1);
)的实例,则无法将其转换为B.
但是如果你有一个B(var player = new B(1);
)的实例 - 你可以把它投射到A:
var casted = (A)item;
那么,你是什么意思玩家永远不会“创建”只从项目中复制,现有项目?