Обектно-ориентирано програмиране (част 1)
22-11-2009
Няколко въпроса, чиито отговори трябва да знаете

Какво представлява обектно-ориентираното програмиране ?
Ще кажа само малко за основната идея при ООП - на едно място са събрани обекти - данни или функции, които определят структурата на класа. Всяка функция е метод, който служи да извършването на нещо, а данните - за запазване на информация.

Какви са предимствата на обектно-ориентираното програмиране ?
Предимствата са в това че можем да се абстрахираме от начина на извършване на действията (с по-прости думи не ни трябва да знаем как точно работи даден обект, стига ползвайки го да има подходящ отговор от него). Друго предимство е пакетирането на обектите - всички те са на едно място.

Къде е удобно на ползваме ООП ?
При по-големите проекти като писане на готови системи, изграждане на сайтове с голяма функционалност и друго подобни, ползването на ООП внася голямо убодство - особено когато кода ще бъде редактиран/разглеждан от други хора.

Какво е клас ?
Класа е пакета, в който са пакетирани обектите.

Как се дефинира клас в PHP ?
Със запазената дума class, последвана от името на класа и фигурни скоби, в които е структурата на класа.
Ето пример, в който създаваме клас с променлива в него:
class MyClass {
public $MyVar;
}

Как се ползва клас ?
В PHP има запазена дума new с която можем да дефинираме инстанция на класа. Инстанцията е променлива, която има свойствата на класа.
Първо трябва да си създадем клас - за целта ще ползвам класа от предния пример
Нека сега видим как се ползва:
$p = new MyClass;
$p->MyVar = "някаква стойност";
echo $p->MyVar;

Нека и да обясним какво правим. $p = new MyClass на този ред създаваме променлива $p, която има свойствата на класа. На втория ред задаваме някаква стойност на обекта на инстанцията. На третия вече извеждаме стойността на обекта.

Достъп до обектите в клас

Достъпа се осъществява по следния начин
$име_на_инстанцията->име_на_обекта;
Като ако викаме обект в тялото на самия клас, има псевдо инстанция с името this - както се вижда в примера малко по-горе $this->MyVar++; осъществява достъп до MyVar, чрез инстанцията this.
Всеки обект има ниво на достъп, което се определя от една от трите запазени думи: public, private, protected.
Ако даден обект е public, той може да бъде достъпен от всякъде.
Ако е private, той е достъпен само в тялото на класа, в който е дефиниран.
Третия вид - protected - е достъпен в тялото на класа, в който е дефиниран, и в дъщерните - за дъщерните можете да прочетете след примерите.
Ако ползваме var за дефиниране на променлива в клас, то тя ще е public.
Дефинирането на функция само с function също ще я направи public.

Ето и пример:
<?php
class MyClass { //дефинираме първия клас
public $publ = 'Public'; //дефинираме променлива $publ от тип public - т.е. достъпна отвсякъде
protected $prot = 'Protected'; //тази променлива е достъпна само от тялото на този клас и на дъщерните
private $priv = 'Private'; //тази е достъпна само от тялото на този клас
function printHello() { //функция с която ще извеждаме стойностите на променливите
echo $this->publ; //извеждаме
echo $this->prot; //..
echo $this->priv; //..
}
}
$obj = new MyClass(); //дефинираме инстанция на първия клас
echo $obj->publ; // Работи
echo $obj->prot; // Fatal Error
echo $obj->priv; // Fatal Error
$obj->printHello(); // Извежда Public, Protected и Private
class MyClass2 extends MyClass { //дефинираме втория клас който е дъщерен на първия
protected $prot = 'Protected2'; //променяме стойността на $prot - можем да го направим защото тя е достъпна и в дъщерния клас
}
$obj2 = new MyClass2(); //дефинираме инстанция на втория клас
echo $obj2->public; // Работи
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Извежда Public, Protected2, Undefined
?>



Наследяване
Вероятно повечето са чували за наследяване, но дори и да не сте от тях няма значение.
Наследяването се осъществява между два класа - единият е родителски, другият - дъщерен. Дъщерния наследява всички обекти без един специален вид, който ще споменем надолу. Един клас може да има само един родител, но много дъщерни. Осъществява се със запазената дума extends по този начин class MyClass2 extends MyClass - като по този начин MyClass2 е дъщерен, а MyClass родителски.

Защо е измислено наследяването ?
Представете си че сте в следната ситуация: трябва на направите класове за следните животни: тигър, домашна котка и гъзела. Всички животни имат потребности - да се хранят, но те се хранят с различна храна. Всички бягат - но с различна скорост. Всички имат начин на хранене - но различен. Би ли било удобно за всяко да пишете по-отделно всяка една подробност ? - Не. Какъв трябва да е начина, по който да ги напишете 1 път, но те да имат различни стойности ? Всички имат размери, възръст, килограми...Не би ли било удобно да ги пакетирате всичките тези неща, и после да използвате по 1 пакет за всеки животно ? Как може да стане това ? С наследяване.
Пишете 1 клас, който се казва Animal например и както всяко животно има някакви характеристики - размер, тегло, възръст - това са ви променливите. Всяко от тях се храни - първо обаче трябва да си улови храната, но тази храна може да я даде на малките си например. Значи ви трябва една функция, за улавяне на храната и друга за хранене. Функцията на хранене би била една и съща и при трите животни нали ? - Просто яде. Но всяко от тях улавя/намира храната си по-различен начин. И този различен начин е единственото, което трябва да промените, за да се получат класовете за животните, от началния клас.
Ключова дума final - забранява предефинирането на обекти.
Предефиниране на обект - когато един обект бъде наследен и той е public или protected - т.е. има достъп до тях, можем да ги предефинираме - ако е променлива - да променим стойността, ако е функция - да променим ядрото и.
Когато обекта е private, той изобщо не се наследява. Т.е. можем без никакъв проблем да си създадем нов обект със същото име.

Такъв код би изглеждал по горе долу такъв начин:

class Animal {
protected $weight, $high, $age;
function feed() {
//функция за хранене
}
function find_food() {
//функция за намиране на храна
}
function run() {
//функция за бягство при нападение от враг
}
}
class Tiger extends Animal {
//тук може да предефинирате обекти, които не са final
}
class Cat extends Animal {
//предефинираме обектите по начина по който трябва да се изпълняват за домашната котка
}
class Gazele extends Animal {
//предефинираме обектите по начина по който искаме да са за гъзелата
}


Следва втора част
Урока е авторски и е писан специално за web-tourist.net










/ Трябва да сте регистриран за да напишете коментар /
От: admin
1:02 27-11-2009
Урока го одобрявам защото виждам, че си вложил труд и имаш желание.
Урок за ООП се пише по трудно. По трудно е за обяснение.
Останалите ще кажат дали са разбрали нещо от това, което си написал и ако се наложи урока ще се редактира.
От: adrian
10:58 27-11-2009
Браво за труда!
Наистина е трудно да се обясни ООП, ако не смятах така щях аз да съм се хванал да пиша уроци за това. Трудно е да решиш откъде да почнеш и къде да свършиш с обясненията. Също така е трудно да се обясни на разбираем език ООП (най-доброто обяснение за ООП намерих в книга за JAVA и това е разбираемо, но нещата са същите г-д и във всеки ООП език).

Имам няколко забележки по урока:
1. Ще кажа само малко за основната идея при ООП - [b]на едно място са събрани обекти[/b] - данни или функции, които определят структурата на класа. Всяка функция е метод, който служи да извършването на нещо, а данните - за запазване на информация.

По-скоро данните и функциите са събрани на едно място, познато като обект. Като данните са свойствата на даден обект, а функциите са методите му за взаимодействие. Обектите са инстанции, създадени от даден клас. Данните и функциите не са обекти, а са един вид членове на обектите.

2. Друго предимство е пакетирането на обектите - всички те са на едно място.

Като цяло това изречение няма реален смисъл, защото PHP не поддържа пакетиране и пакети в PHP не съществуват. Може би си искал да кажеш, че класът КАПСУЛИРА данните и кодът в едно цяло.

3. Класът е пакета, в който са пакетирани обектите.

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

4. В PHP има запазена дума new с която можем да дефинираме инстанция на класа. Инстанцията е променлива, която има свойствата на класа.
Първо трябва да си създадем клас - за целта ще ползвам класа от предния пример

new не дефинира инстанция, а създава инстанция на дадения клас. При извикването на new се заделя памет за нов обект, като всеки обект използва собствени копия на свойствата и методите. Тук също може да се спомене за конструкторите, защото new след като задели памет вика конструктора на класа (ако има такъв).
Също така една съществена разлика между PHP 5 и PHP 4 се крие именно тук. В PHP 5 като създаваме обект с ключовата дума new се връща манипулатор на обекта (идентификатор), а в PHP 4 връщаната стойност е самият обект.

5. Нека и да обясним какво правим. $p = new MyClass на този ред създаваме променлива $p, която има свойствата на класа. На втория ред задаваме някаква стойност на обекта на инстанцията. На третия вече извеждаме стойността на обекта.

На първия ред от примера ти се създава инстанция на класа, като на $p се присвоява манипулатор на обекта, който наистина съдържа свойствата и методите на класа. На втория ред даваме стойност на една от променливите на обекта. На третия се изкарва стойността на променливата, а не на обекта.

6. $име_на_инстанцията->име_на_обекта;
не име_на_обекта, а име_на_свойство или метод.

7. Като ако викаме обект в тялото на самия клас, има псевдо инстанция с името this - както се вижда в примера малко по-горе $this->MyVar++; осъществява достъп до MyVar, чрез инстанцията this.

this не е псевдо инстанция, каквото и да значи това, а е променлива, която съдържа референция към самия обект. Чрез нея могат да се извършват референции към методите и свойствата на даден обект.
Би ми се искало да дам хубав пример за това, но просто не мога в момента да измисля такъв.

8. Ако ползваме var за дефиниране на променлива в клас, то тя ще е public.
Не е хубаво да се споменава за var, защото var стои в PHP 5 единствено, за да се запази по някакъв начин приемствеността с PHP 4

9. $obj = new MyClass(); //дефинираме инстанция на първия клас

както казах създаваме инстанция, а не я дефинираме

protected $prot = 'Protected2'; //променяме стойността на $prot - можем да го направим защото тя е достъпна и в дъщерния клас

Не си спомням много добре, а ме мързи да погледна, но мисля, че дъщерния клас трябва да запазва модификатора (protected) на родителския. Т.е ако в дъщерния клас се пропусне protected, променливата $prot от родителския няма да бъде предефинирана. Както казах, за това не съм много сигурен, че беше така.

10. Вероятно повечето са чували за наследяване, но дори и да не сте от тях няма значение.

Как да няма значение наследяването? В основата на полиморфизма седи наследяването. А полиморфизма е може би една от най-важните теми в ООП.

Примерът, който си дал за наследяването е хубав и в повечето книги използват подобни примери. Единствената забележка по него е, че пак си се омешал с понятията обект, пакетиране и т.н :)

Ами това е от мен. Надявам се в другите части на урока да бъде споменато за абстрактни методи и класове, също така за интерфейсите, static свойствата и методите и клонирането на обекти с clone.
От: emagi
12:02 27-11-2009
Аз така и не видях в хилядите редове, какъв е смисъла да програмираш по този начин.Изписаха се хиляди редове, но така или иначе, ако някой го запитам:"Аджеба, за кво го правиш така", на дали ще ми отговори.Преди 2 дена ми беше предоставен урока , и набързо хвърлих един поглед, и видях че е обяснена структурата, но не и същността.Затова много потребители пишат класове, но защо, самите те не знаят.Никъде не видях да се спомене за капсулиране, полиморфизъм, наследяване.Първият урок не трябваше да съдържа код, а само примери с това какво е обект.Какво може да претежа обект.Сега имаме урок, в него пише че с new се създава нова инстанция на обект и т.н..Все едно да ти обясня какво има като екстри една кола, но да не знаеш какво може да направиш с тази кола, изобщо не знаеш какво е кола
На ЛС казах и на renegat96, че урока има нужда от глобална промяна.
Това не е упрек, евала за труда, но в крайна сметка трябва да се обясни какво точно представлява ООП, за какво служи, с една дума - за какво ни е
От: galabin123
1:09 26-12-2009
много съм съгласен с @emagi този начин е труден както мисля аз и безмислен
От: KillerSoft
23:32 19-02-2011
Браво за урока. В момента уча ООП и като цяло чета от много места, но все пак информацията тук ми бе от полза.
От: embaka
2:22 09-05-2011
създаване на глобални и вътрешни променливи, чрез който с едно извикване на определен метод от класа се изпълнява всичко, без прекалено писане на ненужен код, защото всичко както беше написано по-горе е капсулирано, става по прегледен кода и работи по бързо поне според мен, но пак зависи как и кой го е написал :))
1