PHP Учебник

PHP Старт Введение в PHP Установка PHP Синтаксис PHP Комментарии в PHP Переменные PHP PHP Echo / Print Типы данных PHP Строки PHP Числа PHP Математика в PHP Константы PHP Операторы PHP PHP If...Else...Elseif PHP Switch Циклы в PHP Функции PHP Массивы PHP PHP Суперглобальные PHP RegEx

PHP Формы

Обработка форм PHP Валидация форм PHP Обязательные поля Валидация URL/E-mail Полная форма PHP

PHP Продвинутый

PHP Дата и время PHP Include/Require PHP Работа с файлами Открытие/Чтение файлов Создание/Запись файлов PHP Загрузка файлов Файлы cookie PHP Сессии PHP Фильтры PHP Расширенные фильтры PHP Функция Callback PHP JSON PHP Исключения

PHP OOP

Что такое ООП в PHP Классы/Объекты PHP Цепочки методов PHP Конструктор PHP Деструктор PHP Модификаторы доступа Наследование в PHP Константы класса PHP Подсказка типов PHP Подсказка интерфейсов Абстрактные классы PHP PHP Интерфейсы PHP Полиформизм PHP Трейты Статические методы PHP Статические свойства PHP Пространства имен PHP Итерируемые объекты

База данных MySQL

База данных MySQL Подключение к MySQL Создание БД MySQL Создание таблицы MySQL Вставка данных MySQL Получить ID MySQL Подготовленные операторы PHP MySQL Получение данных MySQL Предложение WHERE Предложение ORDER BY Обновление данных MySQL Удаление данных БД MySQL Limit Data

PHP XML

Парсеры PHP XML Парсер PHP SimpleXML Получить PHP SimpleXML PHP XML Expat PHP XML DOM

PHP - AJAX

AJAX Введение AJAX PHP AJAX База Данных AJAX XML AJAX Живой поиск AJAX Опрос

PHP Примеры

PHP Примеры Практика ООП PHP PHP квиз-тест Упражнения Базовый PHP Упражнения Алгоритмы Упражнения Массивы Упражнения Цикл for Упражнения Функции Регулярные выражения Упражнения Дата PHP Упражнения Строки PHP Математика PHP Упражнения Формы PHP Упражнения Классы PHP Упражнения JSON PHP PHP Задачник


Подсказка типов данных для интерфейсов в PHP




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


Давайте Напишем следующий сценарий: менеджер компании по аренде автомобилей, которая арендует только BMW, нанял программиста, чтобы он написал программу, которая рассчитывает цену за полный бак бензина для каждого автомобиля, которым владеет компания. В соответствии с этими требованиями программист пишет класс Bmw, который содержит код задачи. Этот класс содержит данные о BMW, включая номерной знак, модель автомобиля и, что наиболее важно, метод, который вычисляет объем топливного бака.

Функция, вычисляющая объем, называется calcTankVolume. Этот метод рассчитывает объем топливного бака путем умножения площади основания (квадрата длины ребер основания) на высоту. Высота, а также длина ребер основания и номерной знак вводятся в класс через конструктор:

Пример

<?php
class Bmw {
 
  protected $model;
  protected $rib;
  protected $height;
   
  // Свойства вводятся в класс через конструктор
  public function __construct($model, $rib, $height)
  {
    $this -> model = $model;
    $this -> rib = $rib;
    $this -> height = $height;
  }
 
  // Рассчитать объем бак для прямоугольных резервуаров
  public function calcTankVolume()
  {
    return $this -> rib * $this -> rib * $this -> height;
  } 
}
?>

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

Пример

<?php
// Подсказка типа гарантирует, что функция получит только объекты Bmw в качестве аргументов
function calcTankPrice(Bmw $bmw, $pricePerLitr)
{
    return $bmw -> calcTankVolume() * $pricePerLitr . "$";
}
?>

Теперь он может легко подсчитать, сколько стоит полный бак бензина для BMW. Например, для автомобиля с номерным знаком 777 длина ребра 3.5 дм на высоту 5 дм и использование бензина по цене 1 доллар за литр:

Пример

<?php
$bmw1 = new Bmw('777', 3.5, 5); 
echo calcTankPrice($bmw1, 1);
?>

Результат: 61,25$

Через короткое время менеджер решает ввести в свой парк автомобилей новый Mercedes, но проблема в том, что функция calcTankPrice() может выполнять вычисления только для BMW. Оказывается, если у BMW бензобак прямоугольной формы, то у Mercedes — бензобак цилиндрической формы. Итак, наш программист снова призван написать другой класс, который сможет справиться с этой новой задачей. С этой целью наш программист теперь пишет следующий класс с именем Mercedes, который может вычислять объем бака для баков цилиндрической формы:

Пример

<?php
class Mercedes {
  protected $model;
  protected $radius;
  protected $height;
   
  public function __construct($model, $radius, $height)
  {
    $this -> model = $model;
    $this -> radius = $radius;
    $this -> height = $height;
  }
   
  // Рассчитывает объем цилиндра
  public function calcTankVolume()
  {
    return $this -> radius * $this -> radius * pi() * $this -> height;
  }
}
?>

Когда наш программист выполнил задачу по написанию класса Mercedes, он попытался посчитать стоимость полного бака бензина для Mercedes:

Пример

<?php
$mercedes1 = new Mercedes('555', 1.8, 7); 
echo calcTankPrice($mercedes1, 1);
?>

Однако результат оказался не совсем таким, как он ожидал:

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

Catchable fatal error: Argument 1 passed to calcTankPrice() must be an instance of Bmw, instance of Mercedes given

Это сообщение об ошибке является результатом того, что в функцию не был передан правильный объект, поскольку он пытался передать объект Mercedes в функцию calcTankVolume(), тогда как функция может принимать только объекты, принадлежащие классу Bmw.

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

Итак, сначала он создал абстрактный класс с именем Car, от которого могут унаследоваться как Bmw, так и Mercedes (и, фактически, любая другая модель автомобиля):

Пример

<?php
abstract class Car {
  protected $model;
  protected $height;
     
  abstract public function calcTankVolume();
}
?>

Затем он реорганизовал классы Bmw и Mercedes, чтобы они унаследовали от класса Car:

Пример

<?php
class Bmw extends Car {
 
  protected $rib;
  
  public function __construct($model, $rib, $height)
  {
    $this -> model = $model;
    $this -> rib = $rib;
    $this -> height = $height;
  }
   
  // Расчет объема прямоугольного бака
  public function calcTankVolume()
  {
    return $this -> rib * $this -> rib * $this -> height;
  } 
}
 
 
class Mercedes extends Car {
  protected $radius;
   
  public function __construct($model, $radius, $height)
  {
    $this ->model = $model;
    $this -> radius = $radius;
    $this -> height = $height;
  }
 
  
  // Рассчитывает объем цилиндров
  public function calcTankVolume()
  {
    return $this -> radius * $this -> radius * pi() * $this -> height;
  }
}
?>

Следующее изображение может помочь нам лучше понять связь между интерфейсом Car и конкретными классами ( Bmw и Mercedes ), реализующими интерфейс для различных форм бензобаков:

Loop Flow

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

Пример

<?php
// Подсказка типа гарантирует, что функция получит только объекты 
// принадлежащие интерфейсу Car
function calcTankPrice(Car $car, $pricePerLitr)
{
  echo $car -> calcTankVolume() * $pricePerLitr . "$";
}
?>

Теперь посмотрим на результат, когда мы попытаемся использовать функцию calcTankPrice() как для объектов Bmw, так и для Mercedes:

Пример

<?php
$bmw1 = new Bmw('777', 3.5, 5); 
echo calcTankPrice($bmw1, 1);
 
$mercedes1 = new Mercedes('555', 1.8, 7); 
echo calcTankPrice($mercedes1, 1);
?>

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

61.25$
71.251321383417$

Примечание: Всякий раз, когда нам нужно сделать подсказку типа для нескольких связанных классов, мы должны использовать подсказку типа интерфейса.

Очень важный урок, который можно извлечь из приведенных выше примеров, — это важность программирования интерфейса. Когда программист сделал функцию calcTankPrice зависимой от класса Bmw, он ограничил использование класса только одним типом автомобиля. Но когда он решил сделать функцию зависимой от интерфейса, он разрешил использовать функцию для любого типа автомобиля и, таким образом, сделал ее более гибкой. Из этого можно сделать вывод, что программирование интерфейса делает код более гибким и готовым к изменениям.

<?php
abstract class Car {
  protected $model;
  protected $height;
     
  abstract public function calcTankVolume();
}
// Подсказка типа гарантирует, что функция получит только объекты 
// принадлежащие интерфейсу Car
function calcTankPrice(Car $car, $pricePerLitr)
{
  echo $car -> calcTankVolume() * $pricePerLitr . "$";
}

class Bmw extends Car {
 
  protected $rib;
  
  public function __construct($model, $rib, $height)
  {
    $this -> model = $model;
    $this -> rib = $rib;
    $this -> height = $height;
  }
   
  // Расчет объема прямоугольного бака
  public function calcTankVolume()
  {
    return $this -> rib * $this -> rib * $this -> height;
  } 
}
 
class Mercedes extends Car {
  protected $radius;
   
  public function __construct($model, $radius, $height)
  {
    $this ->model = $model;
    $this -> radius = $radius;
    $this -> height = $height;
  }
  
  // Рассчитывает объем цилиндров
  public function calcTankVolume()
  {
    return $this -> radius * $this -> radius * pi() * $this -> height;
  }
}

$bmw1 = new Bmw('777', 3.5, 5); 
echo calcTankPrice($bmw1, 1);
echo "<br>"; 
$mercedes1 = new Mercedes('555', 1.8, 7); 
echo calcTankPrice($mercedes1, 1);
?>

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

Toyota : 528
BMW : 533

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

В этом уроке вы узнали, как реализовать подсказку типов для интерфейсов в PHP. Кликните здесь, чтобы попрактиковаться в предмете.