[英]Java Polymorphism/Overloading surprise
Given this code: 给出以下代码:
class Task{};
class TaskA extends Task{};
class TopWorker{
//... omitting constructor, instance variables, etc.
public void work(Task task){
this.subWorkerA.work(task)
//followed by more subworkers...
}
}
class SubWorkerA{
public void work(TaskA task){
// Subworker A does something interesting here
}
public void work(Task task){
// Subworker A doesn't care, do nothing
}
}
TaskA task = new TaskA();
(new TopWorker).work(task);
I would expect that the TaskA
signature for work()
would be called- instead, the Task
version is being called. 我希望可以TaskA
work()
的TaskA
签名-而是可以调用Task
版本。 I assume the issue is that TopWorker
only accepts a Task
, and so java must dispatch SubWorker.work()
accordingly. 我认为问题是TopWorker
仅接受Task
,因此java必须相应地调度SubWorker.work()
。
Is there any way around this problem? 有什么办法可以解决这个问题? Assume that I have many Tasks
and many workers, and the TopWorker
is there to coordinate their results. 假设我有许多Tasks
和许多工作人员,并且TopWorker
在这里协调他们的结果。
The reason why the TaskA
signature is not being called is because TopWorker.work
guarantees only a Task
to be passed in and not a TaskA
instance. 之所以没有调用TaskA
签名,是因为TopWorker.work
只保证传递一个Task
, TopWorker.work
保证TaskA
实例。 SubWorkerA.work(Task task)
ends up getting called because it's the only work
method that takes type Task
in the arguments. SubWorkerA.work(Task task)
最终被调用,因为它是唯一在参数中采用Task
类型的work
方法。 If you instead call this.subWorkerA.work((TaskA)task)
, the desired method will get called, albeit in an inherently unsafe manner. 如果改为调用this.subWorkerA.work((TaskA)task)
,则所需的方法将被调用,尽管本质上是不安全的。
I think you're probably confusing method overloading with late binding. 我认为您可能将方法重载与后期绑定混淆了。 Overloading simply allows you to name methods the same way so long as they have different numbers of arguments or argument types. 重载只是允许您以相同的方式命名方法,只要它们具有不同数量的参数或参数类型即可。 When you call overloaded methods, the correct method is chosen based on the makeup of the arguments. 调用重载方法时,将根据参数的组成选择正确的方法。 In late binding, you override a method by duplicating its signature in a sub-class, which forces the overriding method to be called even if you refer to its parent object as an instance of the super class. 在后期绑定中,您通过在子类中复制其签名来覆盖方法,即使您将其父对象引用为超类的实例,也将强制调用该覆盖方法。
Here is a workaround... 这是一种解决方法...
public void work(Task task){
if (task instanceof TaskA) {
work((TaskA) task);
}
// Subworker A doesn't care, do nothing
}
I think that Task
would better be an interface, at runtime you can figure out 我认为Task
最好是一个接口,在运行时您可以找出
public void work(Task task){
if (task instanceof TaskA)
this.subWorkerA.work((TaskA) task);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.