Відмінності між версіями «ООП в PHP»

Матеріал з Вікі ЦДУ
Перейти до: навігація, пошук
м
 
(не показані 8 проміжних версій ще одного учасника)
Рядок 1: Рядок 1:
В програмуванні на PHP в основному використовуються такі парадигми програмування як '''процедурне''' і '''об'єктно-орієнтоване''' програмування.
+
В програмуванні на '''PHP''' в основному використовуються такі парадигми програмування як '''процедурне''' і '''об'єктно-орієнтоване''' програмування.
  
''Розглянемо ці парадигми детальніше:''
+
''Розглянемо ці парадигми детальніше.''
  
 
== '''Процедурне програмування.''' ==
 
== '''Процедурне програмування.''' ==
Рядок 24: Рядок 24:
 
'''ООП функціонує за наступними принципами:'''
 
'''ООП функціонує за наступними принципами:'''
  
   1. '''Наслідування''' – це можливість породжувати один клас від іншого, при чому всі методи і властивості батьківського класу передаються дочірньому, дочірній клас в свою чергу може набувати нових методів і властивостей, яких не було в батьківському і також передавати їх в похідні від себе класи.
+
   1. '''Наслідування''' – це можливість породжувати один клас від іншого, при чому всі методи і властивості батьківського класу
 +
                передаються дочірньому, дочірній клас в свою чергу може набувати нових методів і властивостей,
 +
                яких не було в батьківському і також передавати їх в похідні від себе класи.
 
   2. '''Поліморфізм''' – це можливість дочірнього класу змінювати реалізацію тих чи інших дій батьківського класу.
 
   2. '''Поліморфізм''' – це можливість дочірнього класу змінювати реалізацію тих чи інших дій батьківського класу.
   3. '''Інкапсуляція''' – це властивість об'єкта мати спеціальний інтерфейс (певний метод), через який і здійснюється взаємодія зовнішнього середовища з внутрішніми методами класу. При чому зовнішнє середовище може і не підозрювати про структуру і логіку  внутрішніх методів.
+
   3. '''Інкапсуляція''' – це властивість об'єкта мати спеціальний інтерфейс (певний метод), через який і здійснюється
 +
                взаємодія зовнішнього середовища з внутрішніми методами класу. При чому зовнішнє середовище може і не
 +
                підозрювати про структуру і логіку  внутрішніх методів.
  
Якщо розглядати практичне застосування парадигм програмування стосовно PHP, то в попередніх до PHP 5 версіях використовується в основному процедурне програмування, так як об'єктна схема там вимальована достатньо умовно (тільки для виділення окремих сутностей, їх методів і властивостей в певні класи). Вже в 5-й версії PHP механізм взаємодії з об'єктами зазнав еволюційних змін.
+
Якщо розглядати практичне застосування парадигм програмування стосовно '''PHP''', то в попередніх до '''PHP 5''' версіях використовується в основному процедурне програмування, так як об'єктна схема там вимальована достатньо умовно (тільки для виділення окремих сутностей, їх методів і властивостей в певні класи). Вже в '''5-й''' версії '''PHP''' механізм взаємодії з об'єктами зазнав еволюційних змін.
  
'''Вказівники і клонування.'''
 
  
Одною з базових змін є передача об'єкту як параметр функції по вказівнику а не по значенню, тобто всі функції, яким параметром передався об'єкт, працюють з одним і тим самим об'єктом, а не з його копіями. Це дозволяє уникати появи дублікатів об'єктів. Похідною від цього нововведення є вища продуктивність при обробці сценаріїв де активно використовуються об'єкти.
+
== Області видимості методів і властивостей класів. ==
  
Для створення копії об'єкта в PHP 5 використовується спеціальний метод ''__clone()''.
+
В '''PHP 5''' введені специфікатори доступу до методів і властивостей класів:
До цього методу неможна звернутись безпосередньо. Для безпосереднього використання використовується ключове слово ''clone''.
+
 
+
Розглянемо приклад використання цього методу в PHP 5:
+
    <?php
+
    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() не обов'язково описувати (перезавантажувати) в класі. Але якщо ми це зробимо, то зможемо  наперед задати поведінку об'єкта під час його клонування.
+
 
+
Приклад:
+
    <?php
+
    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''' – доступний без обмежень
 
     * '''public''' – доступний без обмежень
Рядок 102: Рядок 48:
 
Розглянемо приклад з методами і властивостями різних типів доступності.
 
Розглянемо приклад з методами і властивостями різних типів доступності.
  
 +
<syntaxhighlight lang="php">
 
     <?php
 
     <?php
 
         // оголошуємо основний клас
 
         // оголошуємо основний клас
Рядок 140: Рядок 87:
 
     }
 
     }
 
     }
 
     }
 
  
 
         // оголошуємо похідний клас від SomeClass
 
         // оголошуємо похідний клас від SomeClass
Рядок 179: Рядок 125:
 
     $someObj2->GetPublic(); // Виводиться 'Public Name'
 
     $someObj2->GetPublic(); // Виводиться 'Public Name'
 
     ?>
 
     ?>
 +
</syntaxhighlight>
  
 
Є ще також статичні (''static'') методи і властивості. Їхньою особливістю є те, що вони не належать певному об'єктові, вони єдині для цілого класу, і можуть викликатися без створення об'єкту. Зміна статичної властивості в одному з об'єктів класу призводить до його зміни для всіх об'єктів цього класу.
 
Є ще також статичні (''static'') методи і властивості. Їхньою особливістю є те, що вони не належать певному об'єктові, вони єдині для цілого класу, і можуть викликатися без створення об'єкту. Зміна статичної властивості в одному з об'єктів класу призводить до його зміни для всіх об'єктів цього класу.
Рядок 184: Рядок 131:
 
Приклад:
 
Приклад:
  
 +
<syntaxhighlight lang="php">
 
     <?php
 
     <?php
 
       // оголошуємо основний клас
 
       // оголошуємо основний клас
Рядок 198: Рядок 146:
 
     echo SomeClass::$staticVar; // Виводить Static Variable
 
     echo SomeClass::$staticVar; // Виводить Static Variable
 
     ?>
 
     ?>
 +
</syntaxhighlight>
  
 +
== Константи класу ==
  
'''Константи класу'''
+
При описі класу в '''PHP 5''' можна задавати властивості-константи (ключове слово '''const'''). Викликати константи можна і без створення об'єкту на основі класу, в якому оголошені константи.
При описі класу в PHP 5 можна задавати властивості-константи (ключове слово '''const'''). Викликати константи можна і без створення об'єкту на основі класу, в якому оголошені константи.
+
  
 
Приклад:
 
Приклад:
  
 +
<syntaxhighlight lang="php">
 
     <?php
 
     <?php
 
     class SomeClass
 
     class SomeClass
Рядок 212: Рядок 162:
 
     echo SomeClass::SOME_CONSTANT; // Виводить "SOME CONSTANT"
 
     echo SomeClass::SOME_CONSTANT; // Виводить "SOME CONSTANT"
 
     ?>
 
     ?>
 +
</syntaxhighlight>
  
 
+
== Конструктори и деструктори. ==
'''Конструктори и деструктори.'''
+
  
  
 
Конструктор ('''__construct()''') і деструктор ('''__destruct()''') це методи що викликаються автоматично при створенні і знищенні об'єкту відповідно:
 
Конструктор ('''__construct()''') і деструктор ('''__destruct()''') це методи що викликаються автоматично при створенні і знищенні об'єкту відповідно:
  
<?php
+
<syntaxhighlight lang="php">
class SomeClass{
+
    <?php
  function __construct() {
+
    class SomeClass
    echo 'Create object';
+
    {
  }
+
        function __construct()
 +
        {
 +
            echo 'Create object';
 +
        }
 
   
 
   
  function __destruct() {
+
        function __destruct()
    echo 'Destroy object';
+
        {
  }
+
            echo 'Destroy object';
}
+
        }
 +
    }
 +
    $someObj = new SomeClass; // Виводиться Create object
 +
    unset($someObj); // Виводиться Destroy object
 +
    ?>
 +
</syntaxhighlight>
  
$someObj = new SomeClass; // Виводиться Create object
+
== Абстрактні методи і класи. ==
unset($someObj); // Виводиться Destroy object
+
 
?>
+
Абстрактні (''abstract'') методи і класи тільки оголошуються, клас який містить абстрактні методи повинен оголоситися як абстрактний. На основі абстрактного класу можна тільки створювати інші класи, а вже від них об'єкти. Абстрактний клас може містити і звичайні (не абстрактні) елементи.
Абстрактні методи і класи.
+
Абстрактні (abstract) методи і класи тільки оголошуються, клас який містить абстрактні методи повинен оголоситися як абстрактний. На основі абстрактного класу можна тільки створювати інші класи, а вже від них об'єкти. Абстрактний клас може містити і звичайні (не абстрактні) елементи.
+
  
 
Приклад:
 
Приклад:
<?php
+
 
abstract class SomeAbstractClass {
+
<syntaxhighlight lang="php">
  // оголошення абстрактної функції
+
    <?php
  abstract public function abstractFunction();
+
    abstract class SomeAbstractClass
+
    {
  // оголошення неабстрактної функції
+
        // оголошення абстрактної функції
  public function GeneralFunction() {
+
        abstract public function abstractFunction();
 +
        // оголошення неабстрактної функції
 +
        public function GeneralFunction()
 +
        {
 
   
 
   
  }
+
        }
}
+
    }
  
class SomeClass extends SomeAbstractClass {
+
    class SomeClass extends SomeAbstractClass
  // перевантаження абстрактного методу
+
    {
  public function abstractFunction() {
+
        // перевантаження абстрактного методу
    echo 'abstractFunction()';
+
        public function abstractFunction()
  }
+
        {
}
+
            echo 'abstractFunction()';
 +
        }
 +
    }
 +
    $someObj = new SomeAbstractClass; // Помилка створення об'єкта
 +
    $someObj1 = new SomeClass;
 +
    $someObj1->abstrFunc(); // Виводить 'abstractFunction()'
 +
    ?>
 +
</syntaxhighlight>
  
$someObj = new SomeAbstractClass; // Помилка створення об'єкта
+
== Інтерфейси. ==
$someObj1 = new SomeClass;
+
$someObj1->abstrFunc(); // Виводить 'abstractFunction()'
+
?>
+
Інтерфейси.
+
В PHP 5 немає множинного наслідування, тобто один клас не може бути створений на основі кількох інших класів. Але клас може бути створений на основі кількох інтерфейсів. Інтерфейс – це фактично абстрактний клас, який містить тільки абстрактні методи і не містить ніяких властивостей.
+
  
Оголошуються інтерфейси з використанням ключового слова interface, а всі функції оголошуються стандартно, з використанням ключового слова function.
+
В '''PHP 5''' немає множинного наслідування, тобто один клас не може бути створений на основі кількох інших класів. Але клас може бути створений на основі кількох інтерфейсів. Інтерфейс – це фактично абстрактний клас, який містить тільки абстрактні методи і не містить ніяких властивостей.
 +
 
 +
Оголошуються інтерфейси з використанням ключового слова ''interface'', а всі функції оголошуються стандартно, з використанням ключового слова ''function''.
  
 
Приклад:
 
Приклад:
<?php
 
// оголошення інтерфейсів
 
interface InterfaceOne {
 
  function SomeFunctionOne();
 
}
 
  
interface InterfaceTwo {
+
<syntaxhighlight lang="php">
  function SomeFunctionTwo();
+
    <?php
}
+
    // оголошення інтерфейсів
 +
    interface InterfaceOne
 +
    {
 +
        function SomeFunctionOne();
 +
    }
  
// оголошення класу на основі інтерфейсів
+
    interface InterfaceTwo
class SomeClass implements InterfaceOne, InterfaceTwo {
+
    {
  public function SomeFunctionOne() {
+
        function SomeFunctionTwo();
    echo 'SomeFunctionOne()';
+
     }
  }
+
  public function SomeFunctionTwo() {
+
     echo 'SomeFunctionTwo()';
+
  }
+
}
+
  
$object = new SomeClass;
+
    // оголошення класу на основі інтерфейсів
$object->SomeFunctionOne(); // Виводить 'SomeFunctionOne()'
+
    class SomeClass implements InterfaceOne, InterfaceTwo
$object->SomeFunctionTwo(); // Виводить 'SomeFunctionTwo()'
+
    {
?>
+
        public function SomeFunctionOne()
Фінальні методи і класи.
+
        {
В PHP 5 є можливість задати таку властивість класу і методу як фінальний (final). На основі фінальних класів неможливо створити класи нащадки. Також не можна перевизначити фінальний метод в класах нащадках.
+
            echo 'SomeFunctionOne()';
 +
        }
 +
        public function SomeFunctionTwo()
 +
        {
 +
            echo 'SomeFunctionTwo()';
 +
        }
 +
    }
 +
    $object = new SomeClass;
 +
    $object->SomeFunctionOne(); // Виводить 'SomeFunctionOne()'
 +
    $object->SomeFunctionTwo(); // Виводить 'SomeFunctionTwo()'
 +
    ?>
 +
</syntaxhighlight>
 +
 
 +
== Фінальні методи і класи. ==
 +
 
 +
В '''PHP 5''' є можливість задати таку властивість класу і методу як фінальний (final). На основі фінальних класів неможливо створити класи нащадки. Також не можна перевизначити фінальний метод в класах нащадках.
  
 
Приклад:
 
Приклад:
<?php
+
 
final class FinalClass {
+
<syntaxhighlight lang="php">
 +
    <?php
 +
    final class FinalClass
 +
    {
 
   
 
   
}
+
    }
  
class ClassWithFinalMethod {
+
    class ClassWithFinalMethod
  final public function FinalFunction() {
+
    {
    echo 'FinalFunction()';
+
        final public function FinalFunction()
  }
+
        {
}
+
            echo 'FinalFunction()';
 +
        }
 +
    }
  
// наступне оголошення класу викликає помилку
+
    // наступне оголошення класу викликає помилку
class SomeClass1 extends FinalClass {
+
    class SomeClass1 extends FinalClass
  // опис класу
+
    {
}
+
        // опис класу
 +
    }
  
// створюємо клас на основі класу з фінальним методом
+
    // створюємо клас на основі класу з фінальним методом
class SomeClass1 extends ClassWithFinalMethod {
+
    class SomeClass1 extends ClassWithFinalMethod
  // наступне перевизначення методі викликає помилку
+
    {
  public function FinalFunction() {
+
    // наступне перевизначення методі викликає помилку
  }
+
        public function FinalFunction()
}
+
        {
?>
+
        }
Обробка винятків (помилок).
+
    }
Найцікавішим нововведенням в PHP 5 є  методи для обробки винятків. Для цього використовуються конструкції  try/catch/throw.
+
    ?>
 +
</syntaxhighlight>
 +
 
 +
== Обробка винятків (помилок). ==
 +
 
 +
Найцікавішим нововведенням в '''PHP 5''' є  методи для обробки винятків. Для цього використовуються конструкції  try/catch/throw.
  
 
Розглянемо простий приклад використання цих методів:
 
Розглянемо простий приклад використання цих методів:
<?php
+
 
  try {
+
<syntaxhighlight lang="php">
    // відкриваємо файл для читання
+
    <?php
    $fp = @fopen("somefile.txt", "r");
+
    try {
      // якщо файл відсутній, створюємо виключення
+
            // відкриваємо файл для читання
      if (!$someFile)
+
            $fp = @fopen("somefile.txt", "r");
        throw new Exception(" Помилка відкриття файлу!");
+
            // якщо файл відсутній, створюємо виключення
 +
            if (!$someFile)
 +
                throw new Exception(" Помилка відкриття файлу!");
 
        
 
        
      fclose($someFile);
+
            fclose($someFile);
  } catch (Exception $exception) {
+
        }
      // метод $exception->getLine() повертає номер рядка даного скрипта, в якому виникла помилка
+
        catch
      echo "Помилка в стрічці ", $exception->getLine();
+
        (Exception $exception)
      echo $exception->getMessage(); // Выводит "Помилка відкриття файлу!"
+
        {
  }
+
            // метод $exception->getLine() повертає номер рядка даного скрипта, в якому виникла помилка
?>
+
            echo "Помилка в рядку ", $exception->getLine();
Ключове слово instanceof.
+
            echo $exception->getMessage(); // Выводит "Помилка відкриття файлу!"
Метод instanceof дозволяє визначити походження об'єкта, його приналежність до певного класу, або чи є він нащадком якогось об'єкта. Також за допомогою  instanceof можна визначити чи об'єкт екземпляром класу, створеного на основі певного інтерфейсу.
+
        }
 +
    ?>
 +
</syntaxhighlight>
 +
 
 +
Ключове слово ''instanceof''.
 +
Метод ''instanceof'' дозволяє визначити походження об'єкта, його приналежність до певного класу, або чи є він нащадком якогось об'єкта. Також за допомогою  instanceof можна визначити чи об'єкт екземпляром класу, створеного на основі певного інтерфейсу.
  
 
Приклад:
 
Приклад:
<?php
+
 
  interface SomeInterfaceOne { }
+
<syntaxhighlight lang="php">
  interface SomeInterfaceTwo { }
+
    <?php
  class SomeClassTypeOne { }
+
    interface SomeInterfaceOne { }
  class SomeClassTypeTwo extends SomeClassTypeOne {}
+
    interface SomeInterfaceTwo { }
  class SomeClassTypeThree implements SomeInterfaceOne, SomeInterfaceTwo {}
+
    class SomeClassTypeOne { }
 +
    class SomeClassTypeTwo extends SomeClassTypeOne {}
 +
    class SomeClassTypeThree implements SomeInterfaceOne, SomeInterfaceTwo {}
 
   
 
   
  $objOne = new SomeClassTypeOne;
+
    $objOne = new SomeClassTypeOne;
  $objTwo = new SomeClassTypeTwo;
+
    $objTwo = new SomeClassTypeTwo;
  $objThree = new SomeClassTypeThree;
+
    $objThree = new SomeClassTypeThree;
  $clonedObj = clone $objThree;
+
    $clonedObj = clone $objThree;
  
  // наступний блок виводить: об'єкт $objOne належить до класу SomeClassTypeOne
+
    // наступний блок виводить: об'єкт $objOne належить до класу SomeClassTypeOne
  if($objOne instanceof SomeClassTypeOne)
+
    if($objOne instanceof SomeClassTypeOne)
    echo 'об\'єкт $objOne належить до класу SomeClassTypeOne';
+
        echo 'об\'єкт $objOne належить до класу SomeClassTypeOne';
 
   
 
   
  // наступний блок виводить: об'єкт $objTwo належить до класу SomeClassTypeTwo
+
    // наступний блок виводить: об'єкт $objTwo належить до класу SomeClassTypeTwo
  if($objTwo instanceof SomeClassTypeTwo)
+
    if($objTwo instanceof SomeClassTypeTwo)
    echo 'об\'єкт $objTwo належить до класу SomeClassTypeTwo';
+
        echo 'об\'єкт $objTwo належить до класу SomeClassTypeTwo';
 
   
 
   
  // наступний блок виводить: об'єкт $objThree належить до класу SomeClassTypeThree
+
    // наступний блок виводить: об'єкт $objThree належить до класу SomeClassTypeThree
  if($objThree instanceof SomeClassTypeThree)
+
    if($objThree instanceof SomeClassTypeThree)
    echo 'об\'єкт $objThree належить до класу SomeClassTypeThree';
+
        echo 'об\'єкт $objThree належить до класу SomeClassTypeThree';
 
   
 
   
  // наступний блок виводить: об'єкт $objTwo є екземпляром класу створеного на основі класу SomeClassTypeOne
+
    // наступний блок виводить: об'єкт $objTwo є екземпляром класу створеного на основі класу SomeClassTypeOne
  if($objTwo instanceof SomeClassTypeOne)
+
    if($objTwo instanceof SomeClassTypeOne)
    echo 'об\'єкт $objTwo є екземпляром класу створеного на основі класу SomeClassTypeOne';
+
        echo 'об\'єкт $objTwo є екземпляром класу створеного на основі класу SomeClassTypeOne';
 
   
 
   
  // наступний блок виводить: об'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceOne
+
    // наступний блок виводить: об'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceOne
  if($objThree instanceof SomeInterfaceOne)
+
    if($objThree instanceof SomeInterfaceOne)
    echo 'об\'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceOne';
+
        echo 'об\'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceOne';
 
   
 
   
  // наступний блок виводить: об'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceTwo   
+
    // наступний блок виводить: об'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceTwo   
  if($objThree instanceof SomeInterfaceTwo)
+
    if($objThree instanceof SomeInterfaceTwo)
    echo 'об\'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceTwo';
+
        echo 'об\'єкт $objThree є екземпляром класу створеного на основі інтерфейсу SomeInterfaceTwo';
 
   
 
   
  // наступний блок виводить: об'єкта $clonedObj створений на основі об'єкту $objThree   
+
    // наступний блок виводить: об'єкта $clonedObj створений на основі об'єкту $objThree   
  if($clonedObj instanceof $objThree)
+
    if($clonedObj instanceof $objThree)
    echo 'об\'єкта $clonedObj створений на основі об\'єкту $objThree';
+
        echo 'об\'єкта $clonedObj створений на основі об\'єкту $objThree';
?>
+
        ?>
Функція __autoload()
+
</syntaxhighlight>
Функція __autoload() викликається в випадку коли створюється об'єкт на основі неіснуючого класу
+
 
 +
== Функція __autoload() ==
 +
 
 +
Функція ''__autoload()'' викликається в випадку коли створюється об'єкт на основі неіснуючого або неописаного в даному конкретному файлі з кодом класу
  
 
Приклад:
 
Приклад:
<?php
+
 
  function __autoload($class) {
+
<syntaxhighlight lang="php">
     echo "спроба створити об'єкт невизначеного класу ", $class;
+
    <?php
  }
+
    function __autoload($class)
 +
     {
 +
        echo "спроба створити об'єкт невизначеного класу ", $class;
 +
    }
 
   
 
   
  // наступна стрічка виводить:
+
    // спроба створити об'єкт невизначеного класу MyClass
  // спроба створити об'єкт невизначеного класу MyClass
+
    // Fatal error: Class 'MyClass' not found in C:\wamp\www\test.php on line 5
  // Fatal error: Class 'MyClass' not found in C:\wamp\www\test.php on line 5
+
    $someObj = new SomeWrongClass;
  $someObj = new SomeWrongClass;
+
 
   
 
   
  // наступна стрічка трохи практичніша
+
    // наступна стрічка трохи практичніша
  // (екрануємо створення об'єту символом "@")
+
    // (екрануємо створення об'єту символом "@")
  // вона виводить:
+
    // вона виводить:
  // спроба створити об'єкт невизначеного класу MyClass
+
    // спроба створити об'єкт невизначеного класу MyClass
  $someObj = @new SomeWrongClass;
+
    $someObj = @new SomeWrongClass;
?>
+
    ?>
Перевантаження доступу до властивостей об'єкту.
+
</syntaxhighlight>
Методи доступу __get() і __set() дозволяють динамічно визначати властивості об'єктів. __get() в якості параметра отримує ім'я властивості, а  __set() окрім імені ще і нове значення властивості, яке відповідно і присвоює.
+
 
 +
== Перевантаження доступу до властивостей об'єкту. ==
 +
 
 +
Методи доступу ''__get()'' і ''__set()'' дозволяють динамічно визначати властивості об'єктів. ''__get()'' в якості параметра отримує ім'я властивості, а  ''__set()'' окрім імені ще і нове значення властивості, яке відповідно і присвоює.
  
 
Приклад:
 
Приклад:
<?php
+
 
  class SomeClass {
+
<syntaxhighlight lang="php">
     private $classPropertys;
+
    <?php
    function __set($name, $value) {
+
    class SomeClass
      echo "__set: присвоювання властивості $name = $value";
+
     {
      $this->classPropertys[$name]=$value;
+
        private $classPropertys;
    }
+
        function __set($name, $value)
 +
        {
 +
            echo "__set: присвоювання властивості $name = $value";
 +
            $this->classPropertys[$name]=$value;
 +
        }
 
    
 
    
    function __get($name) {
+
        function __get($name)
      echo "__get: читання властивості $name: ";
+
        {
      echo $this->classPropertys[$name];
+
            echo "__get: читання властивості $name: ";
 +
            echo $this->classPropertys[$name];
 +
        }
 
     }
 
     }
  }
 
 
   
 
   
  $obj = new SomeClass;
+
    $obj = new SomeClass;
  $obj->name = 'New Value'; // Виводить "__set: присвоювання властивості name=New Value"
+
    $obj->name = 'New Value'; // Виводить "__set: присвоювання властивості name=New Value"
  $value = $obj->name; // Виводить "__get: читання властивості name: New Value"
+
    $value = $obj->name; // Виводить "__get: читання властивості name: New Value"
?>
+
    ?>
Перевантаження викликів методів класу.
+
</syntaxhighlight>
Якщо метод __call() описаний в певному класі, тоді він автоматично переловлює виклики до неіснуючих методів цього класу. В якості параметрів він отримує ім'я і параметри методу що викликається.
+
  
Приклад:
+
== Перевантаження викликів методів класу. ==
<?php
+
  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 |'
+
?>
+
  
 +
Якщо метод ''__call()'' описаний в певному класі, тоді він автоматично переловлює виклики до неіснуючих методів цього класу. В якості параметрів він отримує ім'я і параметри методу що викликається.
  
 +
Приклад:
  
 +
<syntaxhighlight lang="php">
 +
    <?php
 +
    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 |'
 +
    ?>
 +
</syntaxhighlight>
  
 
[[category:Інтернет-програмування|*]]
 
[[category:Інтернет-програмування|*]]
  
 
[[category:Навчальні проекти]]
 
[[category:Навчальні проекти]]

Поточна версія на 09:42, 9 вересня 2014

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

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

Процедурне програмування.

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

Об'єктно-орієнтовне програмування (ООП).

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

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

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

Кожен об'єкт має свій певний тип (клас), що об'єднає в собі наступні елементи:

  1. Властивості – певні параметри і характеристики об'єкту
  2. Методи – дії, що можна виконувати над даним об'єктом, чи які може виконувати він сам
  3. Події – повідомлення що виникають при зміні стану об'єкта


ООП функціонує за наступними принципами:

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

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


Області видимості методів і властивостей класів.

В PHP 5 введені специфікатори доступу до методів і властивостей класів:

   * public – доступний без обмежень
   * protected – тільки в середині класу, в якому вони оголошені і похідних від нього класах
   * private – тільки в середині класу, в якому вони оголошені


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

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

    <?php
        // оголошуємо основний клас
    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) методи і властивості. Їхньою особливістю є те, що вони не належать певному об'єктові, вони єдині для цілого класу, і можуть викликатися без створення об'єкту. Зміна статичної властивості в одному з об'єктів класу призводить до його зміни для всіх об'єктів цього класу.

Приклад:

    <?php
      // оголошуємо основний клас
    class SomeClass
    {
        static $staticVar = 'Static Variable';
 
        static function StaticFunction()
        {
            echo 'StaticFunction()';
        }
    }
    echo SomeClass::StaticFunction(); // Виводить StaticFunction()
    echo SomeClass::$staticVar; // Виводить Static Variable
    ?>

Константи класу

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

Приклад:

    <?php
    class SomeClass
    {
          const SOME_CONSTANT = "SOME CONSTANT";
    }
    echo SomeClass::SOME_CONSTANT; // Виводить "SOME CONSTANT"
    ?>

Конструктори и деструктори.

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

    <?php
    class SomeClass
    {
        function __construct()
        {
            echo 'Create object';
        }
 
        function __destruct()
        {
            echo 'Destroy object';
        }
     }
    $someObj = new SomeClass; // Виводиться Create object
    unset($someObj); // Виводиться Destroy object
    ?>

Абстрактні методи і класи.

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

Приклад:

    <?php
    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.

Приклад:

    <?php
    // оголошення інтерфейсів
    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). На основі фінальних класів неможливо створити класи нащадки. Також не можна перевизначити фінальний метод в класах нащадках.

Приклад:

    <?php
    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.

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

    <?php
    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 можна визначити чи об'єкт екземпляром класу, створеного на основі певного інтерфейсу.

Приклад:

    <?php
    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() викликається в випадку коли створюється об'єкт на основі неіснуючого або неописаного в даному конкретному файлі з кодом класу

Приклад:

    <?php
    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() окрім імені ще і нове значення властивості, яке відповідно і присвоює.

Приклад:

    <?php
    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() описаний в певному класі, тоді він автоматично переловлює виклики до неіснуючих методів цього класу. В якості параметрів він отримує ім'я і параметри методу що викликається.

Приклад:

    <?php
    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 |'
    ?>