51

51


Заметьте, что класс нельзя объявить как private (что сделает класс недоступ­ным для окружающих, использовать он сможет только «сам себя») или protected
[2]
. Поэтому у вас есть лишь такой выбор при задании доступа к классу: в пределах пакета или открытый (public). Если вы хотите перекрыть доступ к классу для всех, объявите все его конструкторы со спецификатором private, соответственно, запретив кому бы то ни было создание объектов этого класса. Только вы сами, в статическом методе своего класса, сможете создавать такие объекты. Пример:

//. access/Lunch.java // Спецификаторы доступа для классов. // Использование конструкторов, объявленных private, // делает класс недоступным при создании объектов.

class Soupl {

private SouplО {}

// (1) Разрешаем создание объектов в статическом методе: public static Soupl makeSoupO { return new SouplO;

}

}

class Soup2 {

private Soup2() {}

// (2) Создаем один статический объект и // по требованию возвращаем ссылку на него, private static Soup2 psl = new Soup2(): public static Soup2 accessO { return psl:

}

public void f() {}

}

// В файле может быть определен только один public-класс: public class Lunch {

void testPrivateO {

// Запрещено, т.к конструктор объявлен приватным: //! Soupl soup = new SouplO:

}

void testStaticO {

Soupl soup = Soupl.makeSoupO;

}

void testSingletonO {

Soup2.access О f();

}

)

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

public static Soupl makeSoupO { return new SouplO:

} на первый взгляд смотрится немного странно. Слово Soupl перед именем мето­да (makeSbup) показывает, что возвращается методом. В предшествующих при­мерах обычно использовалось обозначение void, которое подразумевает, что ме­тод не имеет возвращаемого значения. Однако метод также может возвращать ссылку на объект; в данном случае возвращается ссылка на объект класса Soupl.

Классы Soupl H'Soup2 наглядно показывают, как предотвратить прямое соз­дание объектов класса, объявив все его конструкторы со спецификатором pri­vate. Помните, что без явного определения хотя бы одного конструктора компи­лятор сгенерирует конструктор по умолчанию (конструктор без аргументов). Определяя конструктор по умолчанию в программе, вы запрещаете его автома­тическое создание. Если конструктор объявлен со спецификатором private, ни­кто не сможет создавать объекты данного класса. Но как же тогда использовать этот класс? Рассмотренный пример демонстрирует два способа. В классе Soupl определяется статический метод, который создает новый объект Soupl и возвра­щает ссылку на него. Это бывает полезно в ситуациях, где вам необходимо про­вести некоторые операции над объектом перед возвратом ссылки на него, или при подсчете общего количества созданных объектов Soupl (например, для ог­раничения их максимального количества).

В классе Soup2 использован другой подход — в программе всегда создается не более одного объекта этого класса. Объект Soup2 создается как статическая приватная переменная, пэтому он всегда существует только в одном экземпляре и его невозможно получить без вызова открытого метода access().

Резюме

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

Если программисты-клиенты предоставлены сами себе и не ограничены ни­какими правилами, они могут делать все, что им заблагорассудится, с любыми членами класса — даже теми, доступ к которым вам хотелось бы ограничить. Все детали реализации класса открыты для окружающего мира.

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

По оценкам проекты на языке С начинают «рассыпаться» примерно тогда, когда код достигает объема от 50 до 100 Кбайт, так как С имеет единое «про­странство имен»; в системе возникают конфликты имен, создающие массу не­удобств. В Java ключевое слово package, схема именования пакетов и ключевое слово import обеспечивают полный контроль над именами, так что конфликта имен можно легко избежать.

Существует две причины для ограничения доступа к членам класса. Пер­вая — предотвращение использования клиентами внутренней реализации класса, не входящей во внешний интерфейс. Объявление полей и методов со специфи­катором private только помогает пользователям класса, так как они сразу видят, какие члены класса для них важны, а какие можно игнорировать. Все это упро­щает понимание и использование класса.

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

Открытый интерфейс класса — это то, что фактическивидитего пользова­тель, поэтому очень важно «довести до ума» именно эту, самую важную, часть класса в процессе анализа и разработки. И даже при этом у вас остается относи­тельная свобода действий. Даже если идеальный интерфейс не удалось постро­ить с первого раза, вы можетедобавитьв него новые методы — без удаления уже существующих методов, которые могут использоваться программистами- клиентами.

[1]
Использовать Java-интерпретатор не обязательно. Существует несколько компиляторов, создаю­щих единый исполняемый файл.

[2]
На самом деле доступ private или protected могут иметьвнутренние классы,но это особый случай (см. главу 8).



Повторное использование классов

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

Report Page