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

在java中的重载方法中使用更具体的数据类型,java,oop,Java,Oop,我有一些具有相同接口类型的不同对象的arraylist,例如: Interface interface {} class A implements interface {} class B implements interface {} 我还有一个重载方法,用于实现接口的所有继承对象: public void doSomething(A obj) {} public void doSomething(B obj) {} if(obj instanceof A) { // do

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

Interface interface {}

class A implements interface {}

class B implements interface {}
我还有一个重载方法,用于实现接口的所有继承对象:

public void doSomething(A obj) {}

public void doSomething(B obj) {}
if(obj instanceof A) {
    // do something
} else {
    // do something else
}
编译器还强制我使用接口编写重载方法:

public void doSomething(interface obj) {}
然后我遍历列表的值并调用该方法:

for (interface obj: myList) {
   doSomething(obj);
}
现在,由于obj的类型是“接口”,因此如果obj实际上是类型B,则调用doSomething(接口obj)而不是doSomething(B obj)


我是否可以让java执行其他操作,因此当obj为A类型时,它调用doSomething(A obj),当obj为B类型时,它调用doSomething(B obj)?

您可以使用java
instanceof
操作符来检查实现接口的类:

public void doSomething(A obj) {}

public void doSomething(B obj) {}
if(obj instanceof A) {
    // do something
} else {
    // do something else
}

但更好的方法是使用一种方法,该方法只接受任何作为您创建的接口实例的对象,正如Atmocreations所述。

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

要使其调用正确的方法,有两种选择:

  • (非常难看)在调用对象时使用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
    }
    
  • 在接口中实现一个访问者方法,这样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);
        }
    }
    

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

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

    如果使用doSomething方法的类被称为类执行者,如中所示:

    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);
    }
    
    void doSomething(Ifc x) {
      x.acceptPerformer(this);
    }
    
    并实施如下剂量测定法(Ifc x):

    void acceptPerformer(Performer p) {
      p.doSomething(this);
    }
    
    void doSomething(Ifc x) {
      x.acceptPerformer(this);
    }
    
    这听起来很奇怪,但很管用。调用接受接口的doSomething方法时,它将调用具体类上的acceptPerformer。当该类重新调用doSomething时,它将知道它是哪种类型,并将调用正确的doSomething

    是一种方法

    public void doSomething(interface obj)
    
    定义为接口的一部分?如果编译器强迫您编写方法,那么这是唯一有意义的事情


    这就引出了一个问题:为什么要在实现中尝试更改接口的方法签名。接口是关于对象外观的约定。

    doSomething()方法在哪个类中实现?它们是A、B或其他类的成员。它们在为A和B创建适配器/包装器对象的工厂类中实现。您基本上是在描述访问者模式。模式从来都不丑陋;)如果原始海报希望进行进一步阅读,这称为“双重分派”,在Java中很少使用(以我的经验),因为Java中可以随时获得运行时类型信息,而强制转换是一项正常的活动。如果需要,这仍然是一个有用的习惯用法。注意:虽然“访问者模式”通常依赖于双重分派,但它与双重分派不同。这些例子是相似的。不,我在这里混合了一些东西抱歉,编译器什么都没说,这是一个运行时错误。该方法不是接口的一部分。