С компютърните програми, по същество, създаваме компютърни модели на реални обекти и явления от действителността, на абстрактни обекти, с които си служат различните науки и др. Абстрактните обекти от областта на науката, от своя страна, също се използват за моделиране на реални обекти, така че от програмистка гледна точка е все едно дали явленията са абстрактни или реални.
Както е обяснено в учебника(стр. 54) при създаването на компютърен обект е важно да изберем характеристиките, които са важни за нашето конкретно приложение. Примерно ако моделираме обекти от тип "Кола" е важно в какъв контекст ще използваме тези обекти, да речем ако е е кола в компютърна игра може да ни е необходимо да пазим само координатите на колата в рамките на игралното поле, ако е кола в магазин за продажба на коли ще трябва да пазим цена, кубатура на двигател и т.н. Ако при проектирането обектът започне да става прекалено голям и сложен е добре да обмислим начин да обособим подходящи подобекти, за да намалим сложността. Като златно правило е добре да се стремим нашите обекти да бъдат винаги колкото се може по-прости, изчистени, само с наистина необходими характеристики/атрибути.
Като цяло е обяснено доста добре в ученика(стр.54-55). Може да се добави, че класът представлява един шаблон или калъп, който съдържа структурно описание на данните/атрибутите, както функционално описание с методите, които изпълняват функцията на обектите. Всеки обект представител от този клас се "излива" по този калъп. Можем да мислим за класовете като за нови типове данни, които се добавят към вече съществуващите.
Тъй като в учебника, а също и в други учебни материали се среща термина абстракция ще му обърнем малко внимание. Под абстракция поне аз разбирам отдалечаване от някакво явление обект и разглеждането му в перспектива, което позволява да го видим в по-голяма цялост и да не се концентрираме прекалено в детайлите му. Примерно, когато създаваме нов обект ние се абстрахираме от цялата сложност на обекта и се концентрираме само върху съществените характеристики. Друг пример са езиците за програмиране, машинните езици са най-близо до архитектурата на машината и представляват преки команди, които машината разбира/интерпретира буквално едно към едно, тоест нивото на абстракция е нулево. Малко по-високо ниво на абстракция имат асемблерните езици, където кодовете имат подсказващи имена, но все пак преминаването от асемблерен език към машинен е тривиална задача. При процедурните езици нивото е вече доста по-високо използват се оператори като if, for, while и т.н., което е голямо отдалечаване/абстрахиране от машинните езици, като една програма написана на C да речем може да бъде компилирана и изпълнена на различни архитектури/компютри, докато една програма написана на машинен код може да се изпълни единствено на машината, за която е написана.
Като цяло ми харесва обяснението в учебника(стр. 57). Единствено като съвет мога да добавя, че когато човек научи OOП, може да му се прииска да създава класове във всякакви ситуации, което не е винаги най-удачното. Хубаво е добрият дизайн и оформянето в класове/обекти да се прави най-накрая, когато имаме работещо тествано приложение и вече е ясно каква функционалност/данни трябва да се включат в крайното решение. Това не означава да не добавяте класове, а по-скоро да го правите на етапи, започвайки от по-очевидни прости класове и постепенно усложнявайки класовете/обектите при нужда.
(стр. 58 - 59 - 60 -61)Според мен е добре обяснено, като цяло тук е обяснено как се дефинират класове и как се създават инстанции/екземпляри от съответния клас.
Типовете се разделят на стойностни типове – такива, които пазят данните директно в себе си, т.е. в своята стойност в стека на програмата, и референтни типове – представляват референции, указващи мястото на данните в паметта, т.е. пазят като стойност адрес, област от динамичната памет(Heap), където е записана стойността им. Всички непосредствено дефинирани променливи се съхраняват в стека на програмата(вид памет), макар и да се намират в стека обаче, референтните променливи всъщност сочат към динамичната памет Heap. Размерът при стойностните типове е предварително фиксиран. Обратното е при референтите типове – те могат да се заделят и освобождават динамично. Нулевата референция null, е специален начин да се окаже, че дадена променлива от рефентен тип в момента не сочи към никакви данни, това подлежи на лесна проверка в кода (obj == null). Повече информация относно референтните типове може да намерите тук
Хубаво е обяснено (стр.65 - 66). Може да обърнете по-голямо внимание на предимствата на функциите отбелязани са в списък с кръгчета. Също като дефиниция е добре да знаете какво е сигнатура на метод/функция и да се запознаете с понятието претоварване на имената, както и каква е разликата между формални и фактически параметри.
Обектите или инстанциите на класовете могат да бъдат предавани като аргумент както всеки друг тип. Да разгледаме примерния клас "Car", целта на упражнението е да напишем метод, който изчислява данъка на колата базиран на годината на производство и кубатурата на двигателя + още един метод, който принтира информация за колата. Ще поместим методите GetTax и PrintCarInfo в класа Program във файла Program.cs и ще ги извикаме в същия клас от Main() метода.
//car.cs
class Car
{
public string brand;
public string model;
pubilc int engineVolume;
public int year;
}
//Program.cs
class Program
{
static double GetTax(Car car)
{
double result = 100;
if(car.year < 2010) {result *= 0.5;}
else if(car.year < 2020) {result*= 0.8;}
else result*= 1.2;
if(car.engineVolume < 1400) {result *= 0.5}
else {car.engineVolume *= 1.6;}
return result;
}
static void PrintCarInfo(Car car)
{
System.Console.WriteLine("Brand: " + car.brand);
System.Console.WriteLine("Model: " + car.model);
System.Console.WriteLine("Volume: " + car.engineVolume);
System.Console.WriteLine("Man year: " + car.year);
}
static void Main(string[] args)
{
Car c = new Car();
c.engineVolume= 1399;
c.year = 1997;
double tax = GetTax(c);
PrintCarInfo(c);
System.Console.WriteLine("Tax: " + tax);
}
}
Функциите, дефинирани като част от клас, наричаме член-функции на класа или просто методи. Когато една функция извършва присъща работа за класа е нормално да я направим метод. Нека го направим за функциите GetTax и PrintCarInfo. Когато такива, присъщи за класа функции се оформят като методи, вече не е нужно да предаваме инстанцията на класа, която обработваме като параметър. Вместо това можем да използваме служебната дума this, чрез която имаме достъп до атрибутите на класа. Всъщност this представлява референция към обекта/инстанцията, за която е извикан метода.
//car.cs
class Car
{
public string brand;
public string model;
pubilc int engineVolume;
public int year;
public double GetTax()
{
double result = 100;
if(this.year < 2010) {result *= 0.5;}
else if(this.year < 2020) {result*= 0.8;}
else result*= 1.2;
if(this.engineVolume < 1400) {result *= 0.5}
else {this.engineVolume *= 1.6;}
return result;
}
public void PrintCarInfo()
{
System.Console.WriteLine("Brand: " + this.brand);
System.Console.WriteLine("Model: " + this.model);
System.Console.WriteLine("Volume: " + this.engineVolume);
System.Console.WriteLine("Man year: " + this.year);
}
}
//Program.cs
class Program
{
static void Main(string[] args)
{
Car c = new Car();
c.engineVolume= 1399;
c.year = 1997;
double tax = c.GetTax();
c.PrintCarInfo();
System.Console.WriteLine("Tax: " + tax);
}
}
Жизненият цикъл на обектите включва:
- За обекта се заделя памет и се свързва с неговото име
- Извиква се подходящ конструктор на обекта
- Работа с обекта (достъп до компоненти на обект, изпълняване на операции)
- Обектът излиза от употреба
- Обектът се премахва от динамичната памет
Както се вижда от списъка по-горе конструкторите се използват за инициализация на данните на новосъздадените обекти. Формално погледнато това са функции, със същото име като това на класа, в който принадлежат. Повече информация за конструкторите може да прочетете от учебника(стр.70 - 71).
Конструкторът по подразбиране е този, който не приема входни параметри, в учебника ги наричат стандартни конструктори. Тези конструктори са предоставени автоматично в случай, че не си ги напишете сами. В предишния пример кода :
Car c = new Car();
използва стандартния конструктор, ако няма входни параметри -> Car() това е стандартния конструктор.