使用子类来替换未实现接口的Java类

时间:2008-12-10 11:19:16

标签: java file delegates subclass

例如,java.io.File只是一个具体的类。我的替代品支持解析Windows快捷方式。我需要预处理构造函数参数来解析可能的.lnk文件,因为无法访问在抽象路径上执行规范化/规范化/解析的FileSystem对象。预处理的需要排除了纯子类 - 在调用super(...)之前不能进行预处理,而File是不可变的。所以我扩展File并使用委托,覆盖所有File的构造函数和方法(在所有构造函数中调用super(“”))。

这很好用,但显然不理想 - 如果File更改,我将不会覆盖任何新方法或构造函数,这将公开底层的空抽象路径名。我错过了一些明显的东西吗似乎应该有一个更简单/更好的方式。

4 个答案:

答案 0 :(得分:9)

在特定的情况下,你建议我看起来你最好选择一个单独的工厂类来做出关于规范化/规范化/解决的决定。

然后你可以让文件成为文件。简单。

答案 1 :(得分:4)

如果你真的想要子类路由,你可以通过将清理代码放在类之外或静态块中来欺骗对super()的调用必须是子类构造函数的第一行的要求。 :

public class MyFile extends File {

    public MyFile(String path) {

        // static blocks aren't ideal, this is just for demo purposes:
        super(cleanPath(path)); 
    }

    private static String cleanPath(String uncleanPath) {...}

}

krosenvold提出的工厂模式是另一个很好的解决方案。

答案 2 :(得分:2)

  

这很好用,但显然不理想 - 如果File更改,我将不会覆盖任何新方法或构造函数,这将公开底层的空抽象路径名。我错过了一些明显的东西吗?

不,您发现使用继承存在问题 - 子类与超类及其内部紧密耦合,因此它可能很脆弱。这就是为什么Effective Java和其他人说如果可能的话,你应该在继承之前支持委托。

我认为krosenvold的解决方案听起来很干净。

答案 3 :(得分:2)

在我看来,克罗森沃尔德的解决方案是可行的方法。

但是,如果你需要记录创建文件的原始路径,你可以实现一个包装类。

public class FileWrapper {

    private File file;
    private String path;

    private FileWrapper(String path) {
        this.path = path;
        file = new File(preProcess(path));
    }

    private String preProcess(String path) {
        // process
        return path;
    }

    public File getFile() {
        return file;
    }

    public String getPath() {
        return path;
    }
}