Головна PHP Об'єктно-орієнтовне програмування і PHP 5
Об'єктно-орієнтовне програмування і PHP 5

Як відомо в програмуванні в середовищі PHP в основному використовуються такі парадигми програмування як процедурне і об'єктно-орієнтовне програмування.

Розглянемо ці парадигми детальніше:


Процедурне програмування.
Робота цієї концепції заснована на виклику так званих процедур (методи, функції, ...). Кожна процедура містить певну логіку для виконання тих чи інших операцій і може бути викликана з будь-якого місця програми.

 

 

Об'єктно-орієнтовне програмування (ООП)
В даній парадигмі основою є певний об'єкт чи сукупність об'єктів, їхні властивості, методи і події. Власне з появою ООП і з'явилися такі терміни як клас, наслідування, поліморфізм, інкапсуляція.

Якщо розглядати поняття об'єкту концептуально, то об'єкт є лише екземпляром певного класу об'єктів.

Об'єкти представляють собою часткову інформацію про певну сутність, а власне певну модель, що адекватна завданню що треба вирішити. Цей варіант представлення називається абстракція даних. При такому представленні з об'єктом працювати набагато простіше, ніж з низькорівневим представленнями з описом всіх можливих властивостей і методів.

Кожен об'єкт має свій певний тип (клас), що об'єднає в собі наступні елементи:
Властивості – певні параметри і характеристики об'єкту
Методи – дії, що можна виконувати над даним об'єктом, чи які може виконувати він сам
Події – повідомлення що виникають при зміні стану об'єкта

ООП функціонує за наступними принципами:
Наслідування – це можливість породжувати один клас від іншого, при чому всі методи і властивості батьківського класу передаються дочірньому, дочірній клас в свою чергу може набувати нових методів і властивостей, яких не було в батьківському і також передавати їх в похідні від себе класи.
Поліморфізм – це можливість дочірнього класу змінювати реалізацію тих чи інших дій батьківського класу.
Інкапсуляція – це властивість об'єкта мати спеціальний інтерфейс (певний метод), через який і здійснюється взаємодія зовнішнього середовища з внутрішніми методами класу. При чому зовнішнє середовище може і не підозрювати про структуру і логіку внутрішніх методів.

Якщо розглядати практичне застосування парадигм програмування стосовно PHP, то в попередніх до PHP 5 версіях використовується в основному процедурне програмування, так як об'єктна схема там вимальована достатньо умовно (тільки для виділення окремих сутностей, їх методів і властивостей в певні класи). Вже в 5-й версії PHP механізм взаємодії з об'єктами зазнав еволюційних змін.

Вказівники (ссилки) і клонування
Одною з базових змін є передача об'єкту як параметр функції по вказівнику а не по значенню, тобто всі функції, яким параметром передався об'єкт, працюють з одним і тим самим об'єктом, а не з його копіями. Це дозволяє уникати появи дублікатів об'єктів. Похідною від цього нововведення є вища продуктивність при обробці сценаріїв де активно використовуються об'єкти.

Для створення копії об'єкта в PHP 5 використовується спеціальний метод __clone().
До цього методу неможна звернутись безпосередньо. Для безпосереднього використання використовується ключове слово clone.

Розглянемо приклад використання цього методу в PHP 5:

class SomeClass{
var $name;
}

// створюємо клас someObj1 і присвоюємо властивісті "name" значення "Object 1"
$someObj1 = new SomeClass;
$someObj1->name = 'Object 1';

// копіюємо клас someObj1 в someObj2
$someObj2 = clone $someObj1;

echo $someObj1->name; // Виводить "Object 1"
echo $someObj2->name; // Виводить "Object 1"

// присвоюємо властивісті класу someObj2 "name" значення "Object 2"
$someObj2->name = 'Object 2';

echo $someObj1->name; // Виводить "Object 1"
echo $someObj2->name; // Виводить "Object 2"

 

В PHP 4 для копіювання об'єкту замість $someObj2 = clone $someObj1 треба було б використати $someObj2 = $someObj1.

На перший погляд все зручніше виглядало в PHP 4, але не будемо поспішати з висновками. Метод __clone() не обов'язково описувати (перезавантажувати) в класі. Але якщо ми це зробимо, то зможемо наперед задати поведінку об'єкта під час його клонування.

Приклад:

class SomeClass{
var $name;

 

// перезавантаження методу __clone()
function __clone() {
$this->name = 'Copy';
}
}

// створюємо клас someObj1 і присвоюємо властивісті "name" значення "Original"
$someObj1 = new SomeClass;
$someObj1->name = 'Original';

// створюємо клас someObj2
// автоматично властивості "name" присвоюється значення "Copy"
$someObj2 = clone $someObj1;

echo $someObj1->name; // Виводить "Original"
echo $someObj2->name; // Виводить "Copy"


Області видимості методів і властивостей класів
В PHP 5 введені специфікатори доступу до методів і властивостей класів:
public – доступний без обмежень
protected – тільки в середині класу, в якому вони оголошені і похідних від нього класах
private – тільки в середині класу, в якому вони оголошені

По замовчуванню виставляється тип доступу public.

Розглянемо приклад з методами і властивостями різних типів доступності.

// оголошуємо основний клас
class SomeClass{
private $privateName = 'Private Name';
protected $protectedName = 'Protected Name';
public $publicName = 'Public Name';

 

private function PrivateFunction() {
echo 'PrivateFunction()';
}

protected function ProtectedFunction() {
echo 'ProtectedFunction()';
}

public function PublicFunction() {
echo 'PublicFunction()';
}

public function GetPrivate() {
echo $this->privateName;
}

public function GetProtected() {
echo $this->protectedName;
}

public function GetPublic() {
echo $this->publicName;
}
}

// оголошуємо похідний клас від SomeClass
class SomeClass1 extends SomeClass {
public function GetPrivateFromParent() {
echo $this->privateName;
}
}

$someObj1 = new SomeClass;
$someObj2 = new SomeClass1;

// Доступ до private методів і властивостей
echo $someObj1->privateName; // Виводить помилку
echo $someObj2->privateName; // Виводить помилку
$someObj1->PrivateFunction(); // Виводить помилку
$someObj2->PrivateFunction(); // Виводить помилку
$someObj1->GetPrivate(); // Виводится 'Private Name'
$someObj2->GetPrivate(); // Виводится 'Private Name'*/
$someObj2->GetPrivateFromParent(); // Нічого не виводиться

// Доступ до protected методів і властивостей
echo $someObj1->protectedName; // Виводить помилку
echo $someObj2->protectedName; // Виводить помилку
$someObj1->ProtectedFunction(); // Виводить помилку
$someObj2->ProtectedFunction(); // Виводить помилку
$someObj1->GetProtected(); // Виводится 'Protected Name'
$someObj2->GetProtected(); // Виводится 'Protected Name'

// Доступ до public методів і властивостей
echo $someObj1->publicName; // Виводиться 'Public Name'
echo $someObj2->publicName; // Виводиться 'Public Name'
$someObj1->PublicFunction(); // Виводиться 'PublicFunction()'
$someObj2->PublicFunction(); // Виводиться 'PublicFunction()'
$someObj1->GetPublic(); // Виводиться 'Public Name'
$someObj2->GetPublic(); // Виводиться 'Public Name'
?>

Є ще також статичні (static) методи і властивості. Їхньою особливістю є те, що вони не належать певному об'єктові, вони єдині для цілого класу, і можуть викликатися без створення об'єкту. Зміна статичної властивості в одному з об'єктів класу призводить до його зміни для всіх об'єктів цього класу.

Приклад:

// оголошуємо основний клас
class SomeClass{
static $staticVar = 'Static Variable';

 

static function StaticFunction() {
echo 'StaticFunction()';
}
}

echo SomeClass::StaticFunction(); // Виводить StaticFunction()
echo SomeClass::$staticVar; // Виводить Static Variable

Константи класу
При описі класу в PHP 5 можна задавати властивості-константи (ключове слово const). Викликати константи можна і без створення об'єкту на основі класу, в якому оголошені константи.

Приклад:

class SomeClass {
const SOME_CONSTANT = "SOME CONSTANT";
}

 

echo SomeClass::SOME_CONSTANT; // Виводить "SOME CONSTANT"

 

Конструктори и деструктори
Конструктор (__construct()) і деструктор (__destruct()) це методи що викликаються автоматично при створенні і знищенні об'єкту відповідно:

 

class SomeClass{
function __construct() {
echo 'Create object';
}

function __destruct() {
echo 'Destroy object';
}
}

$someObj = new SomeClass; // Виводиться Create object
unset($someObj); // Виводиться Destroy object

 

Абстрактні методи і класи.
Абстрактні (abstract) методи і класи тільки оголошуються, клас який містить абстрактні методи повинен оголоситися як абстрактний. На основі абстрактного класу можна тільки створювати інші класи, а вже від них об'єкти. Абстрактний клас може містити і звичайні (не абстрактні) елементи.

Приклад:

abstract class SomeAbstractClass {
// оголошення абстрактної функції
abstract public function abstractFunction();

 

// оголошення неабстрактної функції
public function GeneralFunction() {

}
}

class SomeClass extends SomeAbstractClass {
// перевантаження абстрактного методу
public function abstractFunction() {
echo 'abstractFunction()';
}
}

$someObj = new SomeAbstractClass; // Помилка створення об'єкта
$someObj1 = new SomeClass;
$someObj1->abstrFunc(); // Виводить 'abstractFunction()'


Інтерфейси
В PHP 5 немає множинного наслідування, тобто один клас не може бути створений на основі кількох інших класів. Але клас може бути створений на основі кількох інтерфейсів. Інтерфейс – це фактично абстрактний клас, який містить тільки абстрактні методи і не містить ніяких властивостей.

Оголошуються інтерфейси з використанням ключового слова interface, а всі функції оголошуються стандартно, з використанням ключового слова function.

Приклад:

// оголошення інтерфейсів
interface InterfaceOne {
function SomeFunctionOne();
}

 

interface InterfaceTwo {
function SomeFunctionTwo();
}

// оголошення класу на основі інтерфейсів
class SomeClass implements InterfaceOne, InterfaceTwo {
public function SomeFunctionOne() {
echo 'SomeFunctionOne()';
}
public function SomeFunctionTwo() {
echo 'SomeFunctionTwo()';
}
}

$object = new SomeClass;
$object->SomeFunctionOne(); // Виводить 'SomeFunctionOne()'
$object->SomeFunctionTwo(); // Виводить 'SomeFunctionTwo()'


Фінальні методи і класи
В PHP 5 є можливість задати таку властивість класу і методу як фінальний (final). На основі фінальних класів неможливо створити класи нащадки. Також не можна перевизначити фінальний метод в класах нащадках.

Приклад:

final class FinalClass {

 

}

class ClassWithFinalMethod {
final public function FinalFunction() {
echo 'FinalFunction()';
}
}

// наступне оголошення класу викликає помилку
class SomeClass1 extends FinalClass {
// опис класу
}

// створюємо клас на основі класу з фінальним методом
class SomeClass1 extends ClassWithFinalMethod {
// наступне перевизначення методі викликає помилку
public function FinalFunction() {
}
}

Обробка винятків (помилок)
Найцікавішим нововведенням в PHP 5 є методи для обробки винятків. Для цього використовуються конструкції try/catch/throw.

Розглянемо простий приклад використання цих методів:

try {
// відкриваємо файл для читання
$fp = @fopen("somefile.txt", "r");
// якщо файл відсутній, створюємо виключення
if (!$someFile)
throw new Exception(" Помилка відкриття файлу!");

 

fclose($someFile);
} catch (Exception $exception) {
// метод $exception->getLine() повертає номер рядка даного скрипта, в якому виникла помилка
echo "Помилка в стрічці ", $exception->getLine();
echo $exception->getMessage(); // Выводит "Помилка відкриття файлу!"
}

 

Ключове слово instanceof
Метод instanceof дозволяє визначити походження об'єкта, його приналежність до певного класу, або чи є він нащадком якогось об'єкта. Також за допомогою instanceof можна визначити чи об'єкт екземпляром класу, створеного на основі певного інтерфейсу.

Приклад:

interface SomeInterfaceOne { }
interface SomeInterfaceTwo { }
class SomeClassTypeOne { }
class SomeClassTypeTwo extends SomeClassTypeOne {}
class SomeClassTypeThree implements SomeInterfaceOne, SomeInterfaceTwo {}

 

$objOne = new SomeClassTypeOne;
$objTwo = new SomeClassTypeTwo;
$objThree = new SomeClassTypeThree;
$clonedObj = clone $objThree;

// наступний блок виводить: об'єкт $objOne належить до класу SomeClassTypeOne
if($objOne instanceof SomeClassTypeOne)
echo 'об\'єкт $objOne належить до класу SomeClassTypeOne';

// наступний блок виводить: об'єкт $objTwo належить до класу SomeClassTypeTwo
if($objTwo instanceof SomeClassTypeTwo)
echo 'об\'єкт $objTwo належить до класу SomeClassTypeTwo';

// наступний блок виводить: об'єкт $objThree належить до класу SomeClassTypeThree
if($objThree instanceof SomeClassTypeThree)
echo 'об\'єкт $objThree належить до класу SomeClassTypeThree';

// наступний блок виводить: об'єкт $objTwo є екземпляром класу створеного на основі класу SomeClassTypeOne
if($objTwo instanceof SomeClassTypeOne)
echo 'об\'єкт $objTwo є екземпляром класу створеного на основі класу SomeClassTypeOne';

// наступний блок виводить: об'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceOne
if($objThree instanceof SomeInterfaceOne)
echo 'об\'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceOne';

// наступний блок виводить: об'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceTwo
if($objThree instanceof SomeInterfaceTwo)
echo 'об\'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceTwo';

// наступний блок виводить: об'єкта $clonedObj створений на основі об'єкту $objThree
if($clonedObj instanceof $objThree)
echo 'об\'єкта $clonedObj створений на основі об\'єкту $objThree';

 

Функція __autoload()
Функція __autoload() викликається в випадку коли створюється об'єкт на основі неіснуючого класу

Приклад:

function __autoload($class) {
echo "спроба створити об'єкт невизначеного класу ", $class;
}

 

// наступна стрічка виводить:
// спроба створити об'єкт невизначеного класу MyClass
// Fatal error: Class 'MyClass' not found in C:\wamp\www\test.php on line 5
$someObj = new SomeWrongClass;

// наступна стрічка трохи практичніша
// (екрануємо створення об'єту символом "@")
// вона виводить:
// спроба створити об'єкт невизначеного класу MyClass
$someObj = @new SomeWrongClass;

Перевантаження доступу до властивостей об'єкту
Методи доступу __get() і __set() дозволяють динамічно визначати властивості об'єктів. __get() в якості параметра отримує ім'я властивості, а __set() окрім імені ще і нове значення властивості, яке відповідно і присвоює.

Приклад:

class SomeClass {
private $classPropertys;
function __set($name, $value) {
echo "__set: присвоювання властивості $name = $value";
$this->classPropertys[$name]=$value;
}

 

function __get($name) {
echo "__get: читання властивості $name: ";
echo $this->classPropertys[$name];
}
}

$obj = new SomeClass;
$obj->name = 'New Value'; // Виводить "__set: присвоювання властивості name=New Value"
$value = $obj->name; // Виводить "__get: читання властивості name: New Value"

 

Перевантаження викликів методів класу
Якщо метод __call() описаний в певному класі, тоді він автоматично переловлює виклики до неіснуючих методів цього класу. В якості параметрів він отримує ім'я і параметри методу що викликається.

Приклад:

class SomeClass {
function __call($name, $params) {
echo "Помилка: викликано неіснуючий метод $name з параметром[ами]: ";
foreach($params as $val) {
echo $val.' | ';
}
}
}

 

$obj = new SomeClass;
$obj->WrongMethodOne(1, 2, 'param'); // Виводить: 'Помилка: викликано неіснуючий метод WrongMethodOne з параметром[ами]: 1 | 2 | param |'
$obj->WrongMethodTwo(123); // Виводить: 'Помилка: викликано неіснуючий метод WrongMethodOne з параметром[ами]: 123 |'

 

Додати коментар


Захисний код
Оновити

© 2008-2013 PHPist