7

假设我有一个抽象基类 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。”

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

4

3 回答 3

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# 规范 10.10.1 Constructor Initializers,其中指出:

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

通过将数组切换为 be 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使用所需的卡片创建一个。

于 2013-09-10T12:51:22.023 回答
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 范围内可见的值。因此,您不能传递实例变量,因为在该级别上无法访问实例,但您可以传递ctor 参数和调用类的静态成员

于 2013-09-10T12:51:30.367 回答
2

我认为问题在于价值观和西装应该被声明为静态的。

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

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

于 2013-09-10T12:52:44.167 回答