如何创建一个类的(多态性)集合/列表/数组,其中每个类可能具有一些不同的属性
本文关键字:具有一 属性 何创建 一个 创建 多态性 集合 数组 列表 | 更新日期: 2023-09-27 18:19:38
如果我想为游戏创建汽车引擎设计,我会执行以下操作:
基类:
public class EngineParts {
public string name;
public int ID;
public GameObject Mesh;
public Vector3 Position;
public Quaternion Rotation;
public string Description;
public float new_value; // the brand new price of it
}
然后我将拥有从中继承的类:
public class Rods : EngineParts
{
}
public class Pistons : EngineParts
{
public float Size=51;
public float Compression=51;
}
public class Turbo : EngineParts
{
public float maxboostpressure;
public float minboostpressure;
public float MaxOperatingRPM;
public float MinOperatingRPM;
public float AirToEngineRatio;
public float wasteGatePressure;
}
这里的导入内容是,所有汽车零件都共享Base类中的一些通用值,这些值是name、ID、Mesh、Position、Rotation。。etc
它们还有其他更特定于零件本身的值,例如Turbo具有最大增压,这决定了Turbo可以处理的最大增压压力。
现在在实际的游戏中,我需要能够将这些部件用作一个集合
public EngineParts[] Part = new EngineParts[3];
Part[0] = new Rods();
Part[1] = new Pistons();
Part[2] = new Turbo();
因此,我可以在需要时循环浏览所有零件,因为它们都是EngineParts类型。
但是,当试图为maxmaxboostpressure指定一个值时,我无法做到这一点。
//Note: Part[1] here is pistons
Part[1].name = "SportPiston"; // this will work since it is type of EngineParts
Part[1].maxboostpressure = 5.0; // this will not work
这是因为它属于EngineParts类型
然而,我可以说:
Rods rd = new Rods();
Pistons pt = new Pistons();
Turbo tb = new Turbo();
pt.name = 5; // this will work
pt.maxboostpressure = 5; // this will work
现在,它们确实共享基类中的相同DAta,但我不能将活塞杆、活塞和涡轮放在一个集合中,以循环或传递它们,使其成为对所有它们都有效的函数。
所以
问题是
我怎样才能最好地做到这一点
1-将发动机的所有零件放在一个集合/列表中
2-能够在每种单独类型的零件上存储额外的数据,并且编码最少
我一直在读关于
的文章抽象类、重载、多态性和继承来解决这个问题,但仍然有一些我必须错过理解的东西,所以如果有人能为我指明正确的方向,我将不胜感激。
提前感谢
尝试这样的转换:
Piston p = Part[1] as Piston;
如果零件[1]不是活塞,则p将为空。
然后继续
if(p!=null)
doSomethingHere;
最好的方法是将数组分为子类。使用linq
EngineParts[] Part = new EngineParts[3];
Part[0] = new Rods();
Part[1] = new Pistons();
Part[2] = new Turbo();
Rods[] rods = Part.Where(x => x is Rods).Cast<Rods>().ToArray();
Pistons[] position = Part.Where(x => x is Pistons).Cast<Pistons>().ToArray();
Turbo[] turbo = Part.Where(x => x is Turbo).Cast<Turbo>().ToArray();
Turbo[0].name = "SportPiston";
Turbo[0].maxboostpressure = 5.0;
您将有3个已知类型的独立数组。现在您可以单独使用它们。
请注意,索引不再像以前那样了。所以,如果你不想这样,为什么不为它们创建单独的数组呢?;)
问题是,您如何知道列表中的第三项是特定的子类?
您目前知道,因为您专门为它在数组中分配了一个位置,但是您应该在任何时候处理这个问题,因为任何子类都可以位于数组中的任何位置。
考虑到这一点,您需要检查数组项的类型,然后在处理它之前对其进行强制转换
if(Part[1] is Turbo)
{
((Turbo)Part[1]).maxboostpressure = 5;
}
有几种方法可以测试类型:
typeof
采用类型名称(在编译时指定)。
GetType
获取实例的运行时类型。
如果实例在继承树中,则is
返回true。
您可以使用"is"answers"as"运算符。
var list = new List<EngineParts>();
// add some parts to the list here...
foreach(var part in list) {
if(part is Turbo) {
(part as Turbo).maxboostpressure = 123;
}
}
没有副本等…
var lst = new List<EngineParts>(); //fill it
foreach(var itm in lst.Where(x => x is Piston).Cast<Piston>())
{
itm.maxboostpressure = 42;
}