Трейты: множественное наследование в 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 [1443 просмотра]