java - 将父类(super class)传递到需要子类的方法中

标签 java oop

好吧,虽然我试图找到一个可以解释问题的标题,但我可能必须对其进行扩展。

最近我实现了一个小程序,将用于控制磁带库。知道它必须与多种不同类型的磁带库配合使用,因此开发了以下设计。

interface Tapelibrary<T extends TapeDrive> {
    List<T> getListofDrives();
    void doSomethingWithDrive(T d);
}

class SpecificTapeLibrary implements Tapelibrary<HPDrive> {
    private List<HPDrive> driveList;

    SpecificTapeLibrary() {
        driveList.add(new HPDrive());
        driveList.add(new HPDrive());
        driveList.add(new HPDrive());
    }

    @Override
    public List<HPDrive> getListofDrives() {
      return driveList;
    }

    @Override
    public void doSomethingWithDrive(HPDrive d) {
       d.doSomethingHPspecific();
    }
}

abstract class TapeDrive {
    void doSomething() {
    }
}

class HPDrive extends TapeDrive {
    void doSomethingHPspecific() {
    }
}

正确的磁带库由工厂根据命令行参数确定。

public static void main(String[] args) {
    Tapelibrary<? extends TapeDrive> t = new TapeLibraryFabric().get();
    List<? extends TapeDrive> listOfDrives = t.getListofDrives();

    // the user selects a drive by using a small UI or something
    TapeDrive selectedDrive = listOfDrives.get(0);

    t.doSomethingWithDrive(selectedDrive); // compiler error
}

这确实有意义,因为编译器必须将父类(super class)型 TapeDrive 显式转换为子类型 HPDrive,这是 SpecificTapeLibrary 中的 doSomethingWithDrive(HPDrive) 方法所期望的

如何以良好的 oop 方式解决这个问题?我最终没有使用泛型并在 doSomethingWithDrive 方法内部进行转换(如此处建议的: How to Pass a Child Class into a method requiring Super Class as parameter )。但这并不是最佳解决方案。

在写这篇文章时,我的脑海中突然出现了另一个更清晰的解决方案。 DriveSelector 类封装了选择过程。

class DriveSelector {
    <T> T selectDrive(List<T> inputList) {
        // give the user an UI or something to select a drive 
        return inputList.get(0);
    }
}

// the tape library then uses the selector
public void doSomethingWithSelectedDrive(DriveSelector selector) {
     HPDrive t = selector.selectDrive(driveList);
     t.doSomethingHPspecific();
}

还有其他想法吗?

最佳答案

用通用方法完成所有工作:

static <T extends TapeDrive> void doStuff(Tapelibrary<T> t) {
  List<T> listOfDrives = t.getListofDrives();

  // the user selects a drive by using a small UI or something
  T selectedDrive = listOfDrives.get(0);

  t.doSomethingWithDrive(selectedDrive);
}

然后从您的主方法中调用它:

Tapelibrary<? extends TapeDrive> t = new TapeLibraryFabric().get();
doStuff(t);

Ideone demo

它的工作方式是删除所有通配符 - 关于通配符的问题是编译器将每个通配符视为不同的,即使这些值是从单个泛型实例派生的。通过将内容放入这样的泛型方法中,您可以让编译器知道所有 T 都是同一类型 - 因此它可以知道调用是安全的。

关于java - 将父类(super class)传递到需要子类的方法中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42584592/

相关文章:

java - 根据基本的 oop 约定,菜单代码应该在 main 方法中还是在类中?

flutter - Dart继承类并在父类的函数中使用

Java - (非内部)可运行类中的 Actionlistener 不执行

php - 调用没有命名空间的静态自动加载类

oop - 各种语言的关键编程概念和术语

java - java中的点对点存储库

java - 高效的 Websocket 数据处理

python - 在创建时将属性附加到类

java - 当文件有多个空格时如何计算文件中的字数? - java

java - 您什么时候在 Objectify for GAE 中注册类(class)?