我有一个角色扮演游戏的类结构,看起来像这样......
public abstract class Item
{
public abstract string Name { get; set; }
}
public abstract class Armor : Item
{
public override string Name { get; set; }
}
public class Helmet : Armor
{
public override string Name { get; set; }
}
基本上,我试图强制每个派生类型都包含一个“Name”属性。这是最好的方法吗?我知道我可以从Item.Name中删除“abstract”,然后删除Armor和Helmet中的重写“Name”属性。如果我这样做,代码看起来有点干净,但我可能忘记在这些派生类中设置base.Name。
有人可以帮我告诉我最好的方法吗?
编辑: 对不起,让我再澄清一下我的问题了。我想确定两件事。 1)Name属性存在于所有派生类中 2)Name属性不为null或为空
我基本上想强制任何派生自Item(并且不是抽象)的类具有Name的值。
答案 0 :(得分:9)
听起来你担心初始化属性?
但我可能会忘记设置 这些派生类中的base.Name。
您可以强制设置Name属性的一种方法是在基类构造函数中包含此setter,如下所示:
public class MyBaseClass
{
private string _name;
public MyBaseClass(string name)
{
_name = name;
}
}
然后,从MyBaseClass派生的所有内容都必须满足该构造函数:
public class MyDerivedClass
{
public MyDerivedClass(string name) : base(name)
{
}
}
然后您也可以创建该属性:
我不打算冒险上面是否是好的设计,但是它可以确保所有派生类在实例化时都具有有效的name属性。
正如其他答案所暗示的那样,另一种方法是实现一个在其基础实现中抛出异常的虚拟属性。
答案 1 :(得分:4)
您只需要在基类中定义Name
,而不需要将其指定为抽象。它仍将作为所有派生类中的属性提供。
public abstract class Item
{
public string Name { get; set; }
}
public abstract class Armor : Item
{ }
public class Helmet : Armor
{ }
答案 2 :(得分:2)
如果我这样做,代码看起来会更清晰,但我可能忘记在这些派生类中设置base.Name。
然后,对象的名称最终将成为愚蠢的东西。
更好的是,name
以null
开头。然后,如果您忘记初始化名称但有人试图使用它,您将获得异常,并且您将知道必须修复它。
答案 3 :(得分:2)
Mike是对的,如果您只想在所有派生对象上使用属性“Name”,则不需要将其标记为抽象,因为它是继承的。
如果您只想强制创建Items时,确实设置了一个名称,您可以强制它隐藏零参数构造函数并公开接受该名称的构造函数。
看看这段代码:
public class Item
{
public string Name { get; set; }
public Item(string name)
{
this.Name = name;
}
protected Item() {}
}
public class Armor : Item
{
public Armor(string name) : base(name) {}
protected Armor() {}
}
public class Helmet : Armor
{
public Helmet(string name) : base(name) {}
protected Helmet() {}
}
以上定义意味着:
Helmet myHelmet = new Helmet(); //will not build
Helmet myHelmet = new Helmet("Some Fancy Helmet Name"); //will build
Armor myArmor = new Armor (); //will not build
Armor myArmor = new Armor ("Some Fancy Armor Name"); //will build
Item myItem = new Item (); //will not build
Item myItem = new Item("Some Fancy Item Name"); //will build
这会强制任何类的实例必须在创建时定义名称。无论如何,一种可能的解决方案......
答案 4 :(得分:0)
将Name命名为虚拟ie。 Item类中使用public virtual Name {get; set; }
访问器?因为Helment和Armor来自Item类。它会强制它们必须被覆盖......
希望这有帮助, 最好的祝福, 汤姆。
答案 5 :(得分:0)
所以这取决于你想做什么......
使类抽象强制所有子类实现类(及其抽象函数等),但如果你想让一个函数具有可以覆盖函数的基本功能,那么我建议不要使类抽象化并使特定函数变为虚拟,因此当虚函数不被覆盖时,将调用基函数。
并且始终可以选择创建具有相同名称的“新”属性,但我认为这不是一个好习惯。
希望有所帮助。答案 6 :(得分:0)
我认为您仍然可以在抽象类中使属性虚拟化,因此这应该可以解决您的问题。
您可以将值设置为基本抽象类中的特定值, 这里有一个例子:
public abstract class Item
{
public virtual string Name
{
get {return m_strName;}
set {m_strName = value;}
}
public abstract class Armor : Item
{
public override string Name { get; set; } // if you want to override it
}
public class Helmet : Armor
{
public override string Name { get; set; } // if you want to override it
}