在java中的重载方法中使用更具体的数据类型

时间:2009-12-02 19:42:27

标签: java oop

我有一些具有相同界面类型的不同对象的arraylist,例如:

Interface interface {}

class A implements interface {}

class B implements interface {}

我还有一个重载方法,它实现了接口的所有继承对象:

public void doSomething(A obj) {}

public void doSomething(B obj) {}

编译器还强制我用接口编写重载方法:

public void doSomething(interface obj) {}

然后我浏览列表的值并调用方法:

for (interface obj: myList) {
   doSomething(obj);
}

现在因为obj的类型是'interface',所以在obj实际上是B类的情况下调用doSomething(接口obj)而不是doSomething(B obj)。

我可以让java做其他的,所以当obj是A类时调用doSomething(A obj),当obj是B类时调用doSomething(B obj)吗?

5 个答案:

答案 0 :(得分:3)

Java使用早期绑定,这意味着obj的类型是在编译期间定义的,而不是在运行时定义的。由于您的代码表明obj是接口类型,因此编译器将始终调用将接口作为参数的方法。

你有两种选择让它调用正确的方法:

  1. (非常难看)在调用对象时使用instanceof和cast检查obj类型。

    for (interface obj: myList) {
       if(obj instanceof A)
          doSomething((A) obj);
       else if(obj instanceof B)
          doSomething((B) obj);
       else
          doSomething(obj); // Calls the method receiving Interface
    }
    
  2. 在界面中实现访问者方法,因此A和B都会在访问时调用方法doSomething(this)。

    interface Interface {
        void visit(OtherClass methodHolder);
    }
    
    class A implements Interface {
        public void visit(OtherClass methodHolder) {
            methodHolder.doSomething(this);
        }
    }
    
    class B implements Interface {
        public void visit(OtherClass methodHolder) {
            methodHolder.doSomething(this);
        }
    }
    

答案 1 :(得分:2)

有一个技巧。免责声明:这很难看。

如果使用doSomething方法的类被称为类Performer,如:

class Performer {
  void doSomething(A x);
  void doSomething(B x);
  void doSomething(Inf x);
}

您可以添加到您的界面Ifc:

interface Ifc {
  void acceptPerformer(Performer p);
}

在A和B类中都实现如下:

void acceptPerformer(Performer p) {
  p.doSomething(this);
}

并实现这样的doSomething(Ifc x)方法:

void doSomething(Ifc x) {
  x.acceptPerformer(this);
}

这听起来很奇怪,但确实有效。当调用接受接口的doSomething方法时,它将调用具体类上的acceptPerformer。当该类重新调用doSomething时,它将知道它是哪种类型,并将调用正确的doSomething!

答案 2 :(得分:0)

这里的多态方法是在doSomthing()中定义interface并在AB中实现它,然后在循环中调用它。根据具体对象,将运行不同的代码。

答案 3 :(得分:0)

是方法

public void doSomething(interface obj)

定义为界面的一部分?如果编译器强迫你编写方法,这是唯一有意义的事情。

这就引出了为什么要尝试更改实现中接口的方法签名的问题。该接口旨在成为对象外观的契约。

答案 4 :(得分:-1)

您可以使用Java instanceof运算符来检查哪个类实现了您的接口:

if(obj instanceof A) {
    // do something
} else {
    // do something else
}

但更好的方法是让一个方法只接受你所创建的接口实例的任何对象,如Atmocreations所述。