Главная страница

Лабораторная работа 1 2 лабораторная работа 2 31 лабораторная работа 3 44 лабораторная работа 4 74


Скачать 1.76 Mb.
НазваниеЛабораторная работа 1 2 лабораторная работа 2 31 лабораторная работа 3 44 лабораторная работа 4 74
Дата12.03.2021
Размер1.76 Mb.
Формат файлаdoc
Имя файлаOOP_Lab_Rus.doc
ТипЛабораторная работа
#184105
страница13 из 31
1   ...   9   10   11   12   13   14   15   16   ...   31

4.12 Управление доступом


Напомним, что инкапсуляция связывает данные с кодом, который манипулирует ими. Однако инкапсуляция обеспечивает другой важный атрибут: управление доступом. Через инкапсуляцию можно управлять доступом различных частей программы к членам класса и предотвращать неправильное использование таких членов. Например, разрешая доступ к данным только через хорошо определенный набор методов, есть возможность предотвращения неверного использования этих данных. Таким образом, при правильной реализации класс создает для использования «черный ящик», но внутренняя работа, которого не доступна для вмешательства. Однако представленные ранее классы не полностью удовлетворяют этой цели. Например, рассмотрим класс stack. Методы push() и pop() обеспечивают управляемый интерфейс к стеку, интерфейс этот не предписан. То есть, другая часть программы может обойти указанные методы и получить прямой доступ к стеку. Конечно, в неумелых руках это может привести к неприятностям. Далее будет представлен механизм, с помощью которого можно точно управлять доступом к различным членам класса.

Способ доступа к элементу определяет спецификатор доступа, который модифицирует его объявление, и Java поставляет их богатый набор. Некоторые аспекты управления доступом относятся главным образом к наследованию или пакетам. Пакет – это, по существу, группировка классов. Данные части механизма управления доступом Java будут обсуждаются позже. Здесь начнем с рассмотрения управления доступом в применении к отдельному классу.

Спецификаторы доступа Java: public (общий), private (частный) и protected (защищенный). Java также определяет уровень доступа, заданный по умолчанию (default access level). Спецификатор protected применяется только при использовании наследования.

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

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

Спецификатор доступа предшествует остальной части описания типа элемента (члена) класса. То есть он должен начинать предложение объявления такого элемента. Например:
public int i;

private double j;
private int myMethod(int a, char b) { //
Чтобы понимать специфику общего и частного доступа, рассмотрим следующую программу:
/* Эта программа демонстрирует различие между

методами доступа public и private.

*/

class Test {

int a; // доступ по умолчанию (public)

public int b; // общий (public) доступ

private int c; // частный (private) доступ

// метода для доступа к переменной c

void setc(int i) { // установить значение c

c = i;

}

int getc() { // получить значение c

return c;

}

}

class AccessTest {

public static void main(String args[]) {

Test ob = new Test();

// OK, к переменным а и b возможен прямой доступ.

ob.a = 10; ob.b = 20;

// Не OK и вызовет ошибку.

// ob.c = 100; //Ошибка!

// Нужен доступ к c через ее методы.

ob.setc(100); //OK

System.out.println("a, b, и c: " + ob.a + " " + ob.b + " " + ob.getc());

}

}
Внутри класса Test используется доступ по умолчанию, который для этого примера эквивалентен указанию public. Член b явно определен как public.

Для члена с задан доступ private. Это означает, что к нему нельзя обращаться из кода, находящегося вне его класса. Так внутри класса AccessTest переменная c не может использоваться прямо. К ней нужно обращаться через ее public-методы setc() и getc(). Если бы вы удалили символ комментария в начале следующей строки, то не смогли бы откомпилировать эту программу из-за нарушения правил доступа:
// ob.с = 100; // Ошибка!
Чтобы увидеть, как управление доступом может применяться в более практическом примере, рассмотрим следующую улучшенную версию класса stack
// Этот класс определяет целый стек, который может содержать 10 значений.

class Stack {

/* Теперь как stck, так и tos есть private. Это значит,

что они не могут быть случайно или намеренно

изменены опасным для стека способом.

*/

private int stck[] = new int[10];

private int tos;

// инициализировать вершину стека

Stack () {

tos = -1;

}

// поместить элемент в стек

void push(int item) {

if (tos==9)

System.out.println("Стек заполнен.");

else

stck[++tos] = item;

}

// вытолкнуть элемент из стека

int pop() {

if (tos < 0) {

System.out.println("Стек пуст.") ;

return 0;

}

else

return stck[tos--];

}

}
Теперь переменная stck, которая содержит стек, и tos, которая является индексом вершины стека, определены как private. Это означает, что к ним нельзя обращаться или изменять их, кроме как через методы push() и pop(). Делая tos частной, мы, например, предохраняем другие части программы от неосторожной установки в ней значения, которое находится вне границ массива stck.

Следующая программа демонстрирует улучшенный класс stack. Тут члены stck и tos недоступны.
class TestStack {

public static void main(String args[]) {

Stack mystack1 = new Stack();

Stack mystack2 = new Stack();
// поместить несколько чисел в стек

for(int i=0; i<10; i++) mystack1.push(i);

for(int i=10; i<20; i++) mystack2.push(i);
// вытолкнуть эти числа из стека

System.out.println("Стек в mystack1:");

for(int i=0; i<10; i++)

System.out.println(mystack1.pop()) ;
System.out.println("Стек в mystack2:");

for(int i=0; i<10; i++)

System.out.println(mystack2.pop()) ;
// эти операторы не верны

// mystackl.tos = -2;

// mystack2.stck[3] = 100;

}

}
Доступ к данным, определенным в классе со спецификатором private, выполняется только через методы этого класса. Но иногда (и по разным причинам) возникает необходимость обойти эти ограничения. Например, с помощью спецификатора общего доступа public можно расширить область действия переменных экземпляра за пределы своего класса и, следовательно, получить возможность работать с ними не только через их собственные методы. В большинстве реальных классов нужно разрешать операции на данных только через собственные методы. Управление доступом особенно важно, когда нужно пользоваться наследованием.
1   ...   9   10   11   12   13   14   15   16   ...   31


написать администратору сайта