【问题标题】:Use more specific datatype in overloaded method in java在java中的重载方法中使用更具体的数据类型
【发布时间】:2009-12-03 04:17:17
【问题描述】:

我有一些具有相同接口类型的不同对象的数组列表,例如:

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 的类型是“接口”,所以调用 doSomething(interface obj) 而不是说 doSomething(B obj),以防 obj 实际上属于 B 类型。

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

【问题讨论】:

  • doSomething() 方法在哪个类中实现?他们是 A、B 还是其他类别的成员。
  • 它们在为 A 和 B 创建适配器/包装器对象的工厂类中实现。

标签: java oop


【解决方案1】:

Java 使用早期绑定,这意味着 obj 的类型是在编译期间定义的,而不是在运行时定义的。由于你的代码说 obj 是 interface 类型,编译器总是会调用获取 interface 作为参数的方法。

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

  1. (非常丑陋)在调用对象时使用 instanceof 和强制转换检查 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);
        }
    }
    

【讨论】:

    【解决方案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!

    【讨论】:

    • 您基本上是在描述访问者模式。
    • 模式永远不丑;)
    • 如果原始发帖人想要进一步阅读,这被称为“双重调度”,并且很少使用(根据我的经验)在运行时类型信息很容易获得并且强制转换是正常活动的 Java 中.如有必要,仍然是一个有用的成语。
    • 注意:虽然“访问者模式”通常依赖于双重调度,但它与双重调度不同。不过,这些例子是相似的。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      是方法

      public void doSomething(interface obj)
      

      定义为接口的一部分?如果编译器强迫您编写方法,那是唯一有意义的事情。

      这就引出了一个问题,即为什么您要尝试在实现中更改接口的方法签名。该接口旨在成为对象外观的合同。

      【讨论】:

      • 不,我在这里混淆了一些东西,抱歉,编译器什么也没说,这是一个运行时错误。该方法不是接口的一部分。
      【解决方案5】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-11-07
        • 1970-01-01
        • 1970-01-01
        • 2012-03-10
        • 1970-01-01
        相关资源
        最近更新 更多