Книга е още в много ранна фаза на написване


Спецификатори на достъпа в Java



страница29/73
Дата25.07.2016
Размер13.53 Mb.
#6732
1   ...   25   26   27   28   29   30   31   32   ...   73

Спецификатори на достъпа в Java


Спецификаторите на достъпа в Java public, protected и private се слагат пред вся­ка дефиниция на всеки член в класовете, бил той член-данни или метод. Все­ки спецификатор управлява достъпа до само тази конкретна дефиниция. Това е зна­чителен контраст спрямо C++, където спецификаторът на достъпа управлява всич­ки следващи дефиниции докато не се появи нов спецификатор на достъпа.

По един или друг начин за всяко нещо е определен вид достъп. В следващите сек­ции ще научите всичко за достъпа, започвайки с този по подразбиране.


“Приятелски”


Какво става ако въобще не дадете спецификатор на достъпа както във всичките при­мери досега от тази глава? Достъпът по подразбиране няма ключова дума но често се споменава като “приятелски.” Това значи че всички други класове от пакета имат достъп до приятелския член, но всички класове извън пакета ня­мат достъп. Тъй като компилационната единица – файл – може да принадлежи са­мо на един пакет, всичките класове в компилационна единица са автоматично прия­телски един на друг. Така приятелските елементи още казваме че имат па­кетен достъп.

Приятелският достъп позволява да се групират класовете в пакет така че да имат възможност лесно да си взаимодействат. Като сложите класове заедно в па­кет (давайки с това изключителен достъп до техните приятелски членове; т.е. пра­вейки ги “приятели”) вие “владеете” кода в пакета. Има смисъл само кода кой­то владеете да има достъп до код който вие владеете. Би могло да се каже, че приятелският достъп дава обяснение или причина за групиране на класовете във файлове. В много езици начинът на организиране на файловете е щеш-не­щеш, но в Java сте задължени да го направите по смислен признак. В добавка вие вероятно бихте предпочели да изключите (от файла - бел.пр.) класа който не трябва да има достъп до класовете във файла.

Важен въпрос във всяка зависимост е “Кой има достъп до моята private реа­ли­за­ция?” Класът контролира кой код има достъп до неговите членове. Няма ма­ги­чески начин да се “пробие;” някой в друг клас не може да дефинира нов клас и да каже, “Ей, аз съм приятелски на класа на Bob!” и да очаква да види protected, приятелски, и private членове на Bob. Единствения начин да се даде до­стъп до член е да:


  1. Се направи члена public. Тогава всеки и навсякъде има достъп до него.

  2. Се направи члена приятелски, като се остави без спецификатор на достъпа и да се сложат другите класове в същия пакет. Тогава другите класове имат достъп до члена.

  3. Както ще видите в по-късна глава където се въвежда наследяването, на­след­никът има достъп до protected член а също и до public член (но не private членове). Той има достъп до приятелските членове само ако двата кла­са са в един пакет. Но не се занимавайте с това сега.

  4. Се даде “accessor/mutator” методи (известни още като “get/set” методи) кои­то четат/променят стойността. Това е най-цивилизованият подход в тер­ми­ните на ООП и той е основен за Java Beans, както ще видите в глава 13.

public: интерфейсен достъп


Като се използва ключовата дума public това значи, че членът който не­по­сред­стве­но я следва е достъпен за всеки, в частност за клиент-програвиста, който из­ползва библиотеката. Нека дефинираме пакет dessert съдържащ следната ком­пилационна единица: (Виж страница 89 ако има проблеми с пускането на про­грамата.)

//: c05:dessert:Cookie.java

// Creates a library

package c05.dessert;


public class Cookie {

public Cookie() {

System.out.println("Cookie constructor");

}

void foo() { System.out.println("foo"); }



} ///:~

Помнете, Cookie.java трябва да е в поддиректория с име dessert, в директория под C05 (индициращо глава 5 на тази книга) която трябва да е под една от CLASSPATH директориите. Не правете грешката да мислите, че Java винаги ще гле­да на текущата директория като на една от началните точки на търсенето. Ако няма ‘.’ Като един от пътищата във въшия CLASSPATH Java няма да търси там.

Ако сега създадем програма която използва Cookie:

//: c05:Dinner.java

// Uses the library

import c05.dessert.*;


public class Dinner {

public Dinner() {

System.out.println("Dinner constructor");

}

public static void main(String[] args) {



Cookie x = new Cookie();

//! x.foo(); // Can't access

}

} ///:~


Може да създадете Cookie обект, тъй като конструкторът му е public и класът е public. (По-късно ще разгледаме публичните класове още.) Обаче foo( ) членът е недостъпен вътре в Dinner.java понеже foo( ) е приятелски само в пакета dessert.

Пакетът по подразбиране


Може да сте изненадани че следният код се компилира, макар че сякаш нару­ша­ва правилата:

//: c05:Cake.java

// Accesses a class in a separate
// compilation unit.
class Cake {

public static void main(String[] args) {

Pie x = new Pie();

x.f();


}

} ///:~


Във втория файл, в същата директория:

//: c05:Pie.java

// The other class
class Pie {

void f() { System.out.println("Pie.f()"); }

} ///:~

На пръв поглед може да ви се сторят напълно чужди файлове и все пак Cake може да създаде Pie обект и да извика неговия f( ) метод! Типично се очаква че Pie и f( ) са приятелски и затова недостъпни за Cake. Те са приятелски – тази част е точна. Причината да са достъпни в Cake.java че са в една директория и ня­мат явно пакетно име. Java третира файлове като тези неявно като от “пакет по подразбиране” за нея директория, следователно като приятелски на всички фай­лове в нея директория.


private: не може да пипате това!


Ключовата дума private означава, че никой няма право на достъп освен кон­крет­ния клас, вътре в методите на класа. Други класове в пакета нямат достъп до private членовете, каточели класът е изолиран и от самия себе си. От друга стра­на, не е невероятно класът да е създаден от няколко души работещи заедно, та­ка че private позволява членът да се променя без да се засягат други класове в пакета. Подразбиращия се “приятелски” достъп в пакета е често достатъчна степен на скриване; запомнете, “приятелски” член е недостъпен за потребител на пакета. Това е добре, той като нормално се използва достъпът по под­раз­би­ра­не. Така типично членовете, които ще са достъпни за клиента-програмист ще са public и като резултат първоначално може да считате че няма много да из­полз­вате private тъй като сносно може да се разминете без тази ключова дума. (Това е значителен контраст със C++.) Оказва се обаче че смисленото из­полз­ва­не на private е много важно, специално когато се прави многонишковост. (Как­то ще видите в глава 14.)

Ето пример за използване на private:

//: c05:IceCream.java

// Demonstrates "private" keyword


class Sundae {

private Sundae() {}

static Sundae makeASundae() {

return new Sundae();

}

}
public class IceCream {



public static void main(String[] args) {

//! Sundae x = new Sundae();

Sundae x = Sundae.makeASundae();

}

} ///:~



Това е пример където private се оказва удобно: бихте могли да искате да управ­ля­вате създаването на обект и да не допуснете някой да използва даден кон­струк­тор (или всичките). В примера по-горе не може да се създаде Sundae обект чрез неговия конструктор; трябва да се извика вместо това makeASundae( ) за да го създаде.3

Всеки метод за който сте сигурни че е спомагателен в класа може да бъде на­пра­вен private за да се осигури неупотребата му на друго място в класа и по този начин да се остави възможност за замяната му. Правенето на метода private това. (Обаче това че манипулаторът е private не значи, че други обекти не могат да имат public манипулатор към същия обект. Виж глава 12 за въ­про­си­те на алиасинга (псевдонимите).)


protected: “вид приятелски”


Спецификаторът на достъп protected изисква скок напред за да бъде разбран. Първо, ще бъдете предупредени, че разбирането на въпроса не е наложително до­като не разберете наследяването. Но за пълнота тук има кратко описание и при­мери с protected.

Ключовата дума protected се преплита с концепцията за наследяване, която взе­ма съществуващ клас и добавя членове без да се пипа съществуващия клас, кой­то ще наричаме базов клас. Може също да се промени поведението на съ­ще­ству­ващ член на клас. За да наследите от съществуващ клас казвате че новият extends (разширява - бел.пр.) съществуващ клас, както тук:

class Foo extends Bar {

Останалата част от дефиницията на класа изглежда по същия начин.

Ако създавате нов пакет и наследявате от друг пакет, единствените членове до които имате достъп са public членовете на оригиналния пакет. (Разбира се, ако на­следявате в същия пакет ще имате нормалния пакетен достъп до всички “приятелски” членове.) Понякога създателят на клас иска да вземе отделни чле­но­ве и да даде достъп до тях само на наслидниците на класа, а не на целия свят. Това е, което прави protected. Ако погледнете пак Cookie.java на стр. 192, след­ва­щият клас няма достъп до “приятелския” член:

//: c05:ChocolateChip.java

// Can't access friendly member

// in another class

import c05.dessert.*;
public class ChocolateChip extends Cookie {

public ChocolateChip() {

System.out.println(

"ChocolateChip constructor");

}

public static void main(String[] args) {



ChocolateChip x = new ChocolateChip();

//! x.foo(); // Can't access foo

}

} ///:~


Едно от интересните неща за наследяването е че ако методът foo( ) съществува в клас Cookie, той също съществува и във всеки клас, наследен от Cookie. Но до­колкото foo( ) е “приятелски” във външен пакет, той е недостъпен за нас в то­зи. Разбира се, бихте могли да го направите public, но тогава всеки би имал до­стъп и това може да не е което искате. Ако променим класа Cookie така:

public class Cookie {

public Cookie() {

System.out.println("Cookie constructor");

}

protected void foo() {



System.out.println("foo");

}

}



тогава foo( ) още има “приятелски” достъп в пакета dessert, но също е достъпен за всеки, който наследява от Cookie. Обаче не е public.




Сподели с приятели:
1   ...   25   26   27   28   29   30   31   32   ...   73




©obuch.info 2024
отнасят до администрацията

    Начална страница