Re: Type variants
| From: | Sherif Ramadan | Date: | Sun, 12 Mar 2017 05:58:44 +0000 |
| Subject: | Re: Type variants | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-98487@lists.php.net to get a copy of this message | ||
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.vostrikov@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
>