БлогNot. Трейты: множественное наследование в PHP

Трейты: множественное наследование в PHP

В PHP нет множественного наследования в "чистом виде", но начиная с версии 5.4 есть трейты, позволяющие его эмулировать.

Ниже показан пример, из которого видно, что трейты могут содержать как свойства, так и методы, а класс может использовать несколько трейтов. Трейты также могут использовать ранее определённые трейты, а классы-потомки (в примере это класс Rectangle) - трейты, которые применял класс-родитель (Point), соответственно, это даёт возможность построения сколь угодно сложных схем наследования.

Код выполнялся в актуальной сборке XAMPP с PHP 7.4.X.

<?php
 trait Formatter { //Трейт "Форматирование числа"
  private $fmt = '%.3F';
  function format($x) { return sprintf($this->fmt,$x); }
  function setFormat($fmt) { $this->fmt = $fmt; }
 }

 trait CartesianPoint { //Трейт "Точка в декартовых координатах"
  use Formatter; //Использует другой трейт
  function quad ($x=0, $y=0) { //Координатная четверть
   $q = 0;
   if ($x > 0) {
    if ($y > 0) $q = 1;
    else if ($y < 0) $q = 4;
   }
   else if ($x < 0) {
    if ($y > 0) $q = 2;
    else if ($y < 0) $q = 3;
   }
   return $this->format($q); //0, если хотя бы одна из координат равна 0
  }
 }

 trait PolarPoint { //Трейт "Точка в полярных координатах"
  use Formatter;
  function ro ($x=0, $y=0) { //Полярный радиус
   return $this->format(sqrt(pow($x, 2) + pow($y, 2))); 
  }
  function phi ($x=0, $y=0) { //Полярный угол [0; 2*pi[
   $p = 0;
   if ($x != 0) {
    $p = atan ($y / $x);
    if ($x > 0) {
     if ($y < 0) $p += 2 * pi();
    }
    else $p += pi();
   }
   else {
    if ($y > 0) $p = pi() / 2;
    else if ($y < 0) $p = 3 * pi() / 2;
    else $p = 0; //при $r == 0, ответ - произвольное вещественное число
   }
   return $this->format($p);
  }
 }

 class Point { //Класс "Точка"
  use CartesianPoint, PolarPoint; //Использует трейты
  public $x, $y;
  function __construct ($x=0, $y=0) { $this->x = $x; $this->y = $y; }
  function __toString () { return '('.$this->format($this->x).','.$this->format($this->y).')'; }
 } 

 $a = new Point (1,1);
 echo 'Point: '.$a.
  '<br>Quadrant: '.$a->quad($a->x,$a->y).
  '<br>Polar: ('.$a->ro($a->x,$a->y).','.$a->phi($a->x,$a->y).')';

 class Rectangle extends Point { //Класс "Прямоугольник" расширяет "Точку", может использовать её трейты
  public $w, $h; //ширина и высота
  function __construct ($x=0, $y=0, $w=0, $h=0) {
   parent::__construct ($x,$y);
   $this->w = $w; $this->h = $h;
  }
  function __toString () { 
   return parent::__toString().' - ('.
    $this->format($this->x+$this->w).','.$this->format($this->y+$this->h).')';
  }
  function perimeter() { return 2*$this->w + 2*$this->h; }
  function area() { return $this->w * $this->h; }
 }

 $r = new Rectangle (0,0,4,3);
 $r->setFormat('%.2F'); //используем метод трейта
 echo '<br>Rectangle: '.$r.
  '<br>Perimeter: '.$r->perimeter().
  '<br>Area: '.$r->area();
?>

20.08.2020, 23:37 [1433 просмотра]


теги: программирование учебное php

К этой статье пока нет комментариев, Ваш будет первым