如何创建一个类的(多态性)集合/列表/数组,其中每个类可能具有一些不同的属性

本文关键字:具有一 属性 何创建 一个 创建 多态性 集合 数组 列表 | 更新日期: 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;
}
相关文章: