Использование подклассов для замены класса Java, который не реализует интерфейс

Например, java.io.File - это просто конкретный класс. Моя замена для него поддерживает разрешение ярлыков Windows. Мне нужно предварительно обработать параметры конструктора для разрешения возможных файлов .lnk, потому что объект FileSystem, который выполняет нормализацию / каноническое определение / разрешение абстрактных путей, недоступен. Необходимость предварительной обработки исключает использование чистого подкласса - невозможно выполнить предварительную обработку перед вызовом super (...), а File является неизменным. Поэтому я расширяю File и использую делегат, переопределяя все конструкторы и методы File (вызывая super ("") во всех конструкторах).

Это хорошо работает, но, очевидно, не идеально - если файл изменится, я не буду переопределять какие-либо новые методы или конструкторы, и это откроет нижележащий пустой абстрактный путь. Я что-то упускаю из виду? Кажется, должен быть более простой / лучший способ.

10.12.2008 11:19:15
4 ОТВЕТА
РЕШЕНИЕ

В конкретном случае вы предлагаете, мне кажется, что вам лучше с отдельным классом фабрики, который принимает решения о нормализации / каноническом решении / разрешении.

Тогда вы можете просто позволить файлу быть файлом. Simpler.

9
10.12.2008 11:23:53

Если вы действительно хотите маршрут подкласса, вы можете обмануть требование, что вызов 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, является еще одним хорошим решением.

4
10.12.2008 11:28:18
Да, я думаю, что это был ответ, который я просил, но krosenvold дает очевидное и лучшее решение, о котором я знал, что был глуп. Я на самом деле предпочитаю этот стиль фабричным методам, и его не сложно изменить, если File это сделает. Тем не менее, завод полностью избегает такого типа муфт.
Sam Brightman 10.12.2008 13:53:52
Назовите этот «глупый день». Я думаю, что ваш на самом деле работает так же хорошо.
Sam Brightman 10.12.2008 14:01:10
Честно говоря, я думаю, что фабрика - лучшее решение, но Кросенволд первым пришел туда ...
Dan Vinton 10.12.2008 20:36:27

Это хорошо работает, но, очевидно, не идеально - если файл изменится, я не буду переопределять какие-либо новые методы или конструкторы, и это откроет нижележащий пустой абстрактный путь. Я что-то упускаю из виду?

Нет, вы обнаружили проблему с использованием наследования - подклассы тесно связаны с суперклассами и их внутренними компонентами, поэтому они могут быть хрупкими. Вот почему Effective Java и другие говорят, что вы должны отдавать предпочтение делегированию перед наследованием, если это возможно.

Я думаю, решение Крозенволда звучит чисто.

2
10.12.2008 11:32:25
Да, я знаю о необходимости одобрения делегирования, но если нет интерфейса (например, с File) для реализации через делегирование, ваш новый класс не может использоваться в качестве прямой замены старого (например, при переходе на другое ядро ​​Java). классы).
Sam Brightman 10.12.2008 13:48:01

Мне кажется, что решение Кросенволда - это путь.

Но если вам нужно сохранить исходный путь, по которому был создан файл, вы можете реализовать класс-оболочку.

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
10.12.2008 11:36:01