MonoBehaviour生命周期函数调用机制分析

 

1.生命周期函数的调用机制是反射,而并非继承。

    我们打开Mono后发现其的确也没有生命周期函数的实现,向上翻父类中也没有,好,可以确定其就不是继承了。

下面验证下是否是反射,拿void start()函数来说,其原本是private,但如果你硬要改成public,其执行起来也什么影响(但你肯定不想外界去手动调用你的Start吧),甚至于你把它设置成private IEnumerator Start()都可以,因为是发射调用嘛,名字对了就可以。如下图

                       

(针对Start使用IEnumerator是肯定可以的,但其他生命周期函数好像不可以这么用,具体为什么不可以查过没查到很详细的回答,我想应该是Unity内部实现机制上就这么规定只有start返回类型可以是IEnumerator吧,朋友们有了解这方面的欢迎留言指导)

 

2.Unity在当前Mono子类中找不到对应函数时,会主动再去父类中找

比如我们设定:

public class People : MonoBehaviour
{
    private void Start ()
    {
        Debug.Log("执行People的Start函数");
    }
}

public class Teacher : People
{
    void Start ()
    {
        Debug.Log("执行了Teacher的Start函数");
    }
}

 

a.这种是最基本的情况,大家肯定都知道,这是执行Teacher的Start函数,而people的Start函数不执行;

b. 但如果我把Teacher的Start函数去掉后,如下

public class Teacher : People
{
}

      此时再运行,就会发现其会执行父类People的Start函数。这里注意,Teacher的Start函数必须直接去掉,不能如下这样 

private void Start ()
{
    //Debug.Log("执行People的Start函数");
}

       因为这样也算是有Start函数,Unity通过反射会在Teacher中查找到,故不会再去People中查找。其实。其实这一点很重要,很多子类要掩盖父类的生命周期函数的时候,经常会手写一个空的去覆盖,你要是觉得这个空函数没用直接删了,那就错了。

 

3.那当调用父类Start函数时,其Start内部调用成员函数的机制是什么样的呢,且看下面:

public class People : MonoBehaviour
{
    private  void Start ()
    {
        Debug.Log("执行People的Start函数 +"+ this.GetType().ToString());
        Debug.Log("执行People的Start函数 +" + this.Sign());
        Debug.Log("执行People的Start函数 +" + this.Mark());
    }
    public virtual string Sign()
    {
        return "This is belong to People";
    }
    public virtual string Mark()
    {
        return "People Mark";
    }
}

public class Teacher : People
{
    //void Start ()
    //   {
    //       Debug.Log("执行了Teacher的Start函数");
    //}
    public override string Sign()
    {
        return "This is belong to Teacher";
    }
    public new string Mark()
    {
        return "Teacher Mark";
    }
}

最后执行结果:

 

      所以,当执行父类的Start函数时,其机制采用的就是多态,声明的是父类,子类的实现(父类的壳,子类的填充),所以我们在项目中构建父类框架时,就可以随心所欲的写,如果子类中要改写哪个函数,直接overide重写就可以了,这是很方便的。

 

       同时,还有一点,你会发现上述代码中,people的Start函数不论声明是public还是private,对结果都不影响,也就是说Unity对于这个地方的原则就是:让父类中私有生命周期函数的也可以被子类访问到(用反射模拟实现),其他的依然符合多态和继承的概念。

 

 

 

posted @ 2018-05-05 12:32  天蝎の守护  阅读(407)  评论(0编辑  收藏  举报