简体   繁体   English

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

[英]How to create a (Polymorphism) collection/list/array of a class where each one may have some different properties

If i wanted to create a Car Engine Design for a game i will do the following: 如果我想为游戏创建汽车引擎设计 ,我将执行以下操作:

The Base class: 基类:

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
}

Then i would have the classes that inherits from 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;
    }

The importing thing here is that all car parts share some common values that are in the Base class those values are name, ID, Mesh, Position, Rotation.. etc 这里的导入是所有汽车零件共享类中的一些常见值,这些值是名称,ID,网格,位置,旋转等。

They also have other values that are more specific for the part itself, like for instance the Turbo has maxboostpressure which determines the maximum pressure of boost the turbo can handle. 它们还具有其他更适合零件本身的值,例如Turbo具有maxboostpressure ,它决定了涡轮增压器可以承受的最大增压压力。

Now in the actual game I need to be able to make the use of the parts as one collection 现在在实际游戏中,我需要能够将这些部分用作一个集合

public EngineParts[] Part = new EngineParts[3];

Part[0] = new Rods();
Part[1] = new Pistons();
Part[2] = new Turbo();

I can therefore loop through all parts when needed since they are all of type EngineParts . 因此,我可以在需要时遍历所有部件,因为它们都是EngineParts类型。

But when trying to assign a value to max maxboostpressure , i am unable to do that. 但是当试图为max maxboostpressure分配一个值时,我无法做到这一点。

   //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

and that is due to that it is of type EngineParts 这是因为它是EngineParts类型

I can however say: 但我可以说:

Rods rd = new Rods();
Pistons pt = new Pistons();
Turbo tb = new Turbo();

pt.name = 5; // this will work
pt.maxboostpressure = 5; // this will work

Now they do share the same DAta from the Base class, but i cant put the Rods, Pistons, Turbo in one collection to loop through or pass them in a function that works on all of them. 现在他们确实从Base类共享相同的DAta,但是我不能将Rods,Pistons,Turbo放在一个集合中来循环或传递它们在一个适用于所有这些的函数中。

So 所以

Question Here is 问题在这里

How can i best do this? 我怎么能做到最好呢?
1- Have all the parts of the engine in one collection/List 1-将发动机的所有部件放在一个集合/列表中
2- Be able to have extra data stored on each individual type of part as well with minimum coding. 2-能够以最少的编码在每种类型的零件上存储额外的数据。

I have been reading about 我一直在读书
Abstract Classes, Overloading, Polymorphism, and INHERITANCE to solve this but still there is something that i must miss understand, so if anyone could point me in the right direction it would be highly appreciated. 抽象类,重载,多态和继承来解决这个问题,但仍然有一些我必须忽略的东西,所以如果有人能指出我正确的方向,我将非常感激。

Thank you in Advance 先感谢您

Try a cast like this: 试试像这样的演员:

Piston p = Part[1] as Piston;

p will be null if Part[1] isn't a Piston. 如果Part [1]不是Piston,p将为null。

Then continue with 然后继续

if(p!=null)
    doSomethingHere;

The best way is to separate your array into parts of subclasses. 最好的方法是将数组分成子类的一部分。 Using linq 使用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;

You will have 3 seperate arrays with known type. 您将拥有3个已知类型的单独数组。 now you can work with them individually. 现在你可以单独使用它们。

Notice that indexes are no more like before. 请注意,索引不再像以前那样。 So if you dont want this why not already create separate arrays for them? 所以如果你不想要这个为什么还没有为它们创建单独的数组呢? ;) ;)

The question is, how do you know that the 3rd item in the list is a specific sub-class? 问题是,你怎么知道列表中的第3项是特定的子类?

You currently know because you are specifically assigning it a location in the array, however you should approach this as at any time, any sub-class could be in any position in the array. 您目前知道,因为您专门为它分配了一个位置,但是您应该随时查看,任何子类都可以位于数组中的任何位置。

With that in mind you need to check the type of the array item, and then cast it before you can work on it. 考虑到这一点,您需要检查数组项的类型,然后在可以处理之前将其强制转换。

if(Part[1] is Turbo)
{
   ((Turbo)Part[1]).maxboostpressure = 5;
}

There are a few ways you can test the type: 您可以通过以下几种方式测试类型:

typeof takes a type name (which you specify at compile time). typeof采用类型名称(您在编译时指定)。

GetType gets the runtime type of an instance. GetType获取实例的运行时类型。

is returns true if an instance is in the inheritance tree. 如果实例位于继承树中, is返回true。

You can use "is" and "as" operators. 您可以使用“is”和“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;
  }
}

no copies, etc... 没有副本等......

var lst = new List<EngineParts>(); //fill it
foreach(var itm in lst.Where(x => x is Piston).Cast<Piston>())
{
    itm.maxboostpressure = 42;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM