调用基类方法* WITHOUT *使用override

时间:2013-03-15 09:01:35

标签: c# subclass

我正在试图弄清楚如何用c#做一些我特别注意到的Unity 引擎呢。它似乎是某种形式的实现或子类化,但因为我没有源,我不知道。

Unity中的

所有脚本都是这样的:

class someclass : MonoBehavior
{
}

现在有一个函数列表,您可以通过此MonoBehavior调用引擎在您的类中调用,例如

void OnGUI()
{
  so something here
}

所以,如果您说5个脚本都包含OnGUI函数,那么它将在所有5个脚本中调用

我想自己实现这种类型的东西,但我无法理解这一点。

如何编写基类或实现,或者这是什么,它调用子类中的预定义函数,但不需要函数的子类,而不必在其中使用override ?

这是来自unity Engine的示例源文件:

public class EnemyAttack : MonoBehaviour {
    // Use this for initialization
    void Start () {
        AttackTimer = 0;
        CoolDown = 2.0f;
     }
     // Update is called once per frame
     void Update () {
         if (AttackTimer > 0) AttackTimer -= Time.deltaTime;
         if (AttackTimer < 0) AttackTimer = 0;

         if (AttackTimer == 0){
             Attack();
             AttackTimer = CoolDown;
          }
    }
}

该代码完美运行,然后引擎调用在第一次启动时启动(单次调用)并且每次框架通知都会调用Update ,并且在任何地方都没有覆盖

它是某种事件系统,但我在谷歌上找不到任何描述如何执行此操作的内容。

5 个答案:

答案 0 :(得分:3)

如果您不想/可以使用override关键字,则可以使用反射(可能使用dynamic关键字)来执行此操作

基类'简单'在派生类中搜索特定的签名/属性并调用方法。

如果您自己编写,请考虑缓存反射的结果(或使用可能为您执行缓存的dynamic关键字)并测试您是否仍然获得所追求的性能。反思可能非常缓慢。也请看这个问题:Dynamic Lang. Runtime vs Reflection

示例:

class TheBehavior
{
    public void Act()
    {
        dynamic derived = this;
        try
        {
            derived.Foo(42);
            derived.Foob(43);
        }
        catch (RuntimeBinderException e)
        {
            Console.WriteLine("Method call failed: " + e.Message);
        }
    }
}

class TheDerived : TheBehavior
{
    public void Foo(int bar)
    {
        Console.WriteLine("Bar: " + bar);
    }
}

class Program
{
    static void Main(string[] args)
    {
        TheBehavior behavior = new TheDerived();
        behavior.Act();
        Console.ReadKey(true);
    }
}

答案 1 :(得分:1)

由于它不使用虚方法,最可能的方法是使用反射。 MonoBehavior类将反映其子类并搜索名称与正确模式匹配的方法:

public class MonoBehavior
{
    private void InitSubclass()
    {
        var methods = new[] { "OnGUI", "OnLoad" }; //etc
        foreach (string methodName in methods)
        {
            MethodInfo method = this.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
            if (method != null)
            {
                method.Invoke(this, new object[0]);
            }
        }
    }
}

答案 2 :(得分:0)

  

如何编写基类或实现或其他任何内容   它调用子类中的预定义函数但不调用   要求子类的功能,而不必使用   覆盖它们?

据我所知,这些只是virtual方法。基类可以定义一些基本实现,但不要求派生类覆盖这些方法。

答案 3 :(得分:0)

如果我得到你所说的话,我认为你正在寻找的是一个带继承的基类:

public class BaseClass // or abstract
{
    public void foo(int x)
    {
        //your implementation
    }
}

public class ChildClass : BaseClass
{
    public void foo(int x) : base(x)
    {
        //your implementation
    }
}

答案 4 :(得分:0)

使用virtualoverride

class Program
{
    static void Main(string[] args)
    {
        MyBaseClass ext1 = new Ext1();
        ext1.DoSomething();

        MyBaseClass ext2 = new Ext2();
        ext2.DoSomething();

        Console.ReadKey(true);
    }
}

class MyBaseClass
{
    public void DoSomething()
    {
        DoSomethingBase();
    }

    protected virtual void DoSomethingBase()
    {
        Console.WriteLine("DoSomethingBase");
    }
}

class Ext1 : MyBaseClass
{

}

class Ext2 : MyBaseClass
{
    protected override void DoSomethingBase()
    {
        Console.WriteLine("Overridden DoSomethingBase");
    }
}

Ext1类不会覆盖基类的行为,因此使用基类中的DoSomethingBase()Ext2会覆盖基本方法,因此会调用重写的方法。此代码打印:

DoSomethingBase
Overridden DoSomethingBase

MyBaseClass类也可以标记为abstract,以防止实例化基类本身。