下属类的构造函数问题

时间:2012-09-14 09:59:05

标签: c#

我觉得自己像整个笨蛋。我有一段时间以来一直是编码器,我之前没有遇到过这种语言,我想,我总是用“额外的”东西来覆盖构造函数。所以,我正在截断一些类的说明:

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;
}
可悲的是,不能那样做,我们可以吗? :(但实际上,这几乎就是我想要的!

在你问之前,我确实考虑过将物品添加到连接......但从逻辑上讲,你不会想到这样的话......

那么,我该如何绕过它呢?我想添加一个属性并将其称为其他内容......

好吧,我明白为什么它说教师,很失望它没有与原班上的可用教练一致,但很好,我明白了。但是,由于原始项目已经存在,我不想要副本。我想添加功能......我放弃了。这个问题可以关闭。**

6 个答案:

答案 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)
{

}

Using Constructors - MSDN

  

在派生类中,如果未调用基类构造函数   显式使用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)

如果您希望PlayerItem复制属性,则继承可能不是最佳选择。你可以使用组合:

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;

那么,你是什么意思玩家永远不会“创建”只从项目中复制,现有项目