简体   繁体   English

Java多态性/重载惊喜

[英]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只保证传递一个TaskTopWorker.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM