freeCodeCamp/guide/russian/php/polymorphism-abstract-inter.../index.md

14 KiB
Raw Blame History

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. Использование этих концепций ООП для классов с разной функциональностью, использующих один и тот же базовый «план» (абстрактный класс или интерфейс), называется полиморфизмом.