14 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	title, localeTitle
| title | localeTitle | 
|---|---|
| Polymorphism with Abstract and Interface | Полиморфизм с абстрактным и интерфейсом | 
Полиморфизм с абстрактным и интерфейсом
Совместное использование и принудительное исполнение кода с помощью полиморфизма с использованием абстрактного класса и интерфейса
Мы погрузимся глубже в объектно-ориентированное программирование и попытаемся подумать с точки зрения шаблонов проектирования для совместного использования и обеспечения соблюдения нашего кода с помощью полиморфизма.
Абстрактный класс
Предположим, у нас есть класс Man с некоторыми свойствами ( name , age , height , fav_drinks и fav_sports ) и методы ( giveFirmHandshakes , beStubborn и notPutToiletPaper ).
<?php 
 
 class Man 
 { 
    public $name; 
    public $age; 
    public $height; 
    public $fav_sports; 
    public $fav_drinks; 
 
    public function __construct($name, $age, $height) 
    { 
        $this->name = $name; 
        $this->age = $age; 
        $this->height = $height; 
    } 
 
    public function giveFirmHandshakes() 
    { 
        return "I give firm handshakes."; 
    } 
 
    public function beStubborn() 
    { 
        return "I am stubborn."; 
    } 
 
    public function notPutToiletPaper() 
    { 
        return "It's not humanly possible to remember to put toilet paper rolls when they are finished"; 
    } 
 } 
Нам нужно указать имя, возраст и высоту, чтобы создать экземпляр этого класса, как требуется конструктору.
<?php 
 $jack = new Man('Jack', '26', '5 Feet 6 Inches'); 
 
 echo sprintf('%s - %s - %s', $jack->name, $jack->age, $jack->height); 
 // => Jack - 26 - 5 Feet 6 Inches 
Теперь предположим, что мы хотим добавить новый метод в этот класс, называемый isActive.
Этот метод проверяет свойство активным и возвращает соответствующее сообщение в зависимости от значения active со значением по умолчанию false. Мы можем утверждать, что это верно для тех людей, которые активны.
<?php 
 
 class Man 
 { 
    public $name; 
    public $age; 
    public $height; 
    public $fav_sports; 
    public $fav_drinks; 
    public $active = false; 
 
    ..... 
    ..... 
 
    public function isActive() 
    { 
        if ($this->active == true) { 
            return "I am an active man."; 
        } else { 
            return "I am an idle man."; 
        } 
    } 
 } 
 
 $jack = new Man('Jack', '26', '5 Feet 6 Inches'); 
 $jack->active = true; 
 echo $jack->isActive(); 
 // => I am an active man. 
 
 $jake = new Man('Jake', '30', '6 Feet'); 
 echo "\n" . $jake->isActive(); 
 // => I am an idle man. 
Что делать, если человек не просто активен или не работает?
Что, если есть шкала от 1 до 4, которая измеряет, насколько активен человек (1 - холостой, 2 - слегка активный, 3 - умеренно активный, 4 - очень активный)?
У нас могут быть утверждения if..elseif ... такие как:
<?php 
 
 public function isActive() 
 { 
    if ($this->active == 1) { 
        return "I am an idle man."; 
    } elseif ($this->active == 2) { 
        return "I am a lightly active man."; 
    } elseif ($this->active == 3) { 
        return "I am a moderately active man."; 
    } else { 
        return "I am a very active man."; 
    } 
 } 
Теперь давайте сделаем еще один шаг.
Что, если активное свойство человека - это не просто целое число (1, 2, 3, 4 и т. Д.)?
Что, если значение активного «атлетическое» или «ленивое»?
Разве мы не должны добавлять другие инструкции elseif, которые ищут совпадение с этими строками?
Для такого сценария могут использоваться абстрактные классы.
С абстрактными классами вы в основном определяете класс как абстрактный и методы, которые вы хотите применять как абстрактные, без фактического ввода кода внутри этих методов.
Затем вы создаете дочерний класс, расширяющий родительский абстрактный класс и реализующий абстрактные методы в этом дочернем классе.
Таким образом, вы будете применять все дочерние классы для определения собственной версии абстрактных методов. Давайте посмотрим, как мы можем установить наш isActive() как абстрактный.
1: Определите класс как абстрактный.
<?php 
 abstract class Man 
 { 
 ..... 
 ..... 
 } 
2: Создайте абстрактный метод для метода, который вы хотите применить внутри абстрактного класса.
<?php 
 abstract class Man 
 { 
 ..... 
 ..... 
 abstract public function isActive(); 
 } 
3: Создайте дочерний класс, расширяющий абстрактный класс.
<?php 
 
 class AthleticMan extends Man 
 { 
 ..... 
 ..... 
 } 
4: Внедрить абстрактный метод внутри дочернего класса.
<?php 
 class AthleticMan extends Man 
 { 
    public function isActive() 
    { 
        return "I am a very active athlete."; 
    } 
 } 
5: Создайте дочерний класс (НЕ абстрактный класс).
<?php 
 $jack = new AthleticMan('Jack', '26', '5 feet 6 inches'); 
 echo $jack->isActive(); 
 // => I am a very active athlete. 
Полное описание и код реализации абстрактного класса:
<?php 
 
 abstract class Man 
 { 
    public $name; 
    public $age; 
    public $height; 
    public $fav_sports; 
    public $fav_drinks; 
 
    public function __construct($name, $age, $height) 
    { 
        $this->name = $name; 
        $this->age = $age; 
        $this->height = $height; 
    } 
 
    public function giveFirmHandshakes() 
    { 
        return "I give firm handshakes."; 
    } 
 
    public function beStubborn() 
    { 
        return "I am stubborn."; 
    } 
 
    public function notPutToiletPaper() 
    { 
        return "It's not humanly possible to remember to put toilet paper rolls when they are finished"; 
    } 
 
    abstract public function isActive(); 
 } 
 
 class AthleticMan extends Man 
 { 
    public function isActive() 
    { 
        return "I am a very active athlete."; 
    } 
 } 
 
 $jack = new AthleticMan('Jack', '26', '5 feet 6 inches'); 
 echo $jack->isActive(); 
 // => I am a very active athlete. 
В этом коде вы заметите, что абстрактный абстрактный метод isActive() определен внутри абстрактного класса Man и реализуется внутри дочернего класса AthleticMan .
Теперь класс Man не может быть создан непосредственно для создания объекта.
<?php 
 $ted = new Man('Ted', '30', '6 feet'); 
 echo $ted->isActive(); 
 // => Fatal error:  Uncaught Error: Cannot instantiate abstract class Man 
Кроме того, каждый дочерний класс абстрактного класса (класс Man ) должен реализовать все абстрактные методы. Отсутствие такой реализации приведет к фатальной ошибке.
<?php 
 class LazyMan extends Man 
 { 
 
 } 
 
 $robert = new LazyMan('Robert', '40', '5 feet 10 inches'); 
 echo $robert->isActive(); 
 // => Fatal error:  Class LazyMan contains 1 abstract method 
 // => and must therefore be declared abstract or implement 
 // => the remaining methods (Man::isActive) 
Используя абстрактные классы, вы можете применять определенные методы, которые будут реализованы индивидуально дочерними классами.
Интерфейс
Существует еще одна концепция объектно-ориентированного программирования, которая тесно связана с абстрактными классами, называемыми интерфейсом.
Единственная разница между абстрактными классами и интерфейсами заключается в том, что в абстрактных классах вы можете иметь сочетание определенных методов ( giveFirmHandshakes() , isStubborn() и т. Д.) И абстрактных методов ( isActive() ) внутри родительского класса, тогда как в интерфейсах, вы можете определять методы (не реализуйте) внутри родительского класса.
Давайте посмотрим, как мы можем преобразовать абстрактный класс Man выше в интерфейс.
1: Определите интерфейс со всеми методами (используйте интерфейс вместо класса).
<?php 
 interface Man 
 { 
    public function __construct($name, $age, $height); 
 
    public function giveFirmHandshakes(); 
 
    public function beStubborn(); 
 
    public function notPutToiletPaper(); 
 
    public function isActive(); 
 } 
2: Создайте класс, реализующий интерфейс (используйте инструменты вместо расширений). Этот класс должен реализовать ВСЕ методы, определенные внутри интерфейса, включая метод конструктора.
<?php 
 class AthleticMan implements Man 
 { 
    public $name; 
    public $age; 
    public $height; 
 
    public function __construct($name, $age, $height) 
    { 
        $this->name = $name; 
        $this->age = $age; 
        $this->height = $height; 
    } 
 
    public function giveFirmHandshakes() 
    { 
        return "I give firm handshakes."; 
    } 
 
    public function beStubborn() 
    { 
        return "I am stubborn."; 
    } 
 
    public function notPutToiletPaper() 
    { 
        return "It's not humanly possible to remember to put toilet paper rolls when they are finished"; 
    } 
 
    public function isActive() 
    { 
        return "I am a very active athlete."; 
    } 
 } 
3: Создайте исполняемый класс (AthleticMan)
<?php 
 $jack = new AthleticMan('Jack', '26', '5 feet 6 inches'); 
 echo $jack->isActive(); 
 // => I am a very active athlete. 
С интерфейсами вам нужно иметь в виду, что:
- 
Методы не могут быть реализованы внутри интерфейса. 
- 
Переменные (свойства) не могут быть определены внутри интерфейса. 
- 
Все методы, определенные внутри интерфейса, должны быть реализованы в классе child (implementation). 
- 
Все необходимые переменные должны быть определены внутри дочернего класса. 
- 
Интерфейс Man наставляет свои классы реализации для реализации всех методов в интерфейсе. 
Итак, что такое использование интерфейсов?
Разве мы не можем просто создать новый класс AthleticMan и создать все методы вместо реализации интерфейса?
Именно здесь разрабатываются шаблоны проектирования .
Интерфейсы используются, когда есть базовый класс ( Man ), который хочет заставить вас делать что-либо (создайте объект, giveFirmHandshakes, beStubborn, notPutToiletPaper и проверьте, активны ли вы), но не хочет точно сказать вам, как это сделать ,
Вы можете просто начать реализацию классов с реализацией, как вы сочтете нужным.
Пока все методы реализованы, интерфейсу Man все равно, как это сделать.
Мы рассмотрели, как и когда использовать абстрактные классы и интерфейсы в PHP. Использование этих концепций ООП для классов с разной функциональностью, использующих один и тот же базовый «план» (абстрактный класс или интерфейс), называется полиморфизмом.