【问题标题】:Java: In child classes that implement interface, how to implement and refer to child class only methods and classes?Java:在实现接口的子类中,如何实现和引用子类唯一的方法和类?
【发布时间】:2016-03-17 21:08:04
【问题描述】:

我在理解 Java 中有关继承和多态的一些基本概念时遇到了困难。

我正在尝试为实现给定父接口的子类调用子类方法。但是,当我实例化子类对象并将其放在父类接口中时,我不能只调用这些子类的方法。如何在不影响多态性的情况下做到这一点。

Contract.java

package test;

public interface Contract {

    void getLog();
}

myContract.java

package test;

public class myContract implements Contract {

    public void getLog()
    {
        System.out.println("logging in myContract");
    }

    public void anotherMethod()
    {
        System.out.println("another method");
    }
}

app.java:

package test;

public class app {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Contract myContract = new myContract();

        //I can't call below method in child class
        myContract.anotherMethod();
    }

}

【问题讨论】:

  • 这是代码异味。如果需要与MyContract的实例交互,那么静态类型应该是MyContract。或者,您可以将anotherMethod() 添加到界面如果它真的属于那里,或者在您使用它的地方向下转换,但向下转换表示设计问题。您没有为任何人提供足够的信息或背景来建议“正确”的替代方案。
  • 你想要做的是违背多态性的目的。看到这个相关的问题:What is so important about polymorphism

标签: java


【解决方案1】:

使用instanceof 运算符来检查您的对象是否是指定类型的实例。如果是,您可以强制转换对象并调用方法。

    Contract myContract = new myContract();

    if(myContract instanceof MyContract){
        ((MyContract)myContract).anotherMethod();
    }

【讨论】:

    【解决方案2】:

    正如其他人所提到的,您可以将其转换为 MyContract。但是,如果您想在可以具有多个不同实现的多个实例上执行此操作,比在 instanceof 之后将它们强制转换为它们的实现更好的解决方案是使用 visitor pattern

    【讨论】:

      【解决方案3】:

      在你的主要方法中,你有这个:

      // TODO Auto-generated method stub
      Contract myContract = new myContract();
      
      //I can't call below method in child class
      myContract.anotherMethod();
      

      这段代码sn-p的最后一行没有编译的原因是因为编译器不能“看到”“.anotherMethod()”。您已将 myContract 变量声明为 Contract 类型的对象。因此,即使您已经使用“new myContract()”对其进行了实例化,您也无法调用“.anotherMethod()”,因为“.anotherMethod()”在 Contract 接口中不存在。

      有两种方法可以使这项工作:

      1. 将“.anotherMethod()”签名添加到合约接口。如果这样做,那么编译器将能够在上述代码 sn-p 的最后一行中“看到”它。

      2. 将“myContract”变量声明为 myContract 类型(而不是“Contract”类型,这是您在上面声明的方式。

      除此之外,我强烈建议您遵循以驼峰命名方式命名类和接口的约定。这样,您可以通过将类名称设为“MyContract”而将实例变量命名为“myContract”来消除一些混淆。

      【讨论】:

        【解决方案4】:

        您的命名有冲突。您正在创建一个名为“myContract”的类,以及一个对象“myContract”。由于范围(对象在范围内),您将作为对象访问该对象。对所有类名使用大写首字母,并且不要为对象使用与类已经存在的名称相同的名称。 (也许将类 myContract 重命名为 ControlImpl)。

        【讨论】:

          猜你喜欢
          • 2018-06-29
          • 1970-01-01
          • 2011-11-20
          • 1970-01-01
          • 1970-01-01
          • 2013-12-14
          • 2020-04-02
          • 2016-06-10
          • 2016-01-27
          相关资源
          最近更新 更多