Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

PHP5 и ООП

Лекция



Привет, сегодня поговорим про php5, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое php5, ооп , настоятельно рекомендую прочитать все из категории Психология управления.

Новая объектно-ориентированная модель в php5

PHP5 и ООП Когда Зив Сераски (Zeev Suraski) добавил объектно-ориентированный (ОО) синтаксис в PHP 3, это можно было рассматривать как "синтаксический подсластитель для поддержки классов" ("syntactic sugar for accessing collections"). Объектно-ориентированная модель получила поддержку наследования и позволяла классу (и объекту) объединять методы и свойства, но не более того. Когда Зив и Анди переписали движок для PHP 4, это был полностью новый движок, работающий намного быстрее, намного стабильнее и с еще многими другими возможностями. Однако, изменения практически не затронули ОО модель, первоначально введенную еще в РНР 3.

Хотя объектная модель имела серьезные ограничения, она широко использовалась, часто в очень больших приложениях, написанных на PHP. Это победное шествование парадигмы ооп , даже такой ограниченной в РНР 4, привело к тому, что изменения объектной модели стали центральными в новом релизе РНР - PHP5.

Какие были ограничения в PHP 3 и 4? Самым большим ограничением (которое и приводило ко всем остальным ограничениям) был тот факт, что семантика экземпляра объекта была такой же, что и для родных типов. Как это фактически отражалось на разработчиках? Когда вы присваивали переменную (которая указывает на объект) другой переменной, то создавалась копия объекта. Мало того, что это влияло на производительность, но и это обычно приводило к ошибкам в приложении, потому что многие разработчики думали, что обе переменные будут указывать на тот же самый объект. А они указывали на разные копии того же самого объекта, поэтому, изменяя один объект, мы не меняли другой. Вот пример:

<?php 
class Person { 
     var $name; 
     function getName() { 
         return $this->name; 
     } 
     function setName($name) { 
         $this->name = $name; 
     } 
     function Person($name) { 
         $this->setName($name); 
     } 


function changeName($person, $name) { 
     $person->setName($name); 


$person = new Person("Andi"); 
changeName($person, "Stig"); 
print $person->getName(); 
?>

В РНР 4 этот код выведет "Andi". Причина кроется в том, что мы передаем объект $person в функцию changeName() по значению, а не по ссылке, таким образом, объект $person будет скопирован, и changeName() будет работать уже с копией объекта $person.

Такое поведение не является интуитивно понятным. Действительно, многие разработчики ожидали Java-подобного поведения. В Java, переменные фактически являются указателями на объект, и поэтому при дублировании будет скопирован указатель, а не сам объект.

Было два вида разработчиков: те, кто знал об этой проблеме, и те, кто не знал. Последние, обычно, не сталкивались с этой проблемой, потому что их код был написан так, что было безразлично, существует ли такая проблема или нет. Конечно, некоторые из этих разработчиков проводили бессонные ночи в "увлекательных" поисках "сверхъестественных" ошибок. Первая группа также имела проблему, поскольку приходилось вручную определять передачу объекта по ссылке, запрещая движку копировать объекты, и код был испещрен многочисленными знаками '&'.

Старая объектная модель приводит не только к вышеупомянутым проблемам, но также вскрывает более фундаментальные проблемы, которые на существующей объектной модели не позволяли осуществлять другие возможности.

В PHP 5 объектная модель была полностью переписана для того, чтобы сразу работать с указателями на объект. Если вы явно не клонируете объект, используя ключевое слово clone, вы никогда не будете работать с копией объекта, думая, что работаете с самим объектом. В PHP 5 уже не нужно явно передавать объекты или присваивать их по ссылке, это делаетсяавтоматически.

Обратите внимание: явная передача и присваивание по ссылке также поддерживается, на тот случай, если вы хотите изменить содержимое переменной или объекта.

Новый объектно-ориентированный подход в PHP5

Новые возможности объектной модели являются слишком многочисленными. Приведем обзор главных изменений:

  1. public/private/protected - модификаторы доступа для методов и свойств

    Позволяют управлять доступом к методам и свойствам. Теперь видимость свойств и методов может быть определена ключевыми словами: publicprivateprotected. Модификатор public позволяет обращаться к свойствам и методам отовсюду. Модификатор private позволяет обращаться к свойствам и методам только внутри текущего класса. Модификатор protected позволяет обращаться к свойствам и методам только текущего класса и класса, который наследует свойства и методы текущего класса.

    <?php
    /**
      * Define MyClass
      */
    class MyClass
    {
         public $public = 'Public';
         protected $protected = 'Protected';
         private $private = 'Private';

         function printHello()
         {
             echo $this->public;
             echo $this->protected;
             echo $this->private;
         }
    }

    $obj = new MyClass();
    echo $obj->public; // Works
    echo $obj->protected; // Fatal Error
    echo $obj->private; // Fatal Error
    $obj->printHello(); // Shows Public, Protected and Private


    /**
      * Define MyClass2
      */
    class MyClass2 extends MyClass
    {
         // We can redeclare the public and protected method, but not private
         protected $protected = 'Protected2';

         function printHello()
         {
             echo $this->public;
             echo $this->protected;
             echo $this->private;
         }
    }

    $obj2 = new MyClass2();
    echo $obj->public; // Works
    echo $obj2->private; // Undefined
    echo $obj2->protected; // Fatal Error
    $obj2->printHello(); // Shows Public, Protected2, not Private

    ?>

  2. Унифицированный конструктор __construct()

    PHP 5 позволяет объявлять методы-конструкторы. Классы, в которых объявлен метод-констуктор, будут вызывать этот метод при каждом создании нового объекта, так что это может оказаться полезным, чтобы, например, инициализировать какое-либо состояние объекта перед его использованием. Конструктор, ранее совпадавший с названием класса, теперь необходимо объявлять как __construct(), что позволит легче перемещать классы в иерархиях. Конструкторы в классах-родителях не вызываются автоматически. Чтобы вызвать конструктор, объявленный в родительском классе, следует обратиться к методу parent::__construct().

    <?php
    class BaseClass {
         function __construct() {
             print "Конструктор класса BaseClass\n";
         }
    }

    class SubClass extends BaseClass {
         function __construct() {
             parent::__construct();
             print "Конструктор класса SubClass\n";
         }
    }

    $obj = new BaseClass();
    $obj = new SubClass();
    ?>

    Если PHP 5 не может обнаружить объявленный метод __construct(), вызов конструктора произойдет по прежней схеме, через обращение к методу, имя которого соответствует имени класса. Может возникнуть только одна проблема совместимости старого кода, если в нем присутствуют классы с методами __construct().

  3. Поддержка деструктора для класса, определяемого как метод __destructor()

    PHP 5 предоставляет концепцию деструкторов, сходную с теми, что применяются в других ОО языках, таких, как Java: когда освобождается последняя ссылка на объект, перед высвобождением памяти, занимаемой этим объектом, вызывается метод __destruct(), не принимающий параметров.

    <?php
    class MyDestructableClass {
         function __construct() {
             print "Конструктор\n";
             $this->name = "MyDestructableClass";
         }

         function __destruct() {
             print "Уничтожается " . $this->name . "\n";
         }
    }

    $obj = new MyDestructableClass();
    ?>

    Как и в случае с конструкторами, деструкторы, объявленные в родительском классе, не будут вызваны автоматически. Об этом говорит сайт https://intellect.icu . Для вызова деструктора, объявленном в классе-родителе, следует обратиться к методуparent::__destruct().

    1. Явное клонирование объекта

      Создание копии объекта с абсолютно идентичными свойствами не всегда является приемлемым вариантом. Например, когда ваш объект содержит ссылку на какой-либо другой используемый объект и, когда вы создаете копию ссылающегося объекта, вам нужно также создать новый экземпляр содержащегося объекта, так, чтобы копия объекта содержала собственный отдельный экземпляр содержащегося объекта.

      Копия объекта создается с использованием вызова clone (который вызывает метод __clone() объекта, если это возможно). Вы можете объявить метод __clone(), который будет вызван при клонировании объекта (после того, как все свойства будут скопированы из исходного объекта).

      copy_of_object = clone $object;

      Когда программист запрашивает создание копии объекта, PHP 5 определит, был ли для этого объекта объявлен метод __clone() или нет. Если нет, будет вызван метод __clone(), объявленный по умолчанию, который скопирует все свойства объекта. Если метод __clone() был объявлен, создание копий свойств в копии объекта полностью возлагается на него. Для удобства, движок обеспечивает программиста функцией, которая импортирует все свойства из объекта-источника, так что программист может осуществить позначное копирование свойств и переопределять только необходимые. Приведем пример клонирования объекта:

      <?php 
      class MyClass { 
           function __clone() { 
               print "Объект был клонирован "; 
           } 

      $obj = new MyClass(); 
      clone $obj; 
      ?>

    2. Константы класса

      В определения классов теперь можно включить константы, и ссылаться на них, используя объект. Константы также могут быть объявлены и в пределах одного класса. Отличие переменных и констант состоит в том, что при объявлении последних или при обращении к ним не используется символ $. Как и свойства и методы, значения констант, объявленных внутри класса, не могут быть получены через переменную, содержащую экземпляр этого класса.

      <?php 
      class MyClass { 
           const SUCCESS = "Success"; 
           const FAILURE = "Failure"; 

      print MyClass::SUCCESS; 
      ?>

    3. Статические члены класса

      Определения классов могут теперь включить статических членов класса (свойства и методы), доступ к которым осуществляется через класс. Общее использование статических членов показано на примере:

      <?php 
      class Singleton { 
           static private $instance = NULL; 

           private function __construct() { 
           } 

           static public function getInstance() { 
               if (self::$instance == NULL) { 
                   self::$instance = new Singleton(); 
               } 
               return self::$instance; 
           } 

      ?>

    4. Статические методы

      Вы можете теперь определить методы как статические, разрешая им быть вызванными вне контекста объекта. Статические методы не определяются через переменную $this, поскольку они не должны быть ограничены определенным объектом.

      <?php 
      class MyClass { 
           static function helloWorld() { 
               print "Hello, world"; 
           } 

      MyClass::helloWorld(); 
      ?>

    5. Абстрактные классы

      PHP 5 поддерживает определение абстрактных классов и методов. Создавать экземпляр класса, который был объявлен абстрактным, нельзя. Класс, в котором объявлен хотя бы один абстрактный метод, должен также быть объявлен абстрактным. Методы, объявленные как абстрактные, несут, по существу, лишь описательный смысл и не могут включать какой-либо функционал. Класс может быть объявлен как абстрактный при помощи использования ключевого слова abstract, для исключения из обработки движком описания класса. Однако, вы можете наследовать абстрактные классы. Практический пример:

      <?php

      abstract class AbstractClass {

          /* Данный метод должен быть определен в дочернем классе */
          abstract protected function getValue();

          /* Общий метод */
          public function print() {
            print $this->getValue();
          }

      }

      class ConcreteClass1 extends AbstractClass {

          protected function getValue() {
            return "ConcreteClass1";
          }

      }

      class ConcreteClass2 extends AbstractClass {

          protected function getValue() {
            return "ConcreteClass2";
          }

      }

      $class1 = new ConcreteClass1;
      $class1->print();

      $class2 = new ConcreteClass2;
      $class2->print();
      ?>

    6. Абстрактные методы

      Метод может быть объявлен как abstract, таким образом отложив его определение наследуемым классом. Класс, который включает абстрактные методы, должен быть объявлен как abstract.

      <?php 
      abstract class MyBaseClass { 
           abstract function display(); 

      ?>

    7. Указание класса как типа

      Определения функции могут включить указание типа класса, передаваемого в качестве параметра. Если функция будет вызвана с неправильным типом, произойдет ошибка.

      <?php 
      function expectsMyClass(MyClass $obj) { 


      ?>

    8. Поддержка разыменования объектов, которые возвращаются методами.

      В PHP 4 вы не могли непосредственно разыменовывать объекты, которые возвращаются из методов. Вы должны были бы сначала присвоить такой объект некой фиктивной переменной.

      Поясним на примере. В PHP 4:

      <?php 
      $dummy = $obj->method(); 
      $dummy->method2(); 
      ?>

      В PHP 5:

      <?php 
      $obj->method()->method2(); 
      ?>

    9. Итераторы

      PHP 5 предоставляет механизм итераторов для получения списка всех свойств какого-либо объекта, например, для использования совместно с оператором foreach. По умолчанию, в итерации будут участвовать все свойства, объявленные как public. Пример использования итераторов:

      <?php

      class MyClass {
         public $var1 = 'value 1';
         public $var2 = 'value 2';
         public $var3 = 'value 3';

         protected $protected = 'protected';
         private   $private   = 'private';

      }

      $class = new MyClass();

      foreach($class as $key => $value) {
         print "$key => $value\n";
      }

      Результат:

      var1 => value 1
      var2 => value 2
      var3 => value 3

      Как показывает результат, foreach проитерировал все принадлежащие объекту public-свойства.


    • __autoload()

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

      В PHP 5 в этом больше нет необходимости. Вы можете определить функцию __autoload() , которая автоматически будет вызываться в случае использования класса, который не был определен выше. Вызывая такую функцию, Zend Engine дает возможность загрузить файл с определением класса прежде, чем будет сформировано сообщение об ошибке и выполнение скрипта прекратится.

      <?php 
      function __autoload($class_name) { 
           include_once($class_name . "php"); 


      $obj  = new MyClass1(); 
      $obj2 = new MyClass2(); 
      ?>

    • Обработка исключительных ситуаций (исключений)

    PHP 5 добавляет парадигму обработки исключений, вводя структуру try/throw/catch. Вам остается только создать объекты, которые наследуют класс исключений Exception.

    <?php 
    class SQLException extends Exception { 
         public $problem; 
         function __construct($problem) { 
             $this->problem = $problem; 
         } 


    try { 
         ... 
         throw new SQLException("Couldn't connect to database"); 
         ... 
    } catch (SQLException $e) { 
         print "Caught an SQLException with problem $obj->problem"; 
    } catch (Exception $e) { 
         print "Caught unrecognized exception"; 

    ?>

    В настоящее время в целях обратной совместимости большинство внутренних функций не использует исключения. Однако, все новые расширения будут иметь такую возможность, и вы можете использовать такую конструкцию в своем исходном тексте. Кроме того, подобно уже существующей функции set_error_handler(), вы можете использовать set_exception_handler(), чтобы отловить необработанное исключение прежде, чем выполнение скрипта будет закончено.

    • Сравнение объектов

    В PHP 5 сравнение объектов является более сложным процессом, чем в PHP 4, а также процессом, более соответствующим идеологии объектно-ориентированного языка.

    При использовании оператора сравнения (==), свойства объектов просто сравниваются друг с другом, а именно: два объекта равны, если они содержат одинаковые свойства и одинаковые их значения и являются экземплярами одного и того же класса.

    С другой стороны, при использовании оператора идентичности (===), свойства объекта считаются идентичными тогда и только тогда, когда они ссылаются на один и тот же экземпляр одного и того же класса.

    Следующий пример внесет ясность.

    <?php
    function bool2str($bool) {
         if ($bool === false) {
                 return 'FALSE';
         } else {
                 return 'TRUE';
         }
    }

    function compareObjects(&$o1, &$o2) {
         echo 'o1 == o2 : '.bool2str($o1 == $o2)."\n";
         echo 'o1 != o2 : '.bool2str($o1 != $o2)."\n";
         echo 'o1 === o2 : '.bool2str($o1 === $o2)."\n";
         echo 'o1 !== o2 : '.bool2str($o1 !== $o2)."\n";
    }

    class Flag {
         var $flag;

         function Flag($flag=true) {
                 $this->flag = $flag;
         }
    }

    class OtherFlag {
         var $flag;

         function OtherFlag($flag=true) {
                 $this->flag = $flag;
         }
    }

    $o = new Flag();
    $p = new Flag();
    $q = $o;
    $r = new OtherFlag();

    echo "Два экземпляра одного и того же класса\n";
    compareObjects($o, $p);

    echo "\nДве ссылки на один и тот же экземпляр\n";
    compareObjects($o, $q);

    echo "\nЭкземпляры двух разных классов\n";
    compareObjects($o, $r);
    ?>

    Результатом выполнения этого кода будет:

    Два экземпляра одного и того же класса
    o1 == o2 : TRUE
    o1 != o2 : FALSE
    o1 === o2 : FALSE
    o1 !== o2 : TRUE

    Две ссылки на один и тот же экземпляр
    o1 == o2 : TRUE
    o1 != o2 : FALSE
    o1 === o2 : TRUE
    o1 !== o2 : FALSE

    Экземпляры двух разных классов
    o1 == o2 : FALSE
    o1 != o2 : TRUE
    o1 === o2 : FALSE
    o1 !== o2 : TRUE


    1. Перегрузка свойств классов

Обращения к свойствам объекта могут быть перегружены с использованием методов __call__get и __set. Эти методы будут срабатывать только в том случае, если объект или наследуемый объект не содержат свойства, к которому осуществляется доступ. Синтаксис такой:

void __set ( string имя, mixed значение )

void __get ( mixed имя )

С помощью этих методов обращения к свойствам класса могут быть перегружены с целью выполнения произвольного кода, описанного в классе. В аргументе имя передается имя свойства, к которому производится обращение. Аргумент значение метода __set() должен содержать значение, которое будет присвоено свойству класса с именем имя.

Пример перегрузки с использованием __get и __set:

<?php
class Setter {
   public $n;
   private $x = array("a" => 1, "b" => 2, "c" => 3);

   function __get($nm) {
     print "Читаем [$nm]\n";

     if (isset($this->x[$nm])) {
       $r = $this->x[$nm];
       print "Получили: $r\n";
       return $r;
     } else {
       print "Ничего!\n";
     }
   }

   function __set($nm, $val) {
     print "Пишем $val в [$nm]\n";

     if (isset($this->x[$nm])) {
       $this->x[$nm] = $val;
       print "OK!\n";
     } else {
       print "Все плохо!\n";
     }
   }
}

$foo = new Setter();
$foo->n = 1;
$foo->a = 100;
$foo->a++;
$foo->z++;
var_dump($foo);
?>

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

Пишем 100 в [a]
OK!
Читаем [a]
Получили: 100
Пишем 101 в [a]
OK!
Читаем [z]
Ничего!
Пишем 1 в [z]
Все плохо!
object(Setter)#1 (2) {
   ["n"]=>
   int(1)
   ["x:private"]=>
   array(3) {
     ["a"]=>
     int(101)
     ["b"]=>
     int(2)
     ["c"]=>
     int(3)
   }
}

    1. Перегрузка методов

Вызовы методов могут быть перегружены с использованием методов __call__get и __set. Эти методы будут срабатывать только в том случае, если объект или наследуемый объект не содержат метода, к которому осуществляется доступ. Синтаксис:

mixed __call ( string имя, array аргументы )

С использованием этого метода, методы класса могут быть перегружены с целью выполнения произвольного кода, описанного в классе. В аргументе имя передается имя вызванного метода. Аргументы, которые были переданы методу при обращении, будут возвращены чере аргументы. Значение, возвращенное методом__call(), будет передано вызывающему оператору.

Пример перегрузки с использованием __call:

<?php
class Caller {
   private $x = array(1, 2, 3);

   function __call($m, $a) {
     print "Вызван метод $m :\n";
     var_dump($a);
     return $this->x;
   }
}

$foo = new Caller();
$a = $foo->test(1, "2", 3.4, true);
var_dump($a);
?>

Результат выполнения рассмотренного примера:

Вызван метод test:
array(4) {
   [0]=>
   int(1)
   [1]=>
   string(1) "2"
   [2]=>
   float(3.4)
   [3]=>
   bool(true)
}
array(3) {
   [0]=>
   int(1)
   [1]=>
   int(2)
   [2]=>
   int(3)
}

  1. Интерфейсы

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

    Интерфейсы объявляются так же, как и обычные классы, но с использованием ключевого слова "interface"; тела методов интерфейсов должны быть пустыми. Для включения интерфейса в класс программист должен использовать ключевое слово "implements" и описать функционал методов, перечисленных во включаемом интерфейсе. Если это требуется, классы могут включать более одного интерфейса путем их перечисления через пробел.

    Если класс включает какой-либо интерфейс и не описывает функционал всех методов этого интерфейса, выполнение кода с использованием такого класса завершится фатальной ошибкой, сообщающей, какие именно методы не были описаны. Пример интерфейса:

    <?php
    interface ITemplate
    {
       public function setVariable($name, $var);
       public function getHtml($template);
    }

    class Template implements ITemplate
    {
       private $vars = array();
       
       public function setVariable($name, $var)
       {
         $this->vars[$name] = $var;
       }
       
       public function getHtml($template)
       {
         foreach($this->vars as $name => $value) {
           $template = str_replace('{'.$name.'}', $value, $template);
         }
         
         return $template;
       }
    }
    ?>

  2. Оператор instanceof

    Поддержка проверки зависимости от других объектов. Функцией is_a(), известной из PHP 4, пользоваться теперь не рекомендуется.

    <?php 
    if ($obj instance of Circle) { 
         print '$obj is a Circle'; 

    ?>

  3. Метод final

    Ключевое слово final позволяет вам помечать методы, чтобы наследующий класс не мог перегрузить их. Разместив перед объявлениями методов или свойств класса ключевое слово final, вы можете предотвратить их переопределение в дочерних классах, например:

    <?php
    class BaseClass {
        public function test() {
            echo "Вызван метод BaseClass::test()\n";
        }
        
        final public function moreTesting() {
            echo "Вызван метод BaseClass::moreTesting()\n";
        }
    }

    class ChildClass extends BaseClass {
        public function moreTesting() {
            echo "Вызван метод ChildClass::moreTesting()\n";
        }
    }
    // Выполнение заканчивается фатальной ошибкой: 
    //Cannot override final method BaseClass::moreTesting()
    // (Метод BaseClass::moretesting() не может быть переопределен)
    ?>

  4. Классы, помеченные как final

    После объявления класса final он не может быть унаследован. Следующий пример вызовет ошибку:

    <?php 
    final class FinalClass { 


    class BogusClass extends FinalClass { 

    ?>

Более подробно о возможностях PHP5 и Zend 2.0 вы можете узнать, обратившись к документации Zend Engine 2.0.

 

Надеюсь, эта статья про php5, была вам полезна, счастья и удачи в ваших начинаниях! Надеюсь, что теперь ты понял что такое php5, ооп и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Психология управления

создано: 2015-02-25
обновлено: 2021-03-13
132484



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей



Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Психология управления

Термины: Психология управления