Using a subclass to replace a Java class that does not implement an interface

For example, java.io.File is just a concrete class. My replacement for it supports the resolution of Windows keyboard shortcuts. I need to pre-process the constructor parameters to allow possible .lnk files, because the FileSystem object that performs normalization / canonicalision / resolution on abstract paths is not available. The need for preprocessing eliminates pure subclasses - it cannot preprocess before calling super (...), and the file is unchanged. Therefore, I expand the file and use the delegate, overriding all the constructors and methods of the file (calling super ("") in all the constructors).

This works well, but obviously not perfect - if the file changes, I will not override any new methods or constructors, and this will open a basic empty abstract path. Am I missing something? There seems to be a simpler / better way.

+3
source share
4 answers

In the specific case, you assume that it seems to me that you are better off with a separate factory class that makes decisions about normalization / canonical solution / resolution.

Then you can just enable File be File. Simpler.

+9
source

If you really need a subclass route, you can fool the requirement that the super() call should be the first line of the subclass constructor by placing your cleanup code outside your class or in a static block:

 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) {...} } 

The factory template proposed by krosenvold is another good solution.

+4
source

This works well, but obviously not perfect - if the file changes, I will not override any new methods or constructors, and this will open a basic empty abstract path. Am I missing something?

No, you noticed a problem with using inheritance - these subclasses are closely related to superclasses and their internal elements, so they can be fragile. That's why Effective Java and others say you should approve delegation before inheritance, if possible.

I think the krosenvold solution sounds clean.

+2
source

It seems to me that krosenvold's solution is the way to go.

But if you need to keep a record of the source path that created the file, you can implement a wrapper class.

 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; } } 
+2
source

All Articles