(UNITY/C#)重写函数未从派生泛型类调用

(UNITY/C#)重写函数未从派生泛型类调用,c#,generics,overriding,derived-class,unity-editor,C#,Generics,Overriding,Derived Class,Unity Editor,我知道有很多关于虚拟/覆盖函数、操作指南和文档的问题需要回答,但我还没有找到与我试图实现的目标相匹配的东西 我正在开发一个系统,通过我在Unity中创建的编辑器窗口创建数据对象(特别是针对带有RPG元素的游戏)。我让所有的代码都工作得很好,正如预期的那样,但后来我决定尝试使用泛型将每个管理面板中的所有代码压缩到一个单独的类中 public class DataManagementPanel<T> where T : DataObject { public static Data

我知道有很多关于虚拟/覆盖函数、操作指南和文档的问题需要回答,但我还没有找到与我试图实现的目标相匹配的东西

我正在开发一个系统,通过我在Unity中创建的编辑器窗口创建数据对象(特别是针对带有RPG元素的游戏)。我让所有的代码都工作得很好,正如预期的那样,但后来我决定尝试使用泛型将每个管理面板中的所有代码压缩到一个单独的类中

public class DataManagementPanel<T> where T : DataObject {
   public static DataManagementPanel<T> instance;
   public static DataManagementPanel<T> GetInstance() {
      if (instance == null) {
         instance = new DataManagementPanel<T>();
      }
      return instance;
   }

   protected virtual void Draw(Rect window) {
      Debug.Log("Calling Base Class");
   }
}

public ClassManagementPanel() : DataManagementPanel<ClassData>() {
   protected override void Draw(Rect window) {
      Debug.Log("Calling Derived Class");
   }
}
我对泛型还是相当陌生的,但从目前为止我所做的实验来看,它的效果和我所希望的一样。现在唯一的问题是,由于某种原因,当我试图从派生类调用Draw方法时,它使用父类虚方法。我以前从未见过这种情况,也许我是盲人,我在这里遗漏了一些东西,或者这是一个特定于泛型使用的问题

public class DataManagementPanel<T> where T : DataObject {
   public static DataManagementPanel<T> instance;
   public static DataManagementPanel<T> GetInstance() {
      if (instance == null) {
         instance = new DataManagementPanel<T>();
      }
      return instance;
   }

   protected virtual void Draw(Rect window) {
      Debug.Log("Calling Base Class");
   }
}

public ClassManagementPanel() : DataManagementPanel<ClassData>() {
   protected override void Draw(Rect window) {
      Debug.Log("Calling Derived Class");
   }
}
最后,我尝试在另一个类中的OnGUI()函数中的编辑器窗口中绘制管理面板。控制台输出返回“调用基类”,而不是预期的“调用派生类”


我找到了一个似乎对我有效的解决办法。与其尝试在DataManagementPanel类中拥有静态实例,不如将其设置为抽象类,并将静态实例移动到每个单独的面板类中

public abstract DataManagementPanel<T> where T : DataObject {

   public abstract Draw(Rect window);
}

public ClassManagementPanel() : DataManagementPanel<ClassData>() {
   
   private static ClassManagementPanel instance;
   public static ClassManagementPanel GetInstance() {
      if (instance == null) {
         instance = new ClassManagementPanel();
      }
      return instance;
   }       

   public override void Draw(Rect window) {
      Debug.Log("Calling Derived Class");
   }
}
公共抽象数据管理面板,其中T:DataObject{
公共抽象绘图(矩形窗口);
}
public ClassManagementPanel():DataManagementPanel(){
私有静态ClassManagementPanel实例;
公共静态类管理面板GetInstance(){
if(实例==null){
实例=新的ClassManagementPanel();
}
返回实例;
}       
公共替代无效绘图(矩形窗口){
Log(“调用派生类”);
}
}

此更改会产生所需的“调用派生类”输出,更具体地说,它会按预期在编辑器窗口上绘制“我的面板”。

在代码中,GetInstance始终返回DataManagementPanel实例,因此调用派生类是正确的结果。@Sergey的注释有少量更正<代码>“调用基类”是正确的结果。不过,他对
GetInstance()
方法的观察是正确的。这里没有多态性,它总是只返回基类的一个实例,而不是任何派生类。我仍然看不出你需要基类做什么?继承它是没有用的。这将是更好的使用界面的方式。
public abstract DataManagementPanel<T> where T : DataObject {

   public abstract Draw(Rect window);
}

public ClassManagementPanel() : DataManagementPanel<ClassData>() {
   
   private static ClassManagementPanel instance;
   public static ClassManagementPanel GetInstance() {
      if (instance == null) {
         instance = new ClassManagementPanel();
      }
      return instance;
   }       

   public override void Draw(Rect window) {
      Debug.Log("Calling Derived Class");
   }
}