Может ли открытый класс с невидимым конструктором быть расширен классом из другого пакета? - PullRequest
0 голосов
/ 23 апреля 2019

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

public class Token implements IToken {
    Token(int kind, Object source, int offset, int endOffset) {
        ...
    }
    ...
}

Мой подкласс будет

public class MyToken extends Token {
    ...
}

Получается ошибка:

Неявный супер-конструктор Token () не определен для конструктора по умолчанию. Должен определить явный конструктор

Когда я добавляю конструктор:

MyToken(int kind, Object source, int offset, int endOffset) {
    super(kind, source, offset, endOffset);
}

Я получаю сообщение об ошибке

Токен конструктора (int, Object, int, int) не отображается

Есть ли способ расширить этот класс? Если нет, то какова цель объявления его публичным?

Ответы [ 5 ]

2 голосов
/ 23 апреля 2019

Цель класса public с ограниченным конструктором может состоять в том, чтобы оставить конструкцию классу-другу или статическому методу фабрики (создания).

Здесь можно использовать этот заводской шаблон. Тогда вы можете использовать:

public class MyToken implements IToken {
    private Token delegate;

    public MyToken(int kind, Object source, int offset, int endOffset) {
        // Factory usage:
        delegate = Token.create().withKind(kind).withSource(source)...;
    }

    public int getKind() {
        return delegate.getKind();
    }

    ...

В противном случае вы можете создать в тот же пакет , что и Token (базовый) класс с конструктором public. При модульном java> 8 этот трюк больше не будет разрешен.

Мое личное предположение состоит в том, что Token будет создан некоторым классом Parser / Scanner в том же пакете. На самом деле даже дочерний класс Token может быть возвращен, поскольку он может быть вложенным внутренним классом, который может обращаться к полям контейнера Parser, например, line как String, filePath.

Лучше всего создать собственную реализацию IToken.

2 голосов
/ 23 апреля 2019

Любой подкласс должен иметь доступ как минимум к одному конструктору базового класса.

Если вы хотите, чтобы подкласс жил в другом пакете, вы должны сделать конструктор как минимум protected.

Поскольку это происходит из сторонней библиотеки, похоже, что они не хотят, чтобы вы подкласс Token. Вероятно, здесь есть альтернатива подклассам для всего, что вам нужно сделать.

Непредоставление общедоступного конструктора является распространенным шаблоном, когда вам (автору библиотеки) необходимо контролировать, как создаются экземпляры (например, для реализации одиночных наборов или для принудительного использования фабричных методов).

Если нет, какова цель объявления его публичным?

Публичный класс может использоваться из любой точки мира, то есть вы можете вызывать методы для заданного вами экземпляра (даже если вы не можете создавать новые экземпляры самостоятельно).

1 голос
/ 23 апреля 2019

Ваша точка зрения действительна при создании класса public с конструктором protected, но вы можете попробовать композицию для достижения желаемой функциональности, когда класс MyToken содержит ссылку на класс Token.Таким образом, мы будем следовать принципу Composition over Inheritance.

1 голос
/ 23 апреля 2019

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

List<Token> tokens = stream.getTokens();

Таким образом, в основном библиотека будет создавать токены, и вы можете работать с ними, но не расширять или создавать какие-либо изсвой собственный.

1 голос
/ 23 апреля 2019

Нет . Это невозможно без изменения класса Token.

Некоторые библиотеки могут изменять класс во время выполнения, но я настоятельно не рекомендую вам идти по этому пути.

...