PHP already has horizontal inheritance. They're called traits. How is this an improvement in anyway?
On Sat, Mar 11, 2017 at 1:36 AM, Michael Vostrikov < michael.vostri...@gmail.com> wrote: > Hello. I have an idea which seems rather useful. I would like to know your > opinion, > > Let's say we have class Rectangle and need to have class Square which will > be used in some operations. We don't need any rectangle, this must be only > square. > What if we could describe a type which is the same as another type but have > some restrictions for properties? > > Something like this: > > class Rectangle > { > private $x; > private $y; > private $width; > private $height; > > public function __construct($x, $y, $width, $height) > { > $this->x = $x; > $this->y = $y; > $this->width = $width; > $this->height = $height; > } > } > > class Square variant of Rectangle > { > public function __match() > { > if ($this->width != $this->height) { > return ['width' => 'Width and height have to be the same']; > } > > return true; > } > } > > function drawSquare(Square $square) > { > // ... > } > > $rectangle = new Rectagle(0, 0, 10, 10); > drawSquare($rectangle); > > When drawSquare() is called, the check 'instanceof' is performed. It calls > magic method __match(). > If __match() does not return true, it throws an exception with the data > returned: > 'Order does not match OrderForCheckout. Reason: ...'. > > > Technically, we don't have method __match() in $rectangle object. So it can > be static, or a proxy object can be created here. > > The second variant can be extended. > We may not to inherit implementation of methods, and describe another > interface instead, for example new object can be read only. > > class Square variant of Rectangle > { > public function ___match() > { > // ... > } > > public function getWidth() > { > return parent::getWidth(); > } > } > > With some changes in syntax it can be defined in this way: > > class Square variant of Rectangle > { > ... > > getWidth: base::getWidth; > } > > > This is like inheritance, but semantically differs a little. > Inheritance has vertical direction, type variants have horisontal one. > Also type variants have an access for all methods and properties of base > class, even for private. > > > Another example. Let's say we have an order checkout process which is > splitted into 3 steps - cart for products, date page, delivery address > page. > This is not an input validation, this is a validation in business logic. > > class Order > { > public $products; > public $date; > public $address; > } > > class OrderForCheckout variant of Order > { > public function __match() > { > $errors = []; > if (empty($this->products)) { > $errors['products'] = 'Product list is empty'; > } > if ($this->date === null) { > $errors['date'] = 'Date is not selected'; > } > if (empty($this->products)) { > $errors['address'] = 'Address is not selected'; > } > > return (empty($errors) ? true : $errors); > } > } > > public function checkout(OrderForCheckout $order) > { > ... > } > > $order = findCurrentOrder(); > checkout($order); // if $order does not match requirements, the exception > will be thrown >