Философия Java

Доступ класса


В Java, спецификаторы доступа могут также использоваться для определения того, какие классы внутри библиотеки будут доступны пользователям библиотеки. Если Вы хотите сделать класс доступным клиентскому программисту, Вы располагаете ключевое слово public где-нибудь перед открывающей фигурной скобкой тела класса. Это определяет, может ли клиентский программист создать объект этого класса.

Для контроля доступа к классу, спецификатор должен располагаться перед ключевым словом class. Итак, Вы можете написать:

public class Widget {

Если имя Вашей библиотеки mylib любой клиентский программист может получить доступ к Widget с помощью

import mylib.Widget;

либо

import mylib.*;

Однако, существует несколько дополнительных ограничений:

  • Может существовать только один публичный класс в одном модуле компиляции (файле). Идея состоит в том, что один модуль компиляции имеет один публичный интерфейс, представленный этим публичным классом. Он может иметь так много поддерживающих “дружественных” классов, сколько Вам необходимо. Если у Вас больше одного публичного класса в модуле компиляции, компилятор выдаст сообщение об ошибке.
  • Имя публичного класса должно полностью совпадать, с именем файла, содержащего соответствующий модуль компиляции, включая регистры символов. Так, например, для класса Widget, имя файла должно быть Widget.java, но никак не widget.java или WIDGET.java. Итак, Вы получите ошибку компиляции, если Вы с этим не согласны.
  • Возможно, но не типично, что у Вас будет модуль компиляции вообще без публичного класса. В этом случае, Вы можете называть файл как хотите.
  • А что, если у Вас есть такой класс внутри библиотеки mylib, который Вы используете для выполнения задач представленных классом Widget или каким-то другим публичным классом в mylib? Вы не хотите создавать документацию для клиентского программиста, и думаете, что когда-нибудь позже Вы захотите все изменить, либо вообще удалить класс, заменяя его другим. Чтобы иметь такую возможность, Вам нужно убедиться, что ни один клиентский программист не зависит от Ваших деталей реализации, скрытых внутри mylib. Для достижения этого, Вы удаляете ключевое слово public из класса, в этом случае он становится дружественным. (Этот класс может быть использован только внутри этого пакета.)


    Обратите внимание, что класс не может быть private (это сделало бы его никому не доступным кроме самого этого класса), или protected[35]. Итак, у Вас есть только выбор из двух вариантов: “дружественный” или публичный. Если Вы не хотите, чтобы кто-то другой имел доступ к классу, Вы можете сделать все конструкторы приватными, этим запрещая любому кроме Вас, создание объекта этого класса внутри статического члена класса.[36]. Вот пример:

    //: c05:Lunch.java



    // Демонстрирует спецификаторы доступа к классу.

    // Делает класс приватным

    // с помощью приватных конструкторов:

    class Soup { private Soup() {} // (1) Позволяет создание с помощью статического метода:

    public static Soup makeSoup() { return new Soup(); } // (2) Создание статического объекта

    // возвращается ссылка на запрос.

    // (шаблон "Singleton"):

    private static Soup ps1 = new Soup(); public static Soup access() { return ps1; } public void f() {} }

    class Sandwich { // Использует Lunch

    void f() { new Lunch(); } }

    // В файле только один публичный класс:

    public class Lunch { void test() { // Вы не можете сделать это! Приватный контруктор:

    //! Soup priv1 = new Soup();

    Soup priv2 = Soup.makeSoup(); Sandwich f1 = new Sandwich(); Soup.access().f(); } } ///:~

    До сих пор, большинство методов возвращали либо void либо примитивный тип, и описание:

    public static Soup access() { return ps1; }

    может вначале привести в замешательство. Слово перед именем метода (access) говорит о том, что возвращает метод. Пока чаще всего был тип void, и это означало, что метод не возвращает ничего. Но Вы можете возвратить также ссылку на объект, что и происходит здесь. Этот метод возвращает ссылку на объект класса Soup.

    Класс Soup показывает как предотвратить прямое создание класса, сделав все конструкторы приватными. Запомните, что если Вы не сознаете явно ни одного конструктора, конструктор по умолчанию (конструктор без аргументов) сам будет создан для Вас. Если Вы напишите конструктор по умолчанию, он не будет создаваться автоматически. Если Вы сделаете его приватным, то никто не сможет создать объект этого класса. Но сейчас, как кто-нибудь сможет использовать этот класс? Пример выше показывает два варианта. Первый, с помощью статического метода создается объект типа Soup и возвращается ссылка на него. Это может быть полезно, если Вы хотите выполнить несколько дополнительных операций с классом Soup, перед тем как его возвратить, либо если Вы хотите хранить количество создаваемых объектов типа Soup (возможно для контроля их популяции).



    Второй вариант использует так называемый шаблон разработки, который описан в книге Thinking in Patterns with Java, доступной на с www.BruceEckel.com. Этот специфический шаблон называется “singleton” потому что он позволяет создавать только один объект. Объект класса Soup создается как статический приватный член класса Soup, и существует один и только один объект, и Вы не можете получить его никаким другим способом, кроме как с помощью публичного метода access( ).

    Как ранее было упомянуто, если Вы вообще не ставите идентификатор доступа для класса, он становится “дружественным.” Это означает, что объект этого класса может быть создан в любом другом классе того же пакета, но не за его пределами. (Запомните, все файлы в одном каталоге не имеющие явного выражения package, принадлежат пакету по умолчанию для этого каталога.) Однако, однако, если статический член этого класса - публичный, то клиентский программист сможет получить доступ к этому статическому члену, даже если он не сможет создать объект этого класса.


    Содержание раздела