Да си припомним: какво са класовете и обектите?


Ако два класа не са видими един за друг, то елементите им (полета и методи) не са видими също, независимо с какви нива на достъп са декларирани самите те



страница19/84
Дата03.01.2022
Размер0.54 Mb.
#112941
ТипПрограма
1   ...   15   16   17   18   19   20   21   22   ...   84
Класове
Свързани:
Изпитна тема1, Изпитна тема2
Ако два класа не са видими един за друг, то елементите им (полета и методи) не са видими също, независимо с какви нива на достъп са декларирани самите те.

В следващите подсекции, към обясненията, ще разглеждаме примери, в които имаме два класа (Dog и Kid), които са видими един за друг, т.е. все­ки един от класовете може да създава обекти от тип – другия клас и да до­стъп­ва еле­мен­тите му в зависимост от нивото на достъп, с което са декларирани. Ето как изглежда първия клас Dog:

public class Dog

{

private string name = "Sharo";



 

public string Name

{

get { return this.name; }



}

 

public void Bark()



{

Console.WriteLine("wow-wow");

}

 

public void DoSth()



{

this.Bark();

}

}


В освен полета и методи се използва и свойство Name, което просто връща полето name. Ще разгледаме свойствата след малко, така че за момента се фокусирайте върху останалото.

Кодът на класа Kid има следния вид:



public class Kid

{

public void CallTheDog(Dog dog)



{

Console.WriteLine("Come, " + dog.Name);

}

 

public void WagTheDog(Dog dog)



{

dog.Bark();

}

}


В момента, всички елементи (полета и методи) на двата класа са деклари­рани с модификатор за достъп public, но при обяснението на различните нива на достъп, ще го променяме съответно. Това, което ще ни интере­сува, е как промяната в нивото на достъп на елемен­тите (полета и методи) на класа Dog и ще рефлектира върху достъпа до тези елементи, когато този достъп се извършва от:

-     Самото тяло на класа Dog.

-     Тялото на класа Kid, съответно вземайки предвид дали Kid е в пространството от имена (или асембли), в което се намира класа Dog или не.

Ниво на достъп public

Когато метод или променлива на класа са декларирани с модификатор за достъп public, те могат да бъдат достъпвани от други класове, независи­мо дали другите класове са декларирани в същото пространство от имена, в същото асембли или извън него.

Нека разгледаме двата типа достъп до член на класа, които се срещат в нашите класове Dog и Kid:





Достъп до член на класа осъществен в самата деклара­ция на класа.



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

Когато членовете на двата класа са public, се получава следното:

Dog.cs

 

 

 



 

 

 

 

 



 

 

 



 



class Dog

{

public string name = "Sharo";



 

public string Name

{

get { return this.name; }



}

 

public void Bark()



{

Console.WriteLine("wow-wow");

}

 

public void DoSth()



{

this.Bark();

}

}


 

Kid.cs

 

 

 



 

 





class Kid

{

public void CallTheDog(Dog dog)



{

Console.WriteLine("Come, " + dog.name);

}

 

public void WagTheDog(Dog dog)



{

dog.Bark();

}

}


Както виждаме, без проблем осъществяваме, достъп до полето name и до метода Bark() в класа Dog от тялото на самия клас. Независи­мо дали класът Kid е в пространството от имена на класа Dog, можем от тялото му, да до­стъ­пим полето name и съответно да извикаме метода Bark() чрез операто­ра точка, прило­жен към референцията dog към обект от тип Dog.

Ниво на достъп internal

Когато член на някой клас бъде деклариран с ниво на достъп internal, тогава този елемент на класа може да бъде достъпван от всеки клас в същото асембли (т.е. в същия проект във Visual Studio), но не и от класо­вете извън него (т.е. от друг проект във Visual Studio):

Dog.cs

 

 

 



 

 

 

 

 



 

 

 



 



class Dog

{

internal string name = "Sharo";



 

public string Name

{

get { return this.name; }



}

 

internal void Bark()



{

Console.WriteLine("wow-wow");

}

 

public void DoSth()



{

this.Bark();

}

}


Съответно, за класа Kid, разглеждаме двата случая:

-     Когато е в същото асембли, достъпът до елементите на класа Dog, ще бъде позволен, независимо дали двата класа са в едно и също пространство от имена или в различни:



Kid.cs

 

 

 



 

 





class Kid

{

public void CallTheDog(Dog dog)



{

Console.WriteLine("Come, " + dog.name);

}

 

public void WagTheDog(Dog dog)



{

dog.Bark();

}

}


-     Когато класът Kid е външен за асемблито, в което е деклариран класът Dog, тогава достъпът до полето name и метода Bark() ще е невъзмо­жен:

Kid.cs

 

 

 



 

 





class Kid

{

public void CallTheDog(Dog dog)

{

Console.WriteLine("Come, " + dog.name);



}

 

public void WagTheDog(Dog dog)

{

dog.Bark();



}

}


Всъщност достъпът до internal членовете на класа Dog е невъзможен по две причини: недостатъчна видимост на класа и недостатъчна видимост на членовете му. За да се позволи достъп от друго асембли до класа Dog, той, е необходимо той да е деклариран като public и едновременно с това въпросните му членове да са декларирани като public. Ако или класът или членовете му имат по-ниска видимост, достъпът до тях е невъзможен от други асемблита (други Visual Studio проекти).

Ако се опитаме да компилираме класа Kid, когато е външен за асемблито, в което се намира класа Dog, ще получим грешки при компилация.

Ниво на достъп private

Нивото на достъп, което налага най-много ограничения е private. Еле­ментите на класа, които са декларирани с модификатор за достъп private (или са декларирани без модификатор за достъп, защото тогава private се подразбира), не могат да бъдат достъпвани от никой друг клас, освен от класа, в който са декларирани.

Следователно, ако декларираме полето name и метода Bark() на класа Dog, с модификатори private, няма проблем да ги достъпваме вътрешно от самия клас Dog, но достъп от други класове не е позволен, дори ако са от същото асембли:

Dog.cs

 

 

 



 

 

 

 

 



 

 

 



 



class Dog

{

private string name = "Sharo";



 

public string Name

{

get { return this.name; }



}

 

private void Bark()



{

Console.WriteLine("wow-wow");

}

 

public void DoSth()



{

this.Bark();

}

}


 

Kid.cs

 

 

 



 

 





class Kid

{

public void CallTheDog(Dog dog)

{

Console.WriteLine("Come, " + dog.name);



}

 

public void WagTheDog(Dog dog)

{

dog.Bark();



}

}


Трябва да знаем, че когато задаваме модификатор за достъп за дадено поле, той най-често трябва да бъде private, тъй като така даваме въз­можно най-висока защита на достъпа до стойността на полето. Съответно, достъпът и модификацията на тази стойност от други класове (ако са необходими) ще се осъществяват единствено чрез свойства или методи. Повече за тази техника ще научим в секцията "Капсулация" на главата "Принципи на обектно-ориенти­раното програмиране".

Как се определя нивото на достъп на елементите на класа?

Преди да приключим със секцията за видимостта на елементите на един клас, нека направим един експеримент. Нека в класа Dog полето name и метода Bark() са декларирани с модификатор за достъп private. Нека съ­що така, декларираме метод Main(), със следното съдържание:

public class Dog

{

private string name = "Sharo";



 

// ...


 

private void Bark()

{

Console.WriteLine("wow-wow");



}

 

// ...



 

public static void Main()

{

Dog myDog = new Dog();



Console.WriteLine("My dog's name is " + myDog.name);

myDog.Bark();

}

}


Въпросът, който стои пред нас е, ще се компилира ли класът Dog, при положение, че сме декларирали елементите на класа с модификатор за достъп private, а в същото време ги извикваме с точкова нотация, приложена към променливата myDog, в метода Main()?

Стартираме компилацията и тя минава успешно. Съответно, резултатът от изпълнението на метода Main(), който деклари­рах­ме в класа Dog ще бъде следният:



My dog’s name is Sharo

Wow-wow


Всичко се компилира и работи, тъй като мо­ди­фи­ка­торите за достъп до елементите на класа се прилагат на ниво клас, а не на ниво обекти. Тъй като променливата myDog е дефинирана в тялото на класа Dog (където е разположен и Main() метода на програ­мата), можем да достъпваме елементите му (полета и мето­ди) чрез точкова нотация, независимо че са декларирани с ниво на дос­тъп private. Ако обаче се опитаме да направим същото от тялото на класа Kid, това няма да е възможно, тъй като достъпът до private полетата от външен клас не е разрешено.

Конструктори

В обектно-ориентираното програмиране, когато създаваме обект от даден клас, е необходимо да извикаме елемент от класа, наречен конструктор.

Какво е конструктор?

Конструктор на даден клас, наричаме псевдометод, който няма тип на връщана стойност, носи името на класа и който се извиква чрез ключо­вата дума new. Задачата на конструктора е да инициализира заделената за обекта памет, в която ще се съхраня­ват неговите полетата (тези, които не са static).

Извикване на конструктор

Единственият начин да извикаме един конструктор в C# е чрез ключовата дума new. Тя заделя памет за новия обект (в стека или в хийпа според това дали обектът е стойностен или референтен тип), занулява полетата му, извиква конструктора му (или веригата конструктори, образувана при наследяване) и накрая връща референция към новозаделения обект.

Нека разгледаме един пример, от който ще стане ясно как работи кон­структорът. От главата "Създаване и използване на обекти", знаем как се създава обект:



Dog myDog = new Dog();

В случая, чрез ключовата дума new, извикваме конструктора на класа Dog, при което се заделя паметта необходима за новосъздадения обект от тип Dog. Когато става дума за класове, те се заделят в динамичната памет (хийпа). Нека проследим как протича този процес стъпка по стъпка. Първо се заделя памет за обекта:

След това се инициализират полетата му (ако има такива) с подразбира­щи­те се стойнос­ти за съответните им типове:



Ако създаването на новия обект е завършило успешно, конструкторът връща референция към него, която се присвоява на променливата myDog, от тип класа Dog:



Деклариране на конструктор

Ако имаме класа Dog, ето как би изглеждал неговия най-опростен кон­струк­тор:

public Dog()

{

}



Формално, декларацията на конструктора изглежда по следния начин:



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




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

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