【问题标题】:How to force Java dynamic method call binding [duplicate]如何强制Java动态方法调用绑定[重复]
【发布时间】:2012-12-19 20:34:56
【问题描述】:

可能重复:
Java Overload method with inherited interface

我不确定我的标题是否正确,但我相信如果不正确我会得到纠正。

我正在尝试像这样重载 helpIt 方法:

class Animal{}
class Dog extends Animal{}

class Foo implements AnimalHelper
{
  @Override
  public void helpAnAnimal( Animal a )
  { 
    helpIt( a );
  }

  private void helpIt( Dog d )
  {}

  private void helpIt( Animal a )
  {}
}

问题是它从不调用 helpIt(Dog d) 方法,即使动物是狗。 我使用这种方法是因为 Foo 类覆盖了 AnimalHelper 的 helpAnAnimal 方法。

我在这里错过了什么吗?我希望我不必检查 instanceof 然后强制转换它。 我相信这在 .Net 中是开箱即用的,但是记忆有点褪色并且可能不正确。

【问题讨论】:

标签: java dynamic polymorphism


【解决方案1】:

使helpIt() 方法成为Animal 的可覆盖实例方法:

class Foo implements AnimalHelper {
    @Override
    helpAnAnimal(Animal a) { 
        a.helpIt();
    }
}

或使用visitor pattern

public interface AnimalVisitor {
    void visitDog(Dog d);
    void visitOther(Animal a);
}

public class Animal {
    public void accept(AnimalVisitor visitor) {
        visitor.acceptOther(this);
    }
}

public class Dog extends Animal {
    public void accept(AnimalVisitor visitor) {
        visitor.acceptDog(this);
    }
}

class Foo implements AnimalHelper {
    @Override
    helpAnAnimal(Animal a) { 
        a.accept(new AnimalVisitor() {
            public void visitDog(Dog d) {
                helpIt(d);
            }
            public void visitOther(Animal a) {
                helpIt(a);
            }
        });
    }

    private void helpIt(Dog d) {
    }

    private void helpIt(Animal a) {
    }
}

【讨论】:

  • 谢谢。我以前从未使用过它,但我喜欢访问者模式,因为它将功能保留在我想要的位置并允许多种实现。
【解决方案2】:

你不能这样做,因为 Java 在编译时将它们都视为动物。

您可以做的是添加特定于实际 Dog 类的 Animal / Dog 算法,例如:

class Animal {

    protected boolean hasRabies() {
        return animal.name.equals("Tim");
    }
}

class Dog {

    @Override
    protected boolean hasRabies() {
        return false; // Apparently dogs can't have rabies?
    }
}

那么你可以在helpAnimal中调用这些具体的方法:

private void helpIt(Animal a) {
    if (a.hasRabies()) {
        a.setTreats(4000);
    } else {
        a.setTreats(3000);
    }
}

我不是兽医。

【讨论】:

    【解决方案3】:

    你是从同一个类的方法调用 helpIt(Dog d) 吗?

    注意,您已将私有方法用于这些方法,您将无法在此类之外使用这些方法。

    【讨论】:

      【解决方案4】:

      这里有几件事:

      • Java 绝对不会调用helpIt(Dog d) 方法,因为变量a 的类型是Animal。您必须手动检查并调用正确的方法。这实际上是一种向下/向上类型转换的情况。不过不确定.Net。

      • Foo 应该是什么?是辅助类吗?如果是这样,我不会实现接口,我会删除构造函数并将私有方法公开。这样你就可以直接使用它们,避免手动转换。

      • 1234563 >

      【讨论】:

        猜你喜欢
        • 2019-12-26
        • 2018-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多