Какво е ООП с примери. За глупаци

(OOP) организира данните и алгоритмите, обработвани от програмата. В този случай програмистът създава форми на данни и алгоритми, които съответстват на основните характеристики на проблема, който се решава. Наричат ​​се модели на данни и алгоритми, които ги обработват класове, А обекти- това са техните специфични представители, използвани в програмата.

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

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

Пример за обектно-ориентирани езици са: Object Pascal , C++, Java.

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

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

Предмете комбинация от данни и код. С други думи, обект също се нарича Представител(от някакъв клас) е част от данните, чиято стойност определя текущото му състояние, и набор от подпрограми, наречени методиопериране с тези данни и дефиниране поведениеобект, т.е. неговата реакция на външни влияния.

Обектът се състои от следните три части:

Име на обекта;

Състояние (променливи на състоянието);

Методи (операции).

Всеки обект е представител (инстанция) на определен клас. По време на изпълнение на програмата обектите взаимодействат помежду си чрез извикване на методи, които са подпрограми, специфични за определен клас.

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


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

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

Практически подход.В съвременните обектно-ориентирани езици за програмиране (php, Java, C++, Oberon, Python, Ruby, Smalltalk, Object Pascal) създаването на клас се свежда до писане на структура, съдържаща набор от полета и методи. На практика класът може да се разбира като вид шаблон, според който се създават обекти – екземпляри на даден клас. Екземплярите на един и същи клас се създават с помощта на един и същ шаблон и следователно имат същия набор от полета и методи.

Връзки между класове:

Наследяване (Обобщение) - обектите на дъщерен клас наследяват всички свойства на родителския клас.

Асоциация - обектите на класовете взаимодействат помежду си.

Агрегиране - обекти от един клас се включват в обекти от друг.

Композиция - обекти от един клас са включени в обекти от друг и зависят един от друг по отношение на техния живот.

Клас-метаклас е връзка, в която други класове са екземпляри на един клас.

Видове класове:

Базов (родителски) клас;

Производен клас (наследник, потомък);

Абстрактен клас;

Виртуален клас;

Интерфейс.

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

Методи- процедури и функции, капсулирани в клас, тоест начини за работа с данни.

Класовете и обектно-ориентираното програмиране се основават на три принципа: - капсулиране, наследяванеИ полиморфизъм.

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

Най-често капсулирането се осъществява чрез скриване на информация, тоест маскиране на всички вътрешни детайли, които не влияят на външното поведение. Обикновено както вътрешната структура на обекта, така и изпълнението на неговите методи са скрити.

Цели на капсулирането:

§ екстремна локализация на промените, ако такива промени са необходими,

§ предвидимост на промените (какви промени в кода трябва да се направят за дадена промяна във функционалността) и предвидимост на последствията от промените.

Капсулиране- това е процесът на отделяне един от друг на елементите на даден обект, които определят неговата структура и поведение. Често капсулирането може да се постигне чрез прости организационни мерки: знанието, че „това не е нещо, което не можете да направите“ понякога е най-ефективното средство за капсулиране!

Капсулиране- комбинирането на записи с процедури и функции, които манипулират полетата на тези записи, образува нов тип данни - обект.

Капсулиране- изолиране на компонентите на класа (полета, методи и свойства) от други части на програмата.

Същността на капсулирането: Променливите на състоянието на обекта са скрити от външния свят. Промяната на състоянието на обект (неговите променливи) е възможна САМО с помощта на неговите методи (операции). Защо това е толкова важно? Този принцип ви позволява да защитите променливите на състоянието на обекта от злоупотреба.

Използването на този метод води до намаляване на ефективността на достъпа до елементите на обекта. Това се дължи на необходимостта от извикване на методи за промяна на вътрешните елементи (променливи) на обекта. При сегашното ниво на развитие на компютърните технологии обаче тези загуби в ефективността не играят съществена роля.

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

Наследство- това е процесът, чрез който един обект може да наследи свойствата на друг обект и да добави към тях характеристики, характерни само за него. Смисълът и универсалността на наследяването се крие във факта, че не е необходимо да описвате нов обект всеки път (от нулата), но можете да посочите родителя (базов клас) и да опишете отличителните черти на новия клас. В резултат на това новият обект ще има всички свойства на родителския клас плюс свои собствени отличителни характеристики.

Наследство- представлява възможността за изграждане на йерархия от обекти, използвайки наследяването на техните характеристики.

Наследство. Наследяването е свойство на обект, което му позволява да използва полетата и методите на родителския обект, без да ги описва в своята структура.

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

Ако нов метод със същото име като метод на родителския клас е описан в наследствен клас, тогава те казват, че родителският метод е „отменен“ в потомъка. С други думи, клас наследник имплементира спецификацията на вече съществуващ клас (базов клас). Това ви позволява да третирате обекти от клас наследник по същия начин като обекти от базов клас. Когато създавате йерархия на класове, някои свойства на обектите, запазвайки имената, се променят по същество.

За прилагане на такива йерархии езикът за програмиране осигурява полиморфизъм.Думата полиморфизъм е от гръцки произход и се превежда като „имащ много форми“.

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

Полиморфизъме свойство, което позволява едно и също име да се използва за решаване на няколко технически различни проблема.

От гледна точка на ООП можем да кажем, че всички видове интерфейсни бутони имат способността да се показват на екрана. Въпреки това методът (процедурата) е различен за всеки тип бутон. Един прост бутон се изчертава на екрана с помощта на процедурата „показване на изображение на обикновен бутон“, бутон за превключване се изчертава на екрана чрез процедурата „показване на изображение на бутон за превключване“ и т.н.

По този начин има едно действие за целия списък с интерфейсни бутони (показване на изображението на бутона на екрана), което се изпълнява по специфичен начин за всеки бутон. Това е проява на полиморфизъм.

Полиморфизъм- способността на класовете да решават подобни проблеми по различни начини. Когато родителският метод е отменен, нов алгоритъм за решаване на проблема се прилага в детето. Оказва се, че в родителския обект и дъщерния обект има два едноименни метода, които имат различна алгоритмична основа.

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

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

ПредимствоПолиморфизмът е, че помага за намаляване на сложността на програмата, като позволява един интерфейс да се използва за един клас действия. Изборът на конкретно действие, в зависимост от ситуацията, зависи от компилатора.

В ООП целта на полиморфизма е да се използва едно име за дефиниране на действия, общи за даден клас. На практика това означава способността на обектите да избират вътрешна процедура (метод) въз основа на типа данни, получени в съобщението.

Механизмът на работа на ООП в такива случаи може да се опише по следния начин: при извикване на един или друг метод на класа първо се търси методът на самия клас. Ако бъде намерен метод, той се изпълнява и търсенето на този метод приключва. Ако методът не бъде намерен, тогава се обръщаме към родителския клас и търсим извикания метод в него. Ако бъде намерен, продължаваме така, сякаш сме намерили метод в самия клас. И ако не, продължаваме да търсим нагоре по йерархичното дърво. До корена (горния клас) на йерархията.

Основни принципи и етапи на обектно-ориентирания

програмиране

В теорията на програмирането ООП се дефинира като технология за създаване на сложен софтуер, която се основава на представянето на програмата като колекция от обекти, всеки от които е екземпляр от определен тип (клас), а класовете образуват йерархия с

наследяване на имоти.

Взаимодействието на софтуерните обекти в такава система се осъществява чрез предаване на съобщения.

Забележка.Това представяне на програмата е използвано за първи път в симулационния език за сложни системи Simula, който се появява през 60-те години.

Начинът за представяне на програма, който е естествен за езиците за моделиране, е разработен в друг специализиран език за моделиране - езикът Smalltalk (70-те години), а след това е

Страница 2 от 51

Основни принципи на ООП

използвани в нови версии на универсални езици за програмиране като Pascal, C++,

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

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

което дава възможност за практически независимо развитие на отделните части

(обекти) на програмата.

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

което ви позволява да конструирате сложни обекти от по-прости. В резултат на това степента на повторно използване на код се увеличава значително,

Става възможно да се създават библиотеки от обекти за различни приложения, а на разработчиците се предоставят допълнителни възможности за създаване на системи с повишена сложност.

Основният недостатък на OOP е леко намаляване на производителността поради по-сложна организация на софтуерната система.

ООП се основава на следните принципи: абстракция,

ограничение на достъпа, модулност, йерархия, типизиране, паралелизъм,

устойчивост.

Нека да разгледаме какво представлява всеки принцип.

A b p s t r a g e- процесът на идентифициране на абстракции в предметната област на задача. Абстракцията е набор от съществени характеристики на даден обект, които го отличават от всички други видове обекти и,

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

трето - материалите, от които е направено, четвърто - законът на движението

Страница 3 от 51

Основни принципи на ООП

предмет и др. Съвременното ниво на абстракция включва обединяването на всички свойства на абстракцията (както тези, свързани със състоянието на анализирания обект,

и определяне на неговото поведение) в единична програмна единица, определена

абстрактен тип (клас).

Ограничение на достъпа- скриване на отделни елементи от изпълнението на абстракцията, които не засягат съществените характеристики на нея като цяло.

Необходимостта от ограничаване на достъпа изисква разграничение между две части в описанието на абстракцията:

интерфейс - набор от елементи на внедряване на абстракция, достъпен отвън (основни характеристики на състояние и поведение);

изпълнение - набор от елементи на изпълнението на абстракция, които са недостъпни отвън (вътрешната организация на абстракцията и механизмите за прилагане на нейното поведение).

Ограничаването на достъпа в OOP позволява на програмиста да:

изграждайте системата на етапи, без да се разсейвате от характеристиките на изпълнението на използваните абстракции;

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

Комбинацията от комбиниране на всички свойства на обект (компонентите на неговото състояние и поведение) в една абстракция и ограничаване на достъпа до изпълнението на тези свойства се нарича капсулиране.

МОДУЛНОСТ- принципът на разработване на софтуерна система,

което предполага изпълнението му под формата на отделни части (модули). При разлагането на системата на модули е желателно да се комбинират логически свързани части, като се осигури, ако е възможно, намаляване на броя на външните връзки между модулите. Принципът е наследен от

Страница 4 от 51

Основни принципи на ООП

модулно програмиране, следването му опростява дизайна и

отстраняване на грешки в програмата.

Йерархията е класирана или подредена система от абстракции.

Принципът на йерархията включва използването на йерархии при разработването на софтуерни системи.

OOP използва два типа йерархия.

Йерархия "цяло/част"- показва, че някои абстракции са разрешени

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

Йерархия "общи/частни"- показва, че дадена абстракция е частен случай на друга абстракция, например "маса за хранене -

специфичен тип маса“ и „масите са специфичен тип мебели“. Използвани за

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

Един от най-важните механизми на OOP е наследяването на свойства в публичната/частната йерархия. Наследяването е връзка между абстракции, когато една от тях използва структурна или функционална част от друга или няколко други абстракции (съответно прости и множествени

наследство).

ТИПЗАЦИЯ - ограничение, наложено върху свойствата на обектите и

предотвратяване на взаимозаменяемостта на абстракции от различни видове (или значително намаляване на възможността за такава замяна). В строго типизирани езици, за всеки програмен обект (променлива, подпрограма, параметър и т.н.)

декларира тип, който дефинира набор от операции върху

Страница 5 от 51

Основни принципи на ООП

съответния софтуерен обект. Езиците за програмиране, базирани на Pascal, разгледани по-долу, използват strict, а тези, базирани на C -

средна степен на типизация.

Използването на принципа на писане гарантира:

ранно откриване на грешки, свързани с невалидни операции върху програмни обекти (грешките се откриват на етапа на компилация на програмата, когато се проверява допустимостта на извършване на дадена операция върху програмен обект);

опростяване на документацията;

възможност за генериране на по-ефективен код.

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

П а р л л е л и с м- свойството няколко абстракции да са в активно състояние едновременно, т.е. извършете някои операции.

Има редица задачи, чието решаване изисква едновременно изпълнение на определена последователност от действия. За такива задачи

например задачи, свързани с автоматично управление на няколко процеса.

Реален паралелизъм се постига само при изпълнение на задачи от този тип на многопроцесорни системи, когато е възможно всеки процес да се изпълнява на отделен процесор. Еднопроцесорните системи симулират паралелизъм, като разделят процесорното време между задачите за управление на различни процеси. В зависимост от вида на използваната операционна система (единична или многопрограмна)

Страница 6 от 51

Основни принципи на ООП

споделянето на време може да се извърши или от системата, която се разработва (както в

MS DOS), или използваната операционна система (както в Windows системи).

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

Има:

∙ временни обекти, които съхраняват междинни резултати от определени действия, като изчисления;

∙ локални обекти, които съществуват вътре в подпрограмите, чийто живот се изчислява от извикването на подпрограмата до нейното завършване;

∙ глобални обекти, които съществуват, докато програмата се зарежда в паметта;

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

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

Обектно-ориентирани езици за програмиране. Езикът има значение обектно-ориентиран,ако прилага първите четири от седемте обсъждани принципа.

Особено място заемат обектните модели на Delphi и C++Builder. Тези модели обобщават опита на ООП за MS DOS и включват някои нови функции,

осигуряване на ефективно създаване на по-сложни системи. Въз основа на тези модели са създадени визуални среди за разработване на Windows приложения.

Сложността на програмирането под Windows е значително преодоляна

намалени чрез създаване на специални библиотеки от обекти, които „скриват“ много елементи от техниките за програмиране.

Страница 7 от 51

Основни принципи на ООП

Етапи на разработване на софтуерни системи, използващи ООП.

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

Нека да разгледаме тези етапи.

Анализ . Целта на анализа е най-пълното описание на проблема. На този етап се извършва анализ на проблемната област, извършва се обектна декомпозиция на разработваната система и се определят най-важните характеристики на поведението на обектите (описание на абстракциите). Въз основа на резултатите от анализа се разработва блокова схема на софтуерния продукт, която показва основните обекти и съобщенията, предавани между тях, а също така описва абстракциите.

Дизайн. Има:

логичен дизайн,при които взетите решения са практически независими от условията на работа (операционна система и използвано оборудване);

физически дизайн,в които тези фактори трябва да се вземат предвид.

Логичен дизайне да се разработи класова структура:

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

състав, съдържание, полиморфизъм и др.). Резултатът е йерархия или диаграма на класове, показваща връзките между класовете и описание на класовете.

Физически дизайнвключва комбиниране на описания на класове в модули, избор на тяхната схема на свързване (статично или динамично оформление), определяне на начини за взаимодействие с оборудването, с

операционна система и/или друг софтуер (напр.

бази данни, мрежови програми), осигуряване на синхронизация на процесите за паралелни системи за обработка и др.

Страница 8 от 51

Основни принципи на ООП

Еволюция на системите.Това е процес на поетапно изпълнение и

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

работещ прототип на бъдещата система. Той е тестван и отстранени грешки.

Например, такъв прототип може да бъде система, която включва внедряване на основния интерфейс на софтуерен продукт (съобщенията не се предават към част от системата, която все още не е достъпна). В резултат на това получаваме работещ прототип на продукта, който може например да бъде показан на клиента за изясняване на изискванията. След това към системата се свързва следващата група класове, например свързана с изпълнението на определен елемент от менюто.

Получената версия също се тества и отстранява грешки и така нататък, докато се реализират всички възможности на системата.

Използването на поетапно внедряване значително опростява тестването и отстраняването на грешки на софтуерен продукт.

Модификация. Това е процес на добавяне на нова функционалност или промяна на съществуващи системни свойства. обикновено,

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

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

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

Страница 9 от 51

Основни принципи на ООП

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

Обикновено проектирането започва, когато всеки фрагмент от предметната област е достатъчно пълно описан в процеса на анализ.

Ще започнем нашето разглеждане на основните техники на обектния подход с обектна декомпозиция.

Декомпозиция на обекта

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

възникващи в предметната област на задачата.

В такава система всеки функционален елемент, след като е получил някакво входно влияние (наречено съобщение) в процеса на решаване на проблема,

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

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

(т.е. „способни“ да извършват определени действия в зависимост от получените съобщения и състоянието на елемента) се наричат ​​обекти.

Извиква се процесът на представяне на проблемния домейн като колекция от обекти, които обменят съобщения декомпозиция на обекта.

Страница 10 от 51

Основни принципи на ООП

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

Пример. Декомпозиция на обект (симулационен модел

бензиностанции). Нека се интересуваме от зависимостта на дължината на опашката на бензиностанция от броя на бензиностанциите, параметрите на обслужване на всяка бензиностанция и интензивността на заявките за зареждане (разглеждаме един и същ вид гориво).

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

Процесът на работа на бензиностанция с три бензиностанции може да бъде представен под формата на диаграма.

Не знам как да програмирам на обектно-ориентирани езици. Не научих. След 5 години индустриално програмиране в Java, все още не знам как да създам добра система в обектно-ориентиран стил. Просто не разбирам.

Опитах се да се науча, честно. Изучавах шаблони, четох кода на проекти с отворен код, опитвах се да изградя последователни концепции в главата си, но все още не разбирах принципите за създаване на висококачествени обектно-ориентирани програми. Може би някой друг ги е разбрал, но не и аз.

И ето няколко неща, които ме объркват.

Не знам какво е ООП

Сериозно. Трудно ми е да формулирам основните идеи на ООП. Във функционалното програмиране една от основните идеи е бездържавността. В структурно - разлагане. При модулния функционалността е разделена на пълни блокове. Във всяка от тези парадигми доминиращите принципи се прилагат към 95% от кода и езикът е проектиран да насърчава тяхното използване. Не знам такива правила за ООП.
  • Абстракция
  • Капсулиране
  • Наследство
  • Полиморфизъм
Изглежда като набор от правила, нали? Значи това са правилата, които трябва да се спазват в 95% от случаите? Хм, нека погледнем по-отблизо.

Абстракция

Абстракцията е мощен инструмент за програмиране. Това ни позволява да изграждаме големи системи и да поддържаме контрол над тях. Малко вероятно е някога да се доближим дори до днешното ниво на програми, ако не бяхме въоръжени с такъв инструмент. Как обаче абстракцията се свързва с ООП?

Първо, абстракцията не е атрибут изключително на ООП или на програмирането като цяло. Процесът на създаване на нива на абстракция обхваща почти всички области на човешкото познание. По този начин можем да правим преценки за материалите, без да навлизаме в детайлите на тяхната молекулярна структура. Или говорете за предмети, без да споменавате материалите, от които са направени. Или говорете за сложни механизми, като компютър, самолетна турбина или човешко тяло, без да си спомняте отделни подробности за тези същности.

Второ, винаги е имало абстракции в програмирането, като се започне от писанията на Ада Лавлейс, която се смята за първия програмист в историята. Оттогава хората непрекъснато създават абстракции в своите програми, често само с най-простите инструменти за това. По този начин Абелсън и Сусман в своята добре известна книга описват как да се създаде система за решаване на уравнения, която поддържа комплексни числа и дори полиноми, използвайки само процедури и свързани списъци. И така, какви допълнителни средства за абстракция предоставя OOP? Нямам идея. Разделяне на кода на подпрограми? Всеки език на високо ниво може да направи това. Комбиниране на рутини на едно място? Има достатъчно модули за това. Типизация? Съществуваше много преди ООП. Примерът със система за решаване на уравнения ясно показва, че изграждането на нива на абстракция зависи не толкова от езиковите средства, колкото от способностите на програмиста.

Капсулиране

Основното предимство на капсулирането е да скрие изпълнението. Клиентският код вижда само интерфейса и може да разчита само на него. Това освобождава разработчиците, които могат да решат да променят изпълнението. И това е наистина страхотно. Но въпросът отново е какво общо има OOP с това? всичкоГорните парадигми включват скриване на изпълнението. Когато програмирате в C, вие разпределяте интерфейса в заглавни файлове, Oberon ви позволява да направите полета и методи локални за модула и накрая, абстракцията в много езици се изгражда просто чрез подпрограми, които също капсулират изпълнението. Освен това самите обектно-ориентирани езици често нарушават правилото за капсулиране, предоставяне на достъп до данни чрез специални методи - getters и setter в Java, свойства в C# и др. (В коментарите разбрахме, че някои обекти в езиците за програмиране не са обекти от OOP гледна точка: обектите за прехвърляне на данни са отговорни единствено за прехвърлянето на данни и следователно не са пълноценни OOP обекти и следователно няма нужда от тях, за да запазят капсулирането. От друга страна, методите за достъп са най-добре запазени, за да поддържат архитектурна гъвкавост. Ето как става сложно.) Освен това някои обектно-ориентирани езици, като Python, изобщо не се опитват да скрият нищо , но разчитайте единствено на интелигентността на разработчиците, използващи този код.

Наследство

Наследяването е едно от малкото нови неща, които наистина се появиха на сцената благодарение на ООП. Не, обектно-ориентираните езици не създадоха нова идея - наследяването може да бъде приложено във всяка друга парадигма - но OOP за първи път доведе тази концепция до нивото на самия език. Предимствата на наследството също са очевидни: когато вие почтидоволни от някакъв клас, можете да създадете наследник и да замените част от неговата функционалност. В езиците, които поддържат множествено наследяване, като C++ или Scala (в последния, чрез черти), се появява друг случай на използване - mixins, малки класове, които ви позволяват да „смесвате“ функционалност в нов клас, без да копирате кода.

И така, това е, което отличава ООП като парадигма от другите? Хм... ако е така, защо толкова рядко го използваме в реален код? Помните ли какво казах за 95% от кода, който се подчинява на правилата на доминиращата парадигма? не се шегувах При функционалното програмиране най-малко 95% от кода използва неизменни данни и функции без странични ефекти. При модулния почти целият код е логически пакетиран в модули. Привържениците на структурираното програмиране, следвайки предписанията на Дейкстра, се опитват да разделят всички части на програмата на малки части. Наследяването се използва много по-рядко. Може би в 10% от кода, може би в 50%, в някои случаи (например при наследяване от рамкови класове) - в 70%, но не повече. Защото в повечето ситуации е лесно няма нужда.

Освен това наследство опасноза добър дизайн. Толкова опасен, че Бандата на четиримата (привидно проповедници на ООП) в книгата си препоръчва да се замени с делегиране, когато е възможно. Наследяването, както съществува в популярните в момента езици, води до крехък дизайн. След като е бил наследен от един предшественик, класът вече не може да бъде наследен от други. Смяната на предшественик също става опасна. Има, разбира се, частни/защитени модификатори, но те също изискват значителни психически способности, за да отгатнат как класът може да се промени и как клиентският код може да го използва. Наследяването е толкова опасно и неудобно, че големите рамки (като Spring и EJB в Java) го изоставят в полза на други, необектно-ориентирани инструменти (например метапрограмиране). Последствията са толкова непредсказуеми, че някои библиотеки (като Guava) присвояват модификатори на своите класове, които забраняват наследяването, а в новия език Go беше решено напълно да се откаже от йерархията на наследяването.

Полиморфизъм

Може би полиморфизмът е най-доброто нещо в обектно-ориентираното програмиране. Благодарение на полиморфизма, когато се извежда, обект от тип Person изглежда като „Шандоркин Адам Имполитович“, а обект от тип Point изглежда като „“. Именно това ви позволява да напишете „Mat1 * Mat2“ и да получите произведението на матрици, подобно на произведението на обикновените числа. Без него не би било възможно да се четат данни от входния поток, без да се интересува дали идват от мрежата, файл или ред в паметта. Навсякъде, където има интерфейси, се подразбира и полиморфизъм.

Много харесвам полиморфизма. Затова дори няма да говоря за проблемите му на основните езици. Ще замълча и за теснотата на диспечерския подход само по тип и за това как може да стане това. В повечето случаи работи както трябва, което не е лошо. Въпросът е: полиморфизмът ли е самият принцип, който отличава ООП от другите парадигми? Ако ме бяхте попитали (а тъй като четете този текст, можете да предположите, че сте попитали), щях да отговоря с „не“. И причината е все същият процент на използване в кода. Може би интерфейсите и полиморфните методи са малко по-често срещани от наследяването. Но сравнете броя на редовете код, които те заемат, с броя на редовете, написани в обичайния процедурен стил - винаги има повече от последните. Разглеждайки езиците, които насърчават този стил на програмиране, не бих ги нарекъл полиморфни. Езици, които поддържат полиморфизъм - да, това е нормално. Но не и полиморфни езици.

(Това обаче е моето мнение. Винаги можете да не се съгласите.)

И така, абстракция, капсулиране, наследяване и полиморфизъм - всичко това е в ООП, но нищо от това не е негов интегрален атрибут. Тогава какво е ООП? Има мнение, че същността на обектно-ориентираното програмиране се крие в обектите (звучи доста логично) и класовете. Това е идеята за комбиниране на код и данни и идеята, че обектите в една програма отразяват обекти в реалния свят. Ще се върнем към това мнение по-късно, но нека първо да сложим точка на i.

Чий OOP е по-готин?

От предишната част става ясно, че езиците за програмиране могат да се различават значително по начина, по който реализират обектно-ориентираното програмиране. Ако вземете съвкупността от всички внедрявания на ООП на всички езици, тогава най-вероятно няма да намерите нито една функция, обща за всички. За да огранича по някакъв начин този зоопарк и да изясня разсъжденията, ще се спра само на една група - чисто обектно-ориентирани езици, а именно Java и C#. Терминът „чисто обектно-ориентиран“ в този случай означава, че езикът не поддържа други парадигми или не ги прилага чрез същия OOP. Python или Ruby например няма да са чисти, т.к можете лесно да напишете пълноценна програма върху тях без нито една декларация на клас.

За да разберем по-добре същността на ООП в Java и C#, нека да разгледаме примери за прилагане на тази парадигма в други езици.

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

Common Lisp.Първоначално CL следваше същата парадигма. Тогава разработчиците решиха, че писането на `(send obj "some-message)` е твърде дълго, и преобразуваха нотацията в извикване на метод - `(some-method obj)` Днес Common Lisp има зряла обектно-ориентирана система за програмиране ( CLOS) с поддръжка за множествено наследяване, мултиметоди и метакласове. Отличителна черта е, че ООП в CL не се върти около обекти, а около общи функции.

Clojure. Clojure има две обектно-ориентирани системи за програмиране – едната е наследена от Java, а втората е базирана на мултиметоди и е по-подобна на CLOS.

Р.Този език за статистически анализ на данни има и 2 обектно-ориентирани системи за програмиране - S3 и S4. И двата са наследени от езика S (което не е изненадващо, като се има предвид, че R е имплементация с отворен код на комерсиалния S). S4 до голяма степен съвпада с внедряването на ООП в съвременните масови езици. S3 е по-лека опция, просто реализирана с помощта на самия език: създава се една обща функция, която изпраща заявки въз основа на атрибута „клас“ на получения обект.

JavaScript.Идеологически подобен на Smalltalk, въпреки че използва различен синтаксис. Вместо наследяване, той използва прототипиране: ако желаното свойство или извикан метод не е в самия обект, тогава заявката се предава на прототипния обект (прототипното свойство на всички JavaScript обекти). Интересен факт е, че поведението на всички обекти на класа може да се промени чрез замяна на един от прототипните методи (например добавянето на метода `.toBASE64` за класа string изглежда много добре).

Python.Като цяло той следва същата концепция като основните езици, но също така поддържа предаване на търсенето на атрибут към друг обект, както в JavaScript или Smalltalk.

Haskell.В Haskell изобщо няма състояние и следователно няма обекти в обичайния смисъл. Въпреки това, там все още има един вид ООП: типовете данни могат да принадлежат към един или повече класове типове. Например, почти всички типове в Haskell са в класа Eq (отговорен за операциите за сравнение между 2 обекта), а всички числа са допълнително в класовете Num (операции с числа) и Ord (операции с числа).<, <=, >=, >). В менструалните езици типовете съответстват на класове (от данни), а типовите класове съответстват на интерфейси.

Държавен или без гражданство?

Но да се върнем към по-разпространените системи за обектно-ориентирано програмиране. Това, което никога не можах да разбера, е връзката на обектите с вътрешното състояние. Преди изучаването на ООП всичко беше просто и прозрачно: има структури, които съхраняват няколко свързани данни, има процедури (функции), които ги обработват. разходка (куче), теглене (сметка, сума). След това обектите пристигнаха и това също беше наред (въпреки че четенето на програмите стана много по-трудно - кучето ми се разхождаше [кой?], а сметката теглеше пари [откъде?]). Тогава научих за скриването на данни. Все още можех да разхождам кучето, но вече не можех да гледам състава на храната му. Храната не направи нищо (вероятно бихте могли да напишете food.eat(dog), но все пак предпочитам кучето ми да яде храна, а не обратното). Храната е само данни и аз (и кучето ми) просто имах нужда от достъп до тях. всичко Просто. Но вече не беше възможно да се вмести в рамката на парадигмата, както в стари дънки от края на 90-те.

Добре, имаме методи за достъп до данни. Нека се отдадем на тази малка самоизмама и да се преструваме, че данните ни наистина са скрити. Но сега знам, че обектите са преди всичко данни, а след това може би методи, които ги обработват. Разбрах как се пишат програми, към какво да се стремя при проектирането.

Преди да имам време да се насладя на просветлението, видях думата без гражданство в интернет (заклех се, че беше заобиколена от сияние и ореол надвисна над буквите t и l). Кратко проучване на литературата разкри прекрасния свят на прозрачния контролен поток и простата многопоточност без необходимост от проследяване на последователността на обекта. Разбира се, веднага поисках да се докосна до този прекрасен свят. Това обаче означаваше пълно отхвърляне на всякакви правила - сега не беше ясно дали кучето трябва да се разхожда само или за това е необходим специален Walk Manager; имате ли нужда от сметка, или банката ще се справи с цялата работа и ако да, трябва ли да отписва пари статично или динамично и т.н. Броят на случаите на употреба се е увеличил експоненциално и всички бъдещи случаи на употреба могат да доведат до необходимостта от основен рефакторинг.

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

Въвеждане: статично или динамично?

Друго нещо, което не мога да реша за езици като C# и Java, е дали са статично или динамично въведени. Повечето хора вероятно ще възкликнат: „Какви глупости! Статично въведени разбира се! Типовете се проверяват по време на компилиране! Но наистина ли е толкова просто? Вярно ли е, че като посочи тип X в параметрите на даден метод, програмистът може да бъде сигурен, че обекти от тип X винаги ще му бъдат предавани? Точно така - не може, защото... ще бъде възможно да се предаде параметър от тип X на метод X или негов наследник. Изглежда, какво от това? Потомците на клас X все още ще имат същите методи като X. Методите са си методи, но логиката на работа може да се окаже напълно различна. Най-често срещаният случай е, когато дъщерен клас се окаже оптимизиран за нужди, различни от X, и нашият метод може да разчита точно на тази оптимизация (ако подобен сценарий ви се струва нереалистичен, опитайте да напишете плъгин за някоя разработена библиотека с отворен код - или ще прекарате няколко седмици, за да анализирате архитектурата и алгоритмите на библиотеката, или просто ще извикате произволно методи с подходящ подпис). В резултат на това програмата работи, но скоростта на работа пада с порядък. Въпреки че от гледна точка на компилатора всичко е правилно. Важно е, че Scala, която се нарича наследник на Java, на много места по подразбиране позволява да се предават само аргументи от посочения тип, въпреки че това поведение може да бъде променено.

Друг проблем е нулевата стойност, която може да бъде предадена вместо почти всеки обект в Java и вместо всеки Nullable обект в C#. null принадлежи към всички типове едновременно и в същото време не принадлежи към нито един. null няма нито полета, нито методи, така че всяко извикване към него (освен проверката за null) води до грешка. Изглежда, че всички са свикнали с това, но за сравнение, Haskell (и същата Scala) е принуден да използва специални типове (Може би в Haskell, Option в Scala), за да обгърне функции, които на други езици могат да върнат нула. В резултат на това те често казват за Haskell „трудно е да компилираш програма върху него, но ако успееш, тогава най-вероятно работи правилно“.

От друга страна, основните езици очевидно не се въвеждат динамично и следователно нямат такива свойства като прости интерфейси и гъвкави процедури. В резултат на това писането в стил Python или Lisp също става невъзможно.

Каква е разликата как се нарича това писане, ако така или иначе всички правила са известни? Разликата е от коя страна подхождате към дизайна на архитектурата. Има дългогодишен дебат за това как да се изгради система: да се направят много типове и малко функции или малко типове и много функции? Първият подход се използва активно в Haskell, вторият в Lisp. Съвременните обектно-ориентирани езици използват нещо между тях. Не искам да казвам, че това е лошо - сигурно има своите предимства (все пак не бива да забравяме, че Java и C# са многоезични платформи), но всеки път, когато стартирам нов проект, се чудя откъде да започна проектиране - с видове или от функционалност.

И по-нататък...

Не знам как да моделирам проблема. Смята се, че ООП ви позволява да показвате обекти от реалния свят в програма. Обаче реално имам куче (с две уши, четири лапи и нашийник) и банкова сметка (с управител, чиновници и обедна почивка), а в програмата - WalkManager, AccountFactory... е, получаваш идеята. И въпросът не е, че програмата има спомагателни класове, които не отразяват обекти от реалния свят. Факт е, че контролни промени в потока. Walking Manager ме ограбва от радостта да разхождам кучето си и получавам пари от бездушна банкова сметка (хей, къде е онова сладко момиче, на което смених пари миналата седмица?).

Може би съм сноб, но бях много по-щастлив, когато данните в компютъра бяха само данни, дори и да описват моето куче или банкова сметка. Можех да правя каквото ми беше удобно с данните, без да се съобразявам с реалния свят.

Също така не знам как правилно да разложа функционалността. В Python или C++, ако имах нужда от малка функция за преобразуване на низ в число, просто го записах в края на файла. В Java или C# съм принуден да го поставя в отделен клас StringUtils. В езиците преди OO бих могъл да декларирам ad hoc обвивка, за да върна две стойности от функция (изтеглената сума и салдото по сметката). В ООП езиците ще трябва да създам пълноценен клас Резултат от транзакция. И за нов човек в проекта (или дори за мен седмица по-късно), този клас ще изглежда също толкова важен и основен в архитектурата на системата. 150 файла и всички еднакво важни и фундаментални - о, да, прозрачна архитектура, прекрасни нива на абстракция.

Не знам как да пиша ефективни програми. Ефективните програми използват малко памет - в противен случай събирачът на отпадъци постоянно ще забавя изпълнението. Но за да извършите най-простата операция в обектно-ориентираните езици, трябва да създадете дузина обекти. За да направя една HTTP заявка, трябва да създам обект от тип URL, след това обект от тип HttpConnection, след това обект от тип Request... добре, схванахте идеята. В процедурното програмиране просто бих извикал няколко процедури, предавайки им структура, създадена в стека. Най-вероятно в паметта ще бъде създаден само един обект - за съхраняване на резултата. В ООП трябва да претрупвам паметта през цялото време.

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

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

Какво е обектно ориентирано програмиране

Обектно-ориентираното програмиране е стил на кодиране, който позволява на разработчика да групира подобни задачи класове. Така кодът отговаря на принципа DRY (не се повтаряйте) и става лесен за поддръжка.

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

OOP плаши много разработчици, защото въвежда нов синтаксис и на пръв поглед изглежда по-сложен от обикновеното процедурно кодиране. Въпреки това, при по-внимателно разглеждане, ООП всъщност е много ясен и изключително прост подход към програмирането.

Какво представляват обектите и класовете

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

Каква е разликата между класове и обекти

Разработчиците, започвайки да говорят за класове и обекти, започват да заменят понятията. За съжаление това се случва много често.

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

И обектът е истинска къща, която е изградена по проект. Данните, които се съхраняват в даден обект, са като дървото, жиците и бетона, които изграждат къща: без сглобяване според проекта, тя ще бъде просто купчина материали. Въпреки това, когато са събрани заедно, те правят отличен и удобен дом.

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

Структура на класа

Синтаксисът за създаване на клас е много прост: за да декларирате клас, използвайте ключовата дума class, последвана от името на класа и набор от фигурни скоби (()):

След създаването на клас, нов обект може да бъде инстанциран и съхранен в променлива с помощта на ключовата дума new:

$obj = нов MyClass;

За да видите съдържанието на обект, използвайте var_dump():

Var_dump($obj);

Можете да тествате целия процес, като копирате целия код във файла test.php:

Заредете страницата в браузъра си и на екрана трябва да се появи следният ред:

Обект (MyClass)#1 (0) ( )

Току-що създадохте своя първи ООП скрипт.

Дефиниране на свойства на класа

Свойствата или променливите на класа се използват за добавяне на данни към клас. Свойствата работят като обикновени променливи, но те са свързани с обект и могат да бъдат достъпни само чрез използване на обекта.

За да добавите свойства към класа MyClass, използвайте този код във вашия скрипт:

Ключовата дума public определя видимостта на свойство, което ще разгледаме по-късно в тази глава. След това свойството се наименува с помощта на нормален синтаксис на променливата и му се присвоява стойност (въпреки че свойство на клас не трябва да се инициализира).

Ехо $obj->prop1;

Тъй като може да има множество реализации на клас, без препратка към конкретен обект, свойството не може да бъде прочетено, защото скриптът не може да определи от кой обект да се чете. Стрелката (->) е OOP конструкция, която се използва за достъп до свойствата и методите на даден обект.

Променете скрипта в test.php, за да прочете стойността на свойството, вместо да показва информация за целия клас:

опора1; // Показване на свойството?>

Обновете страницата в браузъра си, за да видите резултата от скрипта:

Свойство на класа

Дефиниране на класови методи

Методе функция от клас. Индивидуално действие, което обектът може да извърши, се дефинира в клас като метод.

Например, нека създадем методи, които задават и четат стойността на свойството $prop1:

prop1 = $newval; ) публична функция getProperty() ( връща $this->prop1 . "
"; ) ) $obj = нов MyClass; echo $obj->prop1; ?>

Забележка- OOP позволява на обект да се позовава на себе си с помощта на $this. Когато работите вътре в метод, използването на $this ви позволява да използвате името на обекта извън класа.

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

prop1 = $newval; ) публична функция getProperty() ( връща $this->prop1 . "
"; ) ) $obj = нов MyClass; echo $obj->getProperty(); // получаване на стойността на свойството $obj->setProperty("Ново свойство."); // Задаване на нова стойност echo $obj->getProperty () ; // Прочетете отново стойността, за да видите промените?>

Опресняваме страницата в браузъра и виждаме следното:

Свойство на клас Ново свойство

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

prop1 = $newval; ) публична функция getProperty() ( връща $this->prop1 . "
"; ) ) // Създаване на два обекта $obj = нов MyClass; $obj2 = нов MyClass; // Получаване на стойностите на $prop1 от двата обекта echo $obj->getProperty(); echo $obj2->getProperty( ); // Задаване на нови стойности на свойства за двата обекта $obj->setProperty("Нова стойност на свойство"); $obj2->setProperty("Свойството принадлежи на втория обект"); // Отпечатване на $prop1 стойности ​за двете echo $obj->getProperty(); echo $obj2->getProperty(); ?>

Когато заредите страницата в браузъра, ще видите следното:

Свойство на класа Свойство на класа Нова стойност на свойството Свойството принадлежи към втория обект

Забележка, OOP съхранява обекти като различни обекти, което улеснява разделянето на кода на различни малки и взаимосвързани части.

Магически методи в ООП

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

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

Когато се създава обект, често е необходимо определени свойства да бъдат зададени веднага. За да изпълнява такива задачи, PHP има магически метод __construct(), който се извиква автоматично, когато се създава нов обект.

За да илюстрираме концепцията, нека добавим конструктор към класа MyClass. Той ще отпечата съобщение, когато бъде създаден нов обект от клас:

"; ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) публична функция getProperty() ( return $this->prop1 . "
"; ) ) // Създаване на нов обект $obj = new MyClass; // Получаване на стойността на свойството $prop1 echo $obj->
"; ?>

Забележка— константата __CLASS__ връща името на класа, в който е извикана; това е една от магическите константи на PHP.

Създаден е обект от клас "MyClass"! Край на свойството на файловия клас.

За да извикате функция по време на процеса на изтриване на обект, използвайте магическия метод __destruct(). Това е много полезен метод за правилно изчистване на свойствата на класа (например за правилно затваряне на връзка с база данни).

Ще покажем съобщение, когато обект от клас бъде изтрит с помощта на магическия метод:
__destruct() в MyClass:

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) публична функция getProperty() ( return $this->prop1 . "
"; ) ) // Създаване на нов обект $obj = new MyClass; // Получаване на стойността на свойството $prop1 echo $obj->getProperty(); // Показване на съобщение за достигане на края на файла echo "End на файл.
"; ?>

Опресняваме страницата в браузъра и получаваме резултата:

Създаден е обект от клас "MyClass"! Край на свойството на файловия клас. Обектът на класа "MyClass" е изтрит.

Когато се достигне краят на файла, PHP автоматично освобождава всички ресурси.

За изрично извикване на деструктор и премахване на обект, можете да използвате функцията unset():


"; ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) публична функция getProperty() ( return $this->prop1 . "
"; ) ) // Създаване на нов обект $obj = new MyClass; // Получаване на стойността на свойството $prop1 echo $obj->getProperty(); // Изтриване на обекта unset($obj); // Показване на съобщение за достигане на края на файла echo „Край на файла.
"; ?>

Сега резултатът от кода ще изглежда така след зареждане в браузъра:

Създаден е обект от клас "MyClass"! Свойство на клас Обектът на класа "MyClass" е изтрит. Край на файла.

Преобразуване в низ

За да се избегне грешка, ако скриптът се опита да изведе MyClass като низ, се използва друг магически метод, __toString().

Без да използвате __toString() опитът за извеждане на обект като низ ще доведе до фатална грешка. Опитайте да използвате функцията ехо, за да изведете обект, без да използвате магическия метод:

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) публична функция getProperty() ( return $this->prop1 . "

"; ?>

Резултатът ще изглежда така:

Създаден е обект от клас "MyClass"! Уловима фатална грешка: Обектът от клас MyClass не може да бъде преобразуван в низ в /Applications/XAMPP/xamppfiles/htdocs/testing/test.php на ред 40

За да избегнете грешката, използвайте метода __toString():

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция __toString() ( echo "Използвайте метода toString: "; върнете $this->getProperty(); ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) публична функция getProperty( ) ( върне $this->prop1 . "
"; ) ) // Създаване на нов обект $obj = new MyClass; // Извеждане на обекта като низ echo $obj; // Изтриване на обекта unset($obj); // Извеждане на съобщение за достигане на края на file echo "Край на файла.
"; ?>

В този случай опитът за конвертиране на обект в низ ще доведе до извикване на метода getProperty(). Заредете скрипта в браузъра и вижте резултата:

Създаден е обект от клас "MyClass"! Използваме метода toString: Свойство на клас Обектът на класа „MyClass“ е изтрит. Край на файла.

Използване на наследяване на класове

Класовете могат да наследяват методи и свойства от други класовеизползвайки ключовата дума extends. Например, нека създадем втори клас, който разширява MyClass и добавя метод:

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция __toString() ( echo "Използвайте метода toString: "; върнете $this->getProperty(); ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) публична функция getProperty( ) ( върне $this->prop1 . "
"; ) ) клас MyOtherClass разширява MyClass ( публична функция newMethod() ( echo "От новия метод на клас " . __CLASS__ .)."
"; ) ) // Създайте нов обект $newobj = new MyOtherClass; // Използвайте новия метод echo $newobj->newMethod(); // Използвайте метода от родителския клас echo $newobj->getProperty(); ? >

След като заредим скрипта в браузъра, получаваме резултата:

Създаден е обект от клас "MyClass"! От новия метод на класа "MyOtherClass". Свойство на клас Обектът на класа "MyClass" е изтрит.

Претоварване на наследени свойства и методи

За да промените поведението на съществуващи свойства или методи в нов клас, можете просто да ги претоварите, като ги декларирате отново в новия клас:

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция __toString() ( echo "Използвайте метода toString: "; върнете $this->getProperty(); ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) публична функция getProperty( ) ( върне $this->prop1 . "
"; ) ) клас MyOtherClass разширява MyClass ( публична функция __construct() ( echo "Нов конструктор в клас " . __CLASS__ .)."

"; ) ) // Създаване на нов обект $newobj = new MyOtherClass; // Извеждане на обекта като низ echo $newobj->newMethod(); // Използване на метода от родителския клас echo $newobj->getProperty() ; ?>

Промените ще доведат до следния резултат при изпълнение на кода:

Нов конструктор в класа "MyOtherClass". От новия метод на класа "MyOtherClass". Свойство на клас Обектът на класа "MyClass" е изтрит.

Запазване на оригиналната функционалност при претоварване на методи

За да добавите нова функционалност към наследен метод, като същевременно запазите функционалността на оригиналния метод, използвайте родителската ключова дума с оператор за резолюция на видимостта ( :: ) :

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция __toString() ( echo "Използвайте метода toString: "; върнете $this->getProperty(); ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) публична функция getProperty( ) ( върне $this->prop1 . "
"; ) ) клас MyOtherClass разширява MyClass ( публична функция __construct() ( parent::__construct(); // Извикване на конструктора на родителския клас echo "Нов конструктор в класа " . __CLASS__ .".
"; ) public function newMethod() ( echo "От нов метод на класа " . __CLASS__ . ".
"; ) ) // Създаване на нов обект $newobj = new MyOtherClass; // Извеждане на обекта като низ echo $newobj->newMethod(); // Използване на метода от родителския клас echo $newobj->getProperty() ; ?>

Горният код, когато бъде изпълнен, ще покаже съобщения както от конструкторите на новия, така и на родителския клас:

Създаден е обект от клас "MyClass"! Нов конструктор в класа "MyOtherClass". От новия метод на класа "MyOtherClass". Свойство на клас Обектът на класа "MyClass" е изтрит.

Определяне на обхвата на свойствата и методите

За допълнителен контрол върху обекти, методи и свойства е зададен обхват. Това контролира как и откъде могат да бъдат достъпни свойства и методи. Има три ключови думи за задаване на обхват: публичен, защитен и частен. В допълнение към задаването на обхвата, методите и свойствата могат да бъдат декларирани статични, което позволява достъп до тях без прилагане на класа.

Забележка- Обхватът е ново свойство, въведено в PHP 5. За OOP съвместимост с PHP 4 вижте ръководството за PHP.

Свойства и методи публични (Общи)

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

Методите и свойствата са защитени

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

Нека декларираме метода getProperty() като защитенив MyClass и се опитайте да получите достъп до него извън класа:

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция __toString() ( echo "Използвайте метода toString: "; върнете $this->getProperty(); ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) защитена функция getProperty( ) ( върне $this->prop1 . "

"; ) public function newMethod() ( echo "От нов метод на класа " . __CLASS__ . ".
"; ) ) // Създайте нов обект $newobj = new MyOtherClass; // Опитайте се да извикате защитения метод echo $newobj->getProperty(); ?>

Когато се опитате да изпълните скрипта, ще се генерира следната грешка:

Създаден е обект от клас "MyClass"! Нов конструктор в класа "MyOtherClass". Фатална грешка: Извикване на защитен метод MyClass::getProperty() от контекст "" в /Applications/XAMPP/xamppfiles/htdocs/testing/test.php на ред 55

Сега нека създадем нов метод в MyOtherClass за извикване на метода getProperty():

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция __toString() ( echo "Използвайте метода toString: "; върнете $this->getProperty(); ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) защитена функция getProperty( ) ( върне $this->prop1 . "
"; ) ) клас MyOtherClass разширява MyClass ( публична функция __construct() ( parent::__construct(); echo "Нов конструктор в класа " . __CLASS__ .".
"; ) public function newMethod() ( echo "От нов метод на класа " . __CLASS__ . ".
"; ) публична функция callProtected() ( return $this->getProperty(); ) ) // Създаване на нов обект $newobj = new MyOtherClass; // Извикване на защитен метод от публичен метод echo $newobj->callProtected() ; ?>

При стартиране на скрипта резултатът ще бъде така:

Създаден е обект от клас "MyClass"! Нов конструктор в класа "MyOtherClass". Свойство на клас Обектът на класа "MyClass" е изтрит.

Методи и свойства частни

Свойствата и методите, обявени за частни, са достъпни само в рамките на класа, в който са дефинирани. Означава, че дори ако новият клас е извлечен от клас, който дефинира частни свойства и методи,те няма да бъдат налични в производния клас.

За демонстрация нека декларираме метода getProperty() като частен V Моят класи нека опитаме да извикаме метода callProtected() от
MyOtherClass :

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция __toString() ( echo "Използвайте метода toString: "; върнете $this->getProperty(); ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) частна функция getProperty( ) ( върне $this->prop1 . "
"; ) ) клас MyOtherClass разширява MyClass ( публична функция __construct() ( parent::__construct(); echo "Нов конструктор в класа " . __CLASS__ .".
"; ) public function newMethod() ( echo "От нов метод на класа " . __CLASS__ . ".
"; ) публична функция callProtected() ( return $this->getProperty(); ) ) // Създаване на нов обект $newobj = new MyOtherClass; // Използване на метода от родителския клас echo $newobj->callProtected(); ?>

Запазваме скрипта, опресняваме страницата в браузъра и получаваме следното:

Създаден е обект от клас "MyClass"! Нов конструктор в класа "MyOtherClass". Фатална грешка: Извикване на частен метод MyClass::getProperty() от контекста "MyOtherClass" в /Applications/XAMPP/xamppfiles/htdocs/testing/test.php на ред 49

Статични методи и свойства (статични)

Методите и свойствата, декларирани със статична директива, могат да бъдат достъпни без иницииране на клас. Просто използвате името на класа, оператора за разрешение за видимост и името на свойството или метода.

Едно от основните предимства на статичните свойства е, че те запазват стойностите си през целия скрипт.

За да демонстрираме, нека добавим статично свойство $count и статичен метод plusOne() към класа Моят клас. След това ще настроим do...while цикъл за отпечатване на нарастващата стойност на $count, докато стане по-голяма от 10:

"; ) публична функция __destruct() ( echo "Обект на клас "", __CLASS__, "" изтрит.
"; ) публична функция __toString() ( echo "Използвайте метода toString: "; върнете $this->getProperty(); ) публична функция setProperty($newval) ( $this->prop1 = $newval; ) частна функция getProperty( ) ( върне $this->prop1 . "
"; ) публична статична функция plusOne() ( return "count = ". ++self::$count. ".
"; ) ) клас MyOtherClass разширява MyClass ( публична функция __construct() ( parent::__construct(); echo "Нов конструктор в класа " . __CLASS__ .".
"; ) public function newMethod() ( echo "От нов метод на класа " . __CLASS__ . ".
"; ) публична функция callProtected() ( return $this->getProperty(); ) ) do ( // Извикване на plusOne без иницииране на класа MyClass echo MyClass::plusOne(); ) докато (MyClass::$count< 10); ?>

Забележка- За достъп до статични свойства, знакът за долар ($) трябва идва след оператора за разрешение за видимост.

Изпълнението на скрипта в браузъра ще доведе до следния резултат:

Брой = 1. Брой = 2. Брой = 3. Брой = 4. Брой = 5. Брой = 6. Брой = 7. Брой = 8. Брой = 9. Брой = 10.

Главна информация

OOP е стил на програмиране, който се появява през 80-те години на 20 век. За разлика от процедурните езици, където данните и инструкциите за тяхната обработка съществуват отделно, в обектно-ориентираното програмиране тази информация се комбинира в едно цяло.

Основни принципи на ООП

Наследство

Вторият принцип на ООП, наследяването, е способността на един клас да използва методите на друг, без да повтаря реалната им реализация. Наследяването ви позволява да се отървете от излишъка в изходния код.

Полиморфизъм

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

ООП езици

OOP принципите се използват в най-популярните езици за програмиране като C++ и Java, в които се разработват значителна част от програмите и приложенията. Има и по-малко използвани OOP езици - Delphi, Object Pascal, Ruby и много други.

Критика към ООП

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

Първо, трудността на прехода. Ще отнеме доста време, за да разберете принципите на ООП, особено за хора, които работят тясно само с процедурни езици за програмиране.

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

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



Свързани статии: