Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Основы ООП

Evgeny E. Neverov
December 05, 2017
88

Основы ООП

5 декабря 2017 года, Евгений Неверов

Evgeny E. Neverov

December 05, 2017
Tweet

Transcript

  1. Класс и объект • Класс — это описание некой сущности/объекта:

    что оно может и умеет, какие у него есть характеристики. 
 
 Класс можно назвать шаблоном, по которому созданы объекты. • Объект — экземпляр класса, конкретная сущность, созданная по шаблону (классу).
  2. Класс и объект class Animal { public $name = 'Шарик';

    public $age = 3; function displayInfo() { echo $this&->name . ': ' . $this&->age; } } $dog = new Animal; $dog&->displayInfo(); &// Шарик: 3
  3. $this class ThisSample { function hasThis() { var_dump(isset($this)); } }

    ThisSample&::hasThis(); &// bool(false) $t = new ThisSample; $t&->hasThis(); &// bool(true)
  4. $this относится к текущему объекту! class Animal { public $name;

    function showName() { echo $this&->name; } } $dog = new Animal; $dog&->name = 'Шарик'; $cat = new Animal; $cat&->name = 'Мурзик'; $dog&->showName(); $cat&->showName();
  5. Константы class Dog extends Animal { const MAX_AGE = 29

    + 5/12; &// expression, scalar or array; not null function displayMaxAge() { echo 'Max dog age: ' . self&::MAX_AGE; } function isRecordBeat() { return $this&->age > self&::MAX_AGE; } } $sharik = new Dog; $sharik&->age = 30; $sharik&->displayMaxAge(); if ($sharik&->isRecordBeat()) echo 'This is a new record!';
  6. Конструктор и деструктор class Animal { function &__construct() { echo

    'Hello, '; } function &__destruct() { echo 'World!'; } } $a = new Animal; $a = false; &// в данном скрипте эту строку можно убрать, &// деструктор сработает при завершении скрипта
  7. Области видимости Обращение снаружи Обращение из дочерних или родительских классов

    public var Доступно Доступно protected Недоступно Доступно private Недоступно Недоступно Переменные, функции, константы (начиная с 7.1)
  8. Области видимости class Animal { public $name; protected $age; private

    $type; } class Dog extends Animal { function change() { $this&->name = 'Шарик'; $this&->age = 10; $this&->type = 'Собака'; &// Fatal Error } } $sharik = new Dog; $sharik&->name = 'Мурзик'; $sharik&->age = 2; &// Fatal Error $sharik&->type = 'Собака'; &// Fatal Error
  9. Видимость из других объектов того же класса class Animal {

    private $age = 10; public function getAge(Animal $other) { return $other&->age; } } $dog = new Animal; $cat = new Animal; echo $cat&->getAge($dog); &// Аналогично с приватными методами
  10. Приватный конструктор class Animal { private function &__construct() { &//

    Создать объект класса снаружи невозможно } } $a = new Animal; &// Fatal Error В таком варианте объект можно создать клонированием или восстановлением через unserialize();
  11. Singletone (одиночка) class LochNessMonster { static private $instance = null;

    private function &__construct() {} private function &__clone() {} private function &__wakeup() {} static public function getInstance() { return self&::$instance &?? (self&::$instance = new static()); } }
  12. Наследование class Animal { public $name; public $age; public function

    displayInfo() { echo $this&->name . ': ' . $this&->age; } } class Dog extends Animal { public $breed; &// порода public function bringAStick() { &&... } &// принеси палку! } $sharik = new Dog; $sharik&->name = 'Шарик'; $sharik&->breed = 'Шпиц'; $sharik&->displayInfo();
  13. Переопределение функций class Animal { public $name; public $age; public

    function displayInfo() { echo $this&->name . ': ' . $this&->age; } } class Cat extends Animal { public function displayInfo() { echo 'Кот: '; parent&::displayInfo(); } } $murzik = new Cat; $murzik&->name = 'Мурзик'; $murzik&->age = 2; $murzik&->displayInfo(); &// Кот: Мурзик: 2
  14. Финальный метод класса class Animal { public $name; public $age;

    public final function displayInfo() { echo $this&->name . ': ' . $this&->age; } } class Cat extends Animal { public function displayInfo() { &// Fatal Error echo 'Кот: '; parent&::displayInfo(); } } &// Другие (не-final) функции можно переопределять
  15. Финальный класс final class Animal { public $name; public $age;

    public function displayInfo() { echo $this&->name . ': ' . $this&->age; } } class Cat extends Animal { &&... } &// Fatal Error
  16. Статические переменные и методы определение переменной или метода, как статического,

    позволяет обращаться к ним без необходимости создания объекта класса
  17. Статические переменные и методы class Dog extends Animal { public

    static $type = 'Dogs'; public static function getType() { echo 'Type: ' . self&::$type; } } echo Dog&::$type; &// Dogs echo Dog&::getType(); &// Type: Dogs $sharik = new Dog; $sharik&->type = 'Cats'; &// Notice: Undefined property $sharik&->getType(); &// Type: Dogs print_r($sharik); &// появилась нестатическая переменная, &// только у этого объекта
  18. Абстрактный класс • часть методов класса определяется абстрактными и должны

    быть переопределены в дочерних классах • нельзя создать объект абстрактного класса • если дочерний класс определяет не все абстрактные методы родительского, он тоже является абстрактным
  19. Абстрактный класс abstract class Animal { public $name; public $age;

    abstract public function getFullName(); public function getName() { echo $this&->name; } } class Dog extends Animal { public function getFullName() { echo 'Собака: '; self&::getName(); } } $sharik = new Dog; $sharik&->name = 'Шарик'; $sharik&->getFullName(); &// Собака: Шарик
  20. Интерфейс • определяет список функций, который должен быть определён в

    классе, включающем интерфейс • не содержит никакого кода и свойств (абстрактный класс может содержать код и свойства) • определяет только публичные методы • интерфейсы можно расширять через extends
  21. Интерфейс interface IAnimal { public function getType(); public function move();

    } class Dog implements IAnimal { public function getType() { return 'Dog'; } public function move() { self&::run(); &// some inner function echo 'I like to move it, move it!'; } }
  22. Зачем? Чтобы быть уверенным, что принимаемый аргумент умеет делать то,

    что нам нужно. Фактически интерфейс — это поддержка требуемого набора функций.
  23. Интерфейс function moveSomeAnimal(IAnimal $animal) { $animal&->move(); echo $animal&->getType() . '

    is moving!!!'; } $sharik = new Dog; moveSomeAnimal($sharik); &// $sharik&::run(); &// I like to move it, move it &// Dog is moving!
  24. Интерфейс interface Runnable { public function run(); } interface Swimmable

    { public function swim(); } class Cat implements Runnable { &&... } class Fish implements Swimmable { &&... } class Dog implements Runnable, Swimmable { &&... }
  25. Описание метода класса должно полностью соответствовать определению интерфейса interface Runnable

    { public function run(Animal $animal); } class Cat implements Runnable { &// Fatal Error public function run($animal) { } }
  26. Интерфейсы можно наследовать interface Swimmable { public function swim(); }

    interface SwimmableInSaltWater extends Swimmable { public function swimInOcean(); }
  27. Интерфейс может содержать константы • Они работают точно так же,

    как константы в классах. • Их нельзя переопределить в классе или в наследуемом интерфейсе.
  28. Traits • Гугл переводит «Trait» как «Особенность», «Отличительная черта». •

    Набор функций и переменных, которые можно «подключить» и использовать в собственном классе. • Нужны для того, чтобы исправить ограничение PHP на наследование только от одного класса. • Методы trait-ов перегружают методы родительских классов. Методы текущего класса перегружают методы подключенных trait-ов.
  29. Перегрузка Trait-ов trait A { public function show() { echo

    1; } } class Base { public function show() { echo 2; } } class Child extends Base { use A; } $var = new Child; $var&->show(); &// 1
  30. Перегрузка Trait-ов trait A { public function show() { echo

    1; } } class Base { public function show() { echo 2; } } class Child extends Base { use A; public function show() { echo 3; } } $var = new Child; $var&->show(); &// 3
  31. Конфликты в Trait-ах trait A { public function show() {

    &&... } public function hide() { &&... } } trait B { public function show() { &&... } public function hide() { &&... } } class C { use A, B; &// Fatal Error }
  32. Конфликты в Trait-ах trait A { public function show() {

    &&... } public function hide() { &&... } } trait B { public function show() { &&... } public function hide() { &&... } } class C { use A, B { A&::show insteadof B; B&::hide insteadof A; } }
  33. Конфликты в Trait-ах trait A { public function show() {

    &&... } public function hide() { &&... } } trait B { public function show() { &&... } public function hide() { &&... } } class C { use A, B { A&::show as AShow; A&::hide as AHide; } }
  34. Переменные Trait-ов trait SomeTrait { public $someVar = 5; static

    public $variable = 10; } class A { use SomeTrait; } echo A&::$variable; &// 10 echo (new A)&->someVar; &// 5 В классе нельзя определить переменную с тем же именем, что и у Trait-а, кроме случая, когда переменная имеет тот же тип и то же начальное значение.
  35. Особенность статических переменных Trait-ов trait SomeTrait { static public $variable

    = 10; } class A { use SomeTrait; } class B { use SomeTrait; } A&::$variable = 15; echo A&::$variable; &// 15 echo B&::$variable; &// 10
  36. Другие фичи Trait-ов trait SomeTrait { use B, C, D;

    &// их можно «наследовать» abstract public function functionName(); &// объявлять в них абстрактные функции } class A { use SomeTrait { functionName as private; &// можно менять функциям trait-ов &// область видимости otherFunctionName as protected someNewName; &// и имена } }
  37. Singletone (одиночка) trait Singletone { static private $instance = null;

    private function &__construct() {} private function &__clone() {} private function &__wakeup() {} static public function getInstance() { return self&::$instance &?? (self&::$instance = new static()); } } class LochNessMoster { use Singletone; } class Zeus { use Singletone; }
  38. Перегрузка • Позволяет динамически создавать свойства и вызывать методы, которые

    в классе не определены. • Работает через «волшебные» методы. • Перегрузка свойств работает только в контексте объекта, не работает статически.
  39. Перегрузка свойств class HiddenList { private $data = []; public

    $var = 1; private $hidden = 2; public function &__set($name, $value) { $this&->data[$name] = $value; } public function &__get($name) { return isset($this&->data[$name]) ? $this&->data[$name] : ’n/a’; } public function &__isset($name) { return isset($this&->data[$name]); } public function &__unset($name) { unset($this&->data[$name]); } }
  40. Перегрузка свойств $list = new HiddenList; $list&->a = 'hello'; $list&->var

    = 3; &// тут вызова &__set() не будет $list&->hidden = 4; &// тут не возникнет Fatal Error echo $list&->hidden; &// и тут не возникнет echo isset($list&->a) ? 'isset' : 'not set’; &// isset unset($list&->a); echo isset($list&->a) ? 'isset' : 'not set’; &// not set
  41. Перегрузка методов class HiddenFunctions { public function &__call($name, $args) {

    echo 'Method ' . $name . ' called with args: '; print_r($args); } public function &__callStatic($name, $args) { echo 'Static method ' . $name . ' called with args: '; print_r($args); } } $a = new HiddenFunctions; $a&->runTest(1, 2, ‘test'); &// Method runTest called with args […] HiddenFunctions&::runTest(3, 4, [5, 6], new Date); &// Static method runTest called with args […]
  42. Больше «магических» методов! class Dog extends Animal { &// Срабатывает

    перед сериализацией и возвращает &// массив имён свойств, которые разрешено &// сериализовать public function &__sleep() { return ['name', 'breed']; } &// срабатывает после десериализации &// полезен для восстановления любых ресурсов &// (соединения с БД и т.п.) public function &__wakeup() {} } $a = new Dog; $a&->name = 'Шарик'; $a&->age = 10; $a&->breed = 'Шпиц'; echo serialize($a); &// O:3:"Dog":2:{s:4:"name";s:10:"Шарик";s: 5:"breed";s:8:"Шпиц";}
  43. Больше «магических» методов! class Dog extends Animal { &// Срабатывает

    при попытке использовать объект &// как строку public function &__toString() { return $this&->name; } } $a = new Dog; $a&->name = 'Шарик'; $a&->age = 10; echo $a; &// Шарик
  44. Больше «магических» методов! class Sheep extends Animal { private $innerId

    = 0; &// Срабатывает при попытке клонировать объект public function &__clone() { $this&->innerId&++; } } $dolly = new Sheep; &// innerId = 0 $molly = clone $dolly; &// innerId = 1
  45. Сравнение объектов • Объекты равны (==), если содержат одинаковый набор

    свойств с одинаковыми значениями (сравниваются тоже через ==) и являются экземплярами одного класса. • Объекты идентичны (===), когда сравниваются ссылки на один и тот же экземпляр класса.
 $a = new Sheep; $b = $a; $a === $b;
  46. self:: и __CLASS__ указывают на класс,
 в котором функция определена

    class Animal { public static function whoami() { echo &__CLASS&__; } public static function showMe() { self&::whoami(); } } class Cat extends Animal { public static function whoami() { echo &__CLASS&__; } } Cat&::showMe(); &// Animal
  47. static:: ссылается на тот класс, который был вызван в ходе

    выполнения class Animal { static function whoami() { echo &__CLASS&__; } public static function showMe() { static&::whoami(); } } class Cat extends Animal { static function whoami() { echo &__CLASS&__; } } Cat&::showMe(); &// Cat
  48. Сравнение разных обращений class Animal { static function whoami() {

    echo &__CLASS&__; } static function showMe() { static&::whoami(); } } class Cats extends Animal { static function whoami() { echo &__CLASS&__; } static function testAll() { Animal&::whoami(); &// Animal self&::whoami(); &// Cats parent&::whoami(); &// Animal static&::whoami(); &// Lion } } class Lion extends Cats { static function whoami() { echo &__CLASS&__; } } Lion&::testAll();
  49. Сравнение разных обращений class Animal { static function whoami() {

    echo &__CLASS&__; } static function showMe() { static&::whoami(); } } class Cats extends Animal { static function whoami() { echo &__CLASS&__; } static function testAll() { Animal&::showMe(); &// Animal self&::showMe(); &// Lion parent&::showMe(); &// Lion static&::showMe(); &// Lion } } class Lion extends Cats { static function whoami() { echo &__CLASS&__; } } Lion&::testAll();
  50. Если изменить область видимости, 
 static:: сдохнет class Animal {

    static function whoami() { echo &__CLASS&__; } public static function showMe() { static&::whoami(); } } class Cat extends Animal { private static function whoami() { echo &__CLASS&__; } } Cat&::showMe(); &// Fatal Error: &// Access level must be public