继承——面向对象编程(OOP)易混淆概念及相关问题
问题1:四种实例化场景的构造函数调用顺序
我逐个给你拆解每个场景的执行逻辑:
1. A a = new A();
调用顺序:1 → 2
解释:第一次创建A类的实例时,CLR会先触发A的静态构造函数(这个静态构造函数整个程序生命周期只会执行一次),然后再执行A的实例构造函数来初始化对象。
2. B b = new A();
调用顺序:1 → 2
解释:别被左边的B类型引用迷惑了!这里实际new的是A类对象,所以完全和场景1一样,B类的任何构造函数都不会被触发——毕竟我们根本没创建B的实例。
3. A c = new B();
调用顺序:1 → 3 → 2 → 4
解释:创建子类实例的规则是先处理静态构造,再处理实例构造:
- 首次创建B实例,先执行父类A的静态构造(1号);
- 接着执行子类B的静态构造(3号);
- 实例构造阶段,必须先调用父类A的实例构造(2号),再执行子类B的实例构造(4号)。
不管左边的引用是A还是B,只要实例是B,这个顺序就不会变。
4. B d = new B();
调用顺序:1 → 3 → 2 → 4
解释:和场景3完全一致!引用类型不影响构造函数的执行顺序,只要实例化的是B,就严格遵循“父静态→子静态→父实例→子实例”的顺序。
问题2:方法重载/隐藏场景下的调用逻辑
这里分两种情况给你说明:
情况1:方法重载(B的Method()是重载版本)
重载的核心是方法签名不同(比如A是void Method(),B是void Method(int num))。题目里的调用都是无参数的Method(),所以所有调用都会命中A类的5号方法:
a.Method();→ 调用5号(A实例直接调用自己的方法)b.Method();→ 调用5号(b的引用是B,但实际是A实例,执行A的无参方法)c.Method();→ 调用5号(c是A引用,指向B实例,但B没有无参的重载方法,所以执行继承自A的5号)d.Method();→ 调用5号(B实例的无参Method还是继承自A的,因为B的重载是带参的,不匹配调用)
情况2:方法隐藏(B用new关键字隐藏A的Method())
方法隐藏的核心是看引用类型,而不是实例类型:
a.Method();→ 调用5号(A引用指向A实例,直接用A的方法)b.Method();→ 调用5号(B引用但实际是A实例,执行A的方法)c.Method();→ 调用5号(A引用指向B实例,方法隐藏下父类引用只会调用父类的方法)d.Method();→ 调用6号(B引用指向B实例,调用B自己隐藏的方法)
内容的提问来源于stack exchange,提问作者Samra
相关产品推荐
相关产品推荐

