我可以将参数从派生类的默认构造函数传递给基构造函数吗?
假设我有一个抽象基类 Deck:
Suppose I have an abstract base class Deck:
public abstract class Deck
{
public List<Card> cards;
public Deck(string[] values, string[] suits)
{...}
...
}
和一个派生类 EuchreDeck:
and a derived class 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();
.
I want the ability to instantiate EuchreDeck
and have the two string arrays passed to the base class, i.e. var gameDeck = new EuchreDeck();
.
目前我收到错误消息:非静态字段、方法或属性 EuchreDeck.values
需要对象引用."
Currently I'm getting the error: "An object reference is required for the non-static field, method, or property EuchreDeck.values
."
这是可能的,还是调用派生的默认构造函数总是调用基本的默认构造函数?
Is this possible, or will calling the derived default constructor always call the base default constructor?
是的,如果您将数组设为 static
就可以做到这一点:
Yes, you can do this if you make the arrays 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 它指出:
The reason why you can't use it as you had with instance-level members is because it's not legal to do so. This comes from the C# specification 10.10.1 Constructor Initializers where it states:
一个实例构造函数初始化器不能访问被创建.因此,在编译时引用它是一个错误构造函数初始值设定项的参数表达式,因为它是一个引用任何参数表达式的编译时错误通过简单名称的实例成员.
An instance constructor initializer cannot access the instance being created. Therefore it is a compile-time error to reference this in an argument expression of the constructor initializer, as is it a compile-time error for an argument expression to reference any instance member through a simple-name.
通过将数组切换为 static
,它们不再通过实例访问,而是通过 EuchreDeck
type 访问.
By switching the arrays to be static
, they are no longer accessed via the instance but rather by the EuchreDeck
type.
也就是说,我可能会建议您对设计稍作调整.也许使用工厂为您而不是他们的构造者创建这些专门的甲板.
That said, I might suggest you take a slight tweak on the design. Maybe use a factory to create these specialized decks for you rather than their constructors.
作为一个示例,可以重构如下:
As an example, maybe refactor something like this:
改变你的基础Deck
,只拿这组牌:
Change your base Deck
to just take the set of cards:
public abstract class Deck
{
public List<Card> Cards;
protected Deck(IEnumerable<Card> cards)
{
this.Cards = new List<Card>(cards);
}
}
然后像这样进行出厂设置:
Then have the factory setup like this:
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
构造函数中有)
You could play around with the factory usage. I just nested it in the class so you couldn't create a EuchreDeck
with an invalid set of cards. Your DeckFactory
base would have your conversion method (which looks like you currently have in your Deck
constructor)
除此之外,我不确定您是否对 EuchreDeck
有特殊需求;我假设您还有其他与之相关的方法?如果没有,你可以完全放弃这个课程,让工厂用所需的卡片创建一个Deck
.
Beyond that, I'm not sure if you have a specific need for a EuchreDeck
; I'm assuming you have other methods associated with it? If not, you could probably ditch the class altogether and just let the factory create a Deck
with the needed cards.