- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个简单的代码,我想知道为什么以及如何选择某些方法而不是其他方法:
A 类:
public class A {
int f(A aa){
return 1;
}
}
B 类:
public class B extends A {
int f(A aa){
return 2;
}
int f(B bb){
return 3;
}
}
测试:
public class Test {
public static void main(String[] args) {
A a = new A();
A ab = new B();
B b = new B();
System.out.println(a.f(a));
System.out.println(a.f(ab));
System.out.println(a.f(b));
System.out.println(ab.f(a));
System.out.println(ab.f(ab));
System.out.println(ab.f(b));
System.out.println(b.f(a));
System.out.println(b.f(ab));
System.out.println(b.f(b));
}
}
现在,这个程序的输出如下:
1
1
1
2
2
2
2
2
3
现在,你能告诉我为什么 System.out.println(ab.f(b))
输出 2 吗?
最佳答案
重载决议在编译时完成。 覆盖在运行时使用。
这意味着在编译时,编译器决定所有方法签名中的哪一个适合于方法调用。然后,在运行时,如果具有该签名的方法在正在使用的运行时对象中被覆盖,则使用被覆盖的方法。
在编译时,只有变量的静态类型 是已知的。也就是说,只考虑与变量的声明类型关联的方法签名。
在这种情况下,变量ab
被声明为A
。因此,只有 A
中存在的方法签名才会被考虑用于调用 ab.f(b)
。 A
类型中唯一的 f
是 f(A aa)
方法。该方法签名的调用是合法的,因此编译器生成的代码说“此时,调用方法f
,它有一个A
类型的参数,并且将 b
作为参数传递给它。”
当运行时,由于 ab
实际上是一个 B
实例,方法 f
有一个 A 类型的参数
实际上在其中被覆盖了,所以它会打印 2
,而不是 1
。
将此与 b.f(b)
进行对比。这里变量b
的声明类型是B
。因此,它有两个重载方法 f
- 一个带有 B
参数,一个带有 A
参数。在编译 时,它已经知道参数b
被声明为B
。所以最具体的重载是f(B bb)
。该调用被翻译成“使用 B
类型的单个参数调用 f
”。在运行时,这会打印 3。
区别是什么?在编译时,ab
是 A
类型,f(B bb)
不存在于该类型中。 b
是 B
类型,f(B bb)
存在并且是最具体的重载。
关于java - 在多态性问题上需要帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34832316/
我来自 Asp.Net 世界,试图理解 Angular State 的含义。 什么是 Angular 状态?它类似于Asp.Net中的ascx组件吗?是子页面吗?它类似于工作流程状态吗? 我听到很多人
我一直在寻找 3 态拨动开关,但运气不佳。 基本上我需要一个具有以下状态的开关: |开 |不适用 |关 | slider 默认从中间开始,一旦用户向左或向右滑动,就无法回到N/A(未回答)状态。 有人
我是一名优秀的程序员,十分优秀!