Mono生命周期函数调用机制分析
Posted syzhang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mono生命周期函数调用机制分析相关的知识,希望对你有一定的参考价值。
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对于这个地方的原则就是:让父类中私有生命周期函数的也可以被子类访问到(用反射模拟实现),其他的依然符合多态和继承的概念。
以上是关于Mono生命周期函数调用机制分析的主要内容,如果未能解决你的问题,请参考以下文章
在不存在的片段上调用片段生命周期和 onCreate 的问题