我可以从派生类的默认构造函数中将参数传递给基础构造函数吗?
假设我有一个抽象基类Deck:
public abstract class Deck { public List 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
需要对象引用。”
这是可能的,还是调用派生的默认构造函数总是调用基本的默认构造函数?
是的,如果将数组设为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构造函数初始化器 ,它指出:
实例构造函数初始值设定项无法访问正在创建的实例。 因此,在构造函数初始值设定项的参数表达式中引用它是一个编译时错误,因为参数表达式通过简单名称引用任何实例成员的编译时错误。
通过将数组切换为static
,不再通过实例访问它们,而是通过EuchreDeck
类型访问它们。
也就是说,我建议你稍微调整一下设计。 也许使用工厂为你而不是他们的构造者创建这些专门的套牌。
举个例子 ,也许重构这样的东西:
将您的基础Deck
更改为只需一组卡片:
public abstract class Deck { public List Cards; protected Deck(IEnumerable cards) { this.Cards = new List (cards); } }
然后让工厂设置如下:
public class EuchreDeck : Deck { private EuchreDeck(IEnumerable 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
。
我认为问题是值和套装应该声明为静态。
static string[] values = new string[] { "9", "10", "J", "Q", "K", "A" }; static string[] suits = new string[] { "clubs", "spades", "hearts", "diamonds" };
这样,它们将在实例化新类时可用。
你必须有一个变量decalred的地方:
public EuchreDeck() : base(values, suits) // Error. {}
宣布values
和suits
?
你必须将它们定义为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参数和调用类的静态成员 。