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


Никога не се налага да разрушавате обект



страница18/73
Дата25.07.2016
Размер13.53 Mb.
#6732
1   ...   14   15   16   17   18   19   20   21   ...   73

Никога не се налага да разрушавате обект


В повечето програмни езици въпросът за времето на живот на обектите (в ши­ро­кия смисъл на думата - б.пр.) заема голяма част от общото програмистко уси­лие. Колко дълго ще трае дадена променлива? Ако трябва да се разруши, ко­­га да се направи това? Трудностите с времетраенето на променливите до­веж­дат до множество грешки и тази секция показва как Java съществено опростява въ­проса, почиствайки всичко вместо вас.

Обхвати


Повечето процедурни езици имат концепцията за обхват. С нея се определят как­то видимостта, така и времето на живот на променливите (в дадения обхват - б.пр.). В C, C++ и Java обхватът се определя чрез поставяне на големи скоби {}. Така например:

{

int x = 12;



/* само x достъпно */

{

int q = 96;



/* x и q достъпни */

}

/* само x достъпно */



/* q “извън обхвата” */

}

Променлива определена в даден обхват е достъпна само до края на същия об­хват.



Индентацията прави Java кода по-лесен за четене. Тъй като Java is е език със сво­бодна форма, табулациите и краищата на редовете не променят програмата по същество.

Забележете че не може да се прави следното, макар и да би могло в C и C++:

{

int x = 12;



{

int x = 96; /* Неприемливо!! */

}

}

Компилаторът ще каже, че x вече е било дефинирано. Така C и C++ въз­мож­ност­та да се “скрие” променлива в по-голям обхват не е позволено, по­не­же проектантите на Java са считали, че това ще доведе до проблемни про­гра­ми.


Обхват на обекти


Java нямат същото време на живот както примитивите. Като създадете Java обект с new той остава и след края на обхвата. Така при:

{
String s = new String("a string");


} /* край на обхвата */

манипулаторът s изчезва на края на обхвата. String обектът към който сочеше s оба­че още заема памет. В това парче код няма начин вече да се достигне обек­та, понеже манипулаторът му е извън обхвата. В други глави ще научите как мо­же да се управлява обектът през цялата програма.

Това извежда наяве че тъй като обектите създадени с new остават толкова, кол­ко­то ги искате, камарата програмистки проблеми просто изчезва в C++ и Java. Най-тежките проблеми изглежда да възникват в C++ понеже няма никаква помощ от езика да се определи дали обектите са още необходими. И по-важ­но­то, в C++ трябва да осигурите унищожаването на обектите когато сте си свър­ши­ли работата с тях.

Това извиква интересен въпрос. Ако Java оставя обектите неразрушени, кое пред­пазва от препълването на паметта и спирането на програмата? Това е точно про­блемът, който би възникнал в C++ (ько програмистът не се грижи до­ста­тъч­но, вж. предния абзац - б.пр.). Малко магия се случва. Java има боклучар, който гле­да всички обекти създадени с new и определя към кои от тях вече няма обръ­щения от никъде. Тогава освобождава паметта на тези обекти, така че да се използва от други обекти. Това значи, че никога не се грижите за самата памет. Про­сто създавате обекти и когато те не са нужни вече, от само себе си изчезват. Това елиминира определен клас от програмистки проблеми: т.н. “изтичане на па­мет,” където програмистът е забравил да освободи паметта.


Създаване на нови типове данни: class


Ако всичко е обект(и), как да определим поведението и изгледа на даден клас обекти? Другояче казано, как да определим типа на обект? Може би очаквате ключова дума “тип” и тя сигурно би имала смесъл. Исторически обаче повечето ООП езици са използвали думата class за да означат “Ще ви кажа на ка­кво ще прилича новия обект.” Ключовата дума class (която толкова много се из­ползва навсякъде, че даже не е с удебелени букви в книгата) се следва от име­то на новия тип. Например:

class ATypeName { /* тялото на класа ще е тук */ }

Това въвежда нов тип, така че може да създадете обект с new:

ATypeName a = new ATypeName();

В AtypeName тялото на класа е само един коментар (звездите и наклонените чер­ти и това, което е между тях) така че не много може да се направи с него. Фак­тически не можете да му кажете да прави повече от нищо (тоест, не може да му изпратите никакво интересно съобщение) докато не му определите ме­то­ди.

Полета и методи


Когато определяте клас (всичко което правите в Java е определяне на класове, пра­вене на такива обекти и изпращане на съобщения до тях) може да сложите два типа елементи в класа: членове-данни (понякога наричани полета) и чле­но­ве-функции (типично наричани методи). Членъ-данни е обект (с когото ко­му­ни­кирате чрез манипулатора му) от какъвто и да е тип. Може да бъде и някой при­митив (и тогава няма да има манипулатор). Ако е манипулатор на обект, тряб­ва правилно да го инициализирате да сочи към обект, преди да го из­пол­зва­те (с new, както видяхме по-рано)в специална функция наречена конструктор (опи­сана напълно в глава 4). Ако е първичен тип може да го инициализирате на­пра­во в точката на дефинирането му. (Както ще видите по-късно, ма­ни­пу­ла­то­ри­те също могат да се инициализират в точката на определянето им (другояче - де­кла­рацията им, б.пр.).)

Всеки обект има собствена памет за своите членове-данни; Те не се споделят от различните обекти. Ето пример за клас с членове данни:

class DataOnly {

int i;


float f;

boolean b;

}

Този клас не прави нищо, но може да се създаде такъв обект:



DataOnly d = new DataOnly();

Може да се присвояват стойности на членовете-данни, но най-напред трябва да нау­чите как се означава член на обект. Това се прави с точка между името на обек­та и члена (objectHandle.member). Например:

d.i = 47;

d.f = 1.1f;

d.b = false;

Възможно е също обектът да съдържа други обекти, които искате да модифицирате. За целта продължавате с точките. Например:

myPlane.leftTank.capacity = 100;

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


Стойности по подразбиране за примитивни членове


Когато примитивен даннов тип е член на клас гарантира се, че ще получи стой­ност по подразбиране, ако не го инициализирате:

Първичен тип

Подр. стойност

Boolean

false

Char

‘\u0000’ (null)

byte

(byte)0

short

(short)0

int

0

long

0L

float

0.0f

double

0.0d

Внимателно отбележете, че стойностите по подразбиране се гарантират от Java ко­гато променливата се използва като член на клас. Това осигурява членовете-при­митиви да са винаги инициализирани (нещо което C++ не прави), намаляват се източниците на грешки.

Тази гаранция не се отнася за “локалните” променливи – онези, които не са полета в клас. Така е ако имате вътре в дефиниция на функция:

int x;

Тогава x ще приеме каквато се случи стойност (както в C и C++); няма да бъде ав­томатично инициализирана с нула. Вие сте си отговорни за присвояването на под­ходяща стойност на x преди използването му. Ако забравите, Java опре­де­ле­но изпреварва C++: имате грешка при компилация с предупреждение, че про­мен­лива може да не е инициализирана. (Много C++ компилатори биха ви преду­предили за това, но в Java това е грешка, а не предупреждение.)





Сподели с приятели:
1   ...   14   15   16   17   18   19   20   21   ...   73




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

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