例如,java.io.File只是一个具体的类。我的替代品支持解析Windows快捷方式。我需要预处理构造函数参数来解析可能的.lnk文件,因为无法访问在抽象路径上执行规范化/规范化/解析的FileSystem对象。预处理的需要排除了纯子类 - 在调用super(...)之前不能进行预处理,而File是不可变的。所以我扩展File并使用委托,覆盖所有File的构造函数和方法(在所有构造函数中调用super(“”))。
这很好用,但显然不理想 - 如果File更改,我将不会覆盖任何新方法或构造函数,这将公开底层的空抽象路径名。我错过了一些明显的东西吗似乎应该有一个更简单/更好的方式。
答案 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;
}
}