Запретить прямое расширение Java-класса вне его пакета - PullRequest
5 голосов
/ 08 апреля 2009

У меня есть пакет с

public abstract class Player { /*...*/ }

и эти

public abstract class GamePlayer extends Player { /*...*/ }
public abstract class TournamentPlayer extends Player { /*...*/ }
public abstract class StatelessPlayer extends Player { /*...*/ }

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

Вопрос: Как мне запретить пользователям расширять Player напрямую?

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

Ответы [ 5 ]

18 голосов
/ 08 апреля 2009

Сделать конструкторы в Player только для доступа к пакету. Тогда они не смогут вызывать конструктор или расширять его сами. Если у вас нет явного конструктора в Player, создайте его (иначе компилятор создаст открытый конструктор по умолчанию без параметров).

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

Это работает, потому что любой конструктор (кроме java.lang.Object) должен вызывать конструктор суперкласса (явно или неявно). Если доступных конструкторов нет, вы не можете создать подкласс.

9 голосов
/ 08 апреля 2009

Убедитесь, что конструкторы Player не являются публичными:

public abstract class Player {
    Player() {
        // initialization goes here
    }
}

Тогда классы могут расширять Player из одного и того же пакета, но не должны иметь возможности извне пакета.

0 голосов
/ 08 апреля 2009

Я бы порекомендовал

  • Создание общедоступных интерфейсов для вещей, к которым клиенты хотят получить доступ, но не для создания или подкласса
  • Создание открытых классов для вещей, к которым вы хотите, чтобы клиенты обращались и , создание или подкласс
  • все остальное должно быть закрытым

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

Чтобы разрешить использование нескольких пакетов с защитой, взгляните на OSGi.

OSGi позволяет вам ограничивать, к каким пакетам пакет (jar) разрешает доступ другим пакетам, и даже устанавливать «дружественные» пакеты, которым разрешена дополнительная видимость.

Модель Java «пакет как защита» недостаточна, когда вы действительно хотите защитить библиотеки, которые становятся большими ...

0 голосов
/ 08 апреля 2009

Хм ... сделать класс Player закрытым? Просто опустите "public", тогда он будет закрытым для пакета, то есть только классы в одном пакете могут расширять его.

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

0 голосов
/ 08 апреля 2009

Используйте модификатор доступа по умолчанию, также известный как «Пакетный доступ». Другими словами, не указывайте модификатор доступа

abstract class Player { /*...*/ }

Документация на веб-сайте Sun описывает все модификаторы доступа более подробно.

...