我最近遇到了以下情况:
我有一个超类A和一个从它派生的B类。一个函数,比如说oracle,返回任何一种类型的对象。我想根据类型做不同的事情,但我不能为A和B引入新的成员函数。
一种解决方案是根据getClass()。getName()进行分支。但是,我想知道多态是否可以使用重载实现相同的行为:
public class Main
{
static class A{}
static class B extends A{}
public static void foo(A a) { System.out.println("A"); };
public static void foo(B b) { System.out.println("B"); };
static A oracle()
{
return (Math.random() > 0.5) ? new A() : new B();
}
public static void main(String[] args)
{
A x = oracle();
foo(x);
}
}
这总是输出“A”,我怀疑这是由于用于解析函数调用的早期绑定。有人可以承认吗?
答案 0 :(得分:3)
在技术方面,Java是一种单一调度 OOP语言。这意味着运行时决定调用哪个方法(方法调度)只考虑第一个方法参数 - 点左边的那个。在那里你可以看到这个原理如何根深蒂固地用于语言,第一个论点甚至得到了特殊的句法处理。
因此,不,您无法通过重载来实现运行时多态性。
答案 1 :(得分:2)
本文对正在发生的事情做了很好的解释: Overloading is compile-time binding
我认为您要做的就是在instanceof
方法中实现foo
代码
以不同的方式对待每种类型。
关于你的getClass().getName()
断言,你绝不应该这样做。这就是instanceof
的用途。从更具体到更不具体的工作(即从B开始,然后从A开始)。
答案 2 :(得分:1)
这是因为foo(A a)
是具有完全相同方法签名的函数,因此它将使用那个。
在这种情况下,foo(B b)
永远不是一个有效的选项,因为你需要做反思才能意识到它可能是一个合适的方法。 Java不会对所有参数使用反射,只是为了查看方法是否最终匹配,这只会耗费太多时间。
如果要调用不同的方法,则应使用Class继承或其他多态技术。
答案 3 :(得分:0)
您需要将您的foo方法作为A和B类中的实例方法。然后调用你的情况x.foo()与一个B对象的实例应该给你结果“B”。
答案 4 :(得分:0)
尝试
static class A {
public void foo() {
System.out.println("A");
}
}
static class B extends A {
public void foo() {
System.out.println("B");
}
}
public static void main(String[] args) {
A x = oracle();
x.foo();
}
会员功能知道他们所属的类型。