我可以从派生类的默认构造函数中将参数传递给基础构造函数吗?

时间:2013-09-10 12:48:59

标签: c# constructor abstract-class derived-class

假设我有一个抽象基类Deck:

public abstract class Deck
{
   public List<Card> cards;

   public Deck(string[] values, string[] suits)
   {...}

   ...
}

和派生类EuchreDeck:

public class EuchreDeck : Deck
{
   string[] values = new string[] { "9", "10", "J", "Q", "K", "A" };
   string[] suits = new string[] { "clubs", "spades", "hearts", "diamonds" };

   public EuchreDeck() : base(values, suits) // Error.
   {}

   ...
}

我希望能够实例化EuchreDeck并将两个字符串数组传递给基类,即var gameDeck = new EuchreDeck();

目前我收到错误:“非静态字段,方法或属性EuchreDeck.values需要对象引用。”

这是可能的,还是调用派生的默认构造函数总是调用基本的默认构造函数?

3 个答案:

答案 0 :(得分:11)

是的,如果您创建数组static,则可以执行此操作:

public class EuchreDeck : Deck
{
   private static readonly string[] values = new string[] { "9", "10", "J", "Q", "K", "A" };
   private static readonly string[] suits = new string[] { "clubs", "spades", "hearts", "diamonds" };

   public EuchreDeck() : base(values, suits)
   {

   }
}

您不能像使用实例级成员那样使用它的原因是因为这样做是不合法的。这来自它所声明的C# specification 10.10.1 Constructor Initializers

  

实例构造函数初始值设定项无法访问实例   创建。因此,在一个引用它是一个编译时错误   构造函数初始化程序的参数表达式,就像它一样   参数表达式的编译时错误以引用任何参数   实例成员通过简单名称。

通过将数组切换为static,不再通过实例访问它们,而是通过EuchreDeck 类型访问它们。


那就是说,我可能会建议你稍微调整一下设计。也许使用工厂为你而不是他们的构造者创建这些专门的套牌。

作为一个示例,可能会重构这样的事情:

将您的基础Deck更改为只需一组卡片:

public abstract class Deck
{
    public List<Card> Cards;
    protected Deck(IEnumerable<Card> cards)
    {
        this.Cards = new List<Card>(cards);
    }
}

然后让工厂设置如下:

public class EuchreDeck : Deck
{
    private EuchreDeck(IEnumerable<Card> cards) : base(cards)
    {

    }

    public class Factory : DeckFactory
    { 
        private static readonly string[] Values = new string[] { "9", "10", "J", "Q", "K", "A" };
        private static readonly string[] Suits = new string[] { "clubs", "spades", "hearts", "diamonds" };

        public static EuchreDeck Create()
        {
            var cards = CreateCards(Values, Suits);
            return new EuchreDeck(cards);
        }
    }
}

实例化/用法:

EuchreDeck.Factory.Create();

你可以玩弄工厂用法。我只是在课堂上嵌套它,因此您无法使用无效的卡片组创建EuchreDeck。您的DeckFactory基础会有您的转化方法(看起来您目前在Deck构造函数中)

除此之外,我不确定你是否特别需要EuchreDeck;我假设你有其他相关方法吗?如果没有,你可以完全放弃这个课程,让工厂用所需的卡片创建一个Deck

答案 1 :(得分:2)

你必须在某处变量decalred:

public EuchreDeck() : base(values, suits) // Error.
{}

valuessuits在哪里宣布?

您必须定义static,例如:

static readonly string[] values = new string[] { "9", "10", "J", "Q", "K", "A" };
static readonly string[] suits = new string[] 
              { "clubs", "spades", "hearts", "diamonds" }; 

问题是base(..)只能访问ctor范围内的值 visible 。因此,您无法传递实例变量,因为该级别无法访问实例,但您可以传递调用类的 ctor参数静态成员

答案 2 :(得分:2)

我认为问题在于值和套装应该被声明为静态。

static string[] values = new string[] { "9", "10", "J", "Q", "K", "A" };
static string[] suits = new string[] { "clubs", "spades", "hearts", "diamonds" };

这样,它们将在实例化新类时可用。