Использование подклассов для замены класса Java, который не реализует интерфейс - PullRequest
3 голосов
/ 10 декабря 2008

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

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

Ответы [ 4 ]

9 голосов
/ 10 декабря 2008

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

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

4 голосов
/ 10 декабря 2008

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

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

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

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 декабря 2008

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

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

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

...