如何强制派生类包含某些具有默认值的属性
-
23-09-2019 - |
题
我有一个角色扮演游戏的类结构,如下所示......
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; }
}
基本上,我试图强制每个派生类型都包含“名称”属性。这是最好的方法吗?我知道我可以从 Item.Name 中删除“abstract”,然后删除 Armor 和 Helmet 中覆盖的“Name”属性。如果我这样做,代码看起来会更干净一些,但我可能会忘记在这些派生类中设置 base.Name。
有人可以帮我看看最好的方法吗?
编辑:抱歉,让我再澄清一下我的问题。我想确定两件事。1)所有派生类中都存在名称属性2)名称属性不是null或空的
我基本上想强制从 Item 派生的任何类(并且不是抽象的)都具有 Name 值。
解决方案
听起来您担心初始化属性?
但是我可能会忘记在这些派生的类中设置基础。
强制设置 Name 属性的一种方法是在基类构造函数中包含此设置器,如下所示:
public class MyBaseClass
{
private string _name;
public MyBaseClass(string name)
{
_name = name;
}
}
然后从 MyBaseClass 派生的所有内容都必须满足该构造函数:
public class MyDerivedClass
{
public MyDerivedClass(string name) : base(name)
{
}
}
然后您还可以创建该属性:
- 抽象以确保它存在于每个派生类中并具有自己的实现
- virtual 提供基本实现以及所有要覆盖的实现。
我不会冒险上面的设计是否良好,但它可以确保所有派生类在实例化时都具有有效的名称属性。
正如其他答案所建议的,另一种方法是实现一个在其基本实现中引发异常的虚拟属性。
其他提示
您只需要在基类来定义Name
,也不需要将其指定为抽象的。它仍然是可作为所有派生类的属性。
public abstract class Item
{
public string Name { get; set; }
}
public abstract class Armor : Item
{ }
public class Helmet : Armor
{ }
如果我这样做,代码看起来干净了一点,但我可能会忘记设置base.Name在这些派生类。
然后,对象的名称只是最终被一些愚蠢的。
更好的是,具有name
开始作为null
。然后,如果你忘了初始化的名字,但有人试图使用它,你会得到一个例外,你就会知道你要修复它。
迈克是正确的,如果你只是想使用“名称”属性上的所有派生的对象,你不需要它被标记在所有抽象的,因为它的继承。
如果您只想强制的事实,创建项目时,一个名字肯定是设置,你可能会迫使它通过隐藏零参数的构造函数和暴露接受名称的构造函数。
在这个代码请看:
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
此力量的类的任何实例必须在创建时间定义名称。一个可能的解决方案无论如何...
将制造名称的虚拟即public virtual Name {get; set; }
访问在项目类中使用?由于Helment和护甲从项目类下降。它会执行,他们必须被覆盖......
希望这有助于 最好的祝福, 汤姆。
所以这取决于你想做的事......
什么使抽象类强制所有子类来实现类(及其摘要函数等),但如果你想一个函数有一个与可能性基本功能覆盖功能,那么我会建议不要使抽象类,使所述特定功能的虚拟代替,从而当虚拟功能没有被覆盖,并且基函数将被调用。
和总是有选项来创建具有相同名称的“新”的属性,但我不认为这是一个很好的做法。
希望帮助。
我觉得你还是可以做一个抽象类中的虚拟财产,因此应该解决您的问题。
可以将该值设置为特定的东西在基抽象类, 这里的示例:
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
}