在我解释我的问题之前,请记住我选择了这样的架构,因为这将在Unity下的库存系统中使用,所以我不得不将Item
分开,这是一个MonoBehavior,从数据中看,它只是世界上的一些东西,它只是用于库存目的的价值......如果这是有道理的。
我有一个这样的架构:
public class ItemData
{
// some fields...
public string _name; //should be private with its properties but it doesn't matter in the current example
}
public class EquipmentData : ItemData
{
// some additional fields...
public float _weight;
}
public class Item
{
private ItemData _data;
//Properties
public virtual ItemData Data { get; set; }
}
public class Equipment : Item
{
//Properties
public override ItemData Data
{
get { return _data as EquipmentData; }
set { _data = value as EquipmentData; }
}
}
所以,基本上我的项目层次结构更深入,但1级足以解释自己。 (它继续像武器:装备一样)......
问题是,如果我将private ItemData _data;
留在Item
课程中,并在private EquipmentData _eData;
课程中添加Equipment
,我会有ItemData
个字段两次因为EquipmentData
继承了其他派生类的ItemData
等等...如果我有一个派生自Equipment
等的类,那么第三次获取它......
类似的东西:
public class Item
{
private ItemData _data;
}
public class Equipment : item
{
private EquipmentData _eData;
}
ItemData
的{{1}}字段会在_name
中出现两次,我不希望这样......
所以我猜我的架构有问题,而且这种方法可能有一种看起来很脏的方法,但是我找不到任何针对这个问题的方法。在线,我已达到极限。
我尝试过:
Equipment
中使用关键字new
,以为我可以隐藏Equipment
课程中的初始protected ItemData _data;
,然后Item
在protected new EquipmentData _data;
,但它显然不允许我因为Shadow _data它需要是相同的类型,似乎不适用于派生类型。Equipment
... 我仍然觉得很奇怪,我最终试图实现类似的东西,所以我愿意接受新的想法,以更好的方式重组事物,或者如果有人有解决方案,我还没想到要保持这样的事情,但让它们工作,它会非常好。
我希望我的问题足够详细,如果不是,我可以在必要时清理。
答案 0 :(得分:0)
您需要的是Generic Classes。这样,您可以为每个Item
指定正确类型的ItemData
。因此,Equipment
将分配EquipmentData
。
//TItemData is a name of this generic type.
//It could be T for example, just like variable name.
//These type names start from T by convention.
//This is not a new class or something like that.
//where TItemData : ItemData is a constraint,
//that assumes that this type should be a subtype of ItemData
public abstract class Item<TItemData> where TItemData : ItemData
{
protected TItemData Data;
}
//EquipmentData is a subtype of ItemData, so it fits here.
//No chances to write, for example, IntEquipment : Item<int> ,
//because int does not derive from ItemData.
public class Equipment : Item<EquipmentData>
{
//here Data will be of EquipmentData type, without any casting.
}
通过实施上述内容,您将实现Type Safety。
要创建一个正确扩展Equipment
的类(让我们称之为Weapon
),并使其具有正确的ItemData
(让我们称之为WeaponData
),您需要写下这样的东西:
修改Equipment
,并将其设为abstract
:
public abstract class Equipment<TEquipmentData>
: Item<TEquipmentData>
//this constraint is VERY important, as EquipmentData derives from ItemData, thus fulfill Item<TItemData> constraint.
where TEquipmentData : EquipmentData
{
//Data will have EquipmentData type here.
}
创建WeaponData
public WeaponData : EquipmentData
{
}
创建Weapon
public class Weapon : Equipment<WeaponData>
{
//Data will have WeaponData type here.
}
答案 1 :(得分:0)
这有效:
public class OverridePropertiesWithSameField
{
public void Test()
{
ChildItem ci = new ChildItem();
ChildItemData cid = new ChildItemData();
cid.ItemDataProp = "ItemDataProperty"; // Inherited
cid.ChildItemDataProp = "ChildItemDataProp"; // Specific
ci.ItemData = cid;
// You know you need ChildItemData type here.
var childItemData = ci.ItemData as ChildItemData;
string itemDataProp = childItemData.ItemDataProp;
string childItemDataProp = childItemData.ChildItemDataProp;
}
}
public class Item
{
protected ItemData data;
public virtual ItemData ItemData { get; set; }
}
public class ChildItem : Item
{
public override ItemData ItemData
{
get { return base.data; }
set { base.data = value; }
}
}
public class ItemData
{
public string ItemDataProp { get; set; }
}
public class ChildItemData : ItemData
{
public string ChildItemDataProp { get; set; }
}
答案 2 :(得分:0)
您可以使用泛型类型参数,使用泛型类型约束(where)。
routes
现在你的班级可以使用特定的ItemData:
public class Item<DATA> where DATA : ItemData
{
public virtual DATA Data { get; set; }
}