我可以从 C# 中的“this”获取子类实例吗?
本文关键字:子类 获取 实例 this 中的 我可以 | 更新日期: 2023-09-27 18:30:17
我有一个RTS游戏对象类WorldObject
。在RTS游戏中,通过鼠标点击来调度对象上的各种操作。我发明了以下系统:
每个 WorldObject 都有一个包含可用操作的Action[]
数组。 Action
构造函数如下所示:
public Action(WorldObject ownerObj) {
owner = ownerObj;
}
在构造函数(实际上是 Unity Start()
方法)WorldObject
中,Action
都是从对象定义中包含的字符串实例化的。这很舒服,因为我可以在Unity UI中编辑动作:
//Load actions
int l = actions_str.Length;
actions = new Action[l];
for (int i = 0; i < l; i++)
{
actions[i] = Action.fromString(actions_str[i], "", this);
if (actions[i] != null)
Debug.Log("Created action...");
else
Debug.LogWarning("Failed to create action!");
}
然后使用反射从字符串转换操作:
public static Action.fromString(string className, WorldObject owner) {
... some code ...
//Get the info about constructor (using array literal)
constructor = t.GetConstructor(new Type[] { typeof(string), typeof(WorldObject) });
... some code ...
}
其中所有者是一些受保护的变量。默认操作是无用的,但是许多类可以从中继承,例如BuildUnit:Action
。如果您创建高级操作,它将只能在某些单元上运行 - 在这种情况下,BuildUnit
需要一个Factory:WorldObject
实例,以使用工厂构建队列等进行操作。
这意味着我已经重载了一个构造函数,BuildUnit:Action
需要Factory
:
public BuildUnit(Factory factory) : base(factory)
{
f = factory;
}
但这是我将BuildUnit
分配给Factory
时得到的错误:
No suitable constructor found for 'Actions.SpawnEgg'.
UnityEngine.Debug:LogError(Object)
Actions.Action:fromString(String, String, WorldObject) (at Assets/WorldObject/Action.cs:66)
Units.WorldObject:Start() (at Assets/WorldObject/WorldObject.cs:349)
Units.Unit:Start() (at Assets/WorldObject/Unit/Unit.cs:38)
似乎传递的是WorldObject
实例,而不是Factory
子实例。
我认为这不应该发生。无论如何:
- 在父类中,如果它
is
其中一个子类,是否仍然只是父实例包含在this
? - 如果是这样,我应该怎么做才能保持这个概念的运作?
假设答案是2.
,我已经想出了一个令人厌恶的解决方法:
//The return value should be castable back to original class (as Factory)
protected virtual WorldObject GetThis() {
return this;
}
这里有两个不同的问题,您询问的一般问题和您遇到的特定错误。
一般问题
没有"父实例"或"子实例"这样的东西。实例始终属于一种特定类型,并且始终可以强制转换为它匹配的任何其他类型。这意味着如果Factory
继承WorldObject
,这将始终有效:
Factory f = new Factory();
WorldObject wo = f; // Works, because Factory is-a WorldObject.
Factory f2 = (Factory)wo; // Works, because the reference wo points to a Factory object.
您的解决方法不会执行我的第二行不会执行的操作 = 作业中的向上转换是隐式的。
具体问题
您收到的错误是由于反射搜索类型和方法签名的方式。在您的代码中,在第 43 行中,您有以下行:
constructor = t.GetConstructor(new Type[] { typeof(string), typeof(WorldObject) });
它正在做的是在采取WorldObject
的操作上搜索构造函数。但是,您的操作具有一个构造函数,该构造函数采用Factory
,而不是WorldObject
。这在使用反射时会有所不同。
的确,在调用构造函数时,编译器知道Factory
是WorldObject
并且可以匹配它,但是在使用反射时,需要Factory
的构造函数和需要WorldObject
的构造函数之间存在差异。你可以同时拥有两者,它们的行为略有不同,你必须明确如何称呼它。
换句话说,如果你想要一个通用的基于反射的方法来实例化你的类型,你要么需要让它们都支持相同的构造函数(在本例中,一个WorldObject
ctor),要么让你的反射代码更聪明(和更丑陋),迭代所有构造函数并查找参数类型是WorldObject
后代的构造函数。