v3shin
@v3shin
Веб-шаман

Как добавить синтаксический сахар, связанный с оператором в php?

Есть желание создать класс, который можно было бы использовать с математическими операторами. Что-то типа:
class N {
    private $n;
    public function __construct($n = 0) {
        $this->n = $n;
    }
    // ???
}

$a = new N(5);
$b = new N(2);
echo $a - $b;

Вопрос в том, реализуемо ли это в таком виде или придется писать метод типа getValue() и затем echo $a->getValue() - $b->getValue();?
  • Вопрос задан
  • 137 просмотров
Решения вопроса 1
Maksclub
@Maksclub Куратор тега PHP
maksfedorov.ru
Проблема 0: В PHP нет перегрузки операторов и магических методов как в Пайтоне под такое дело

Вариант 1: Условно функциональный
Можно например так (если конечно вам подойдет)
$a() - $b()

Тогда надо просто __invoke() реализовать в каждом из классов

Плюс такого, что в $a или $b может быть не только класс, но callable
<?php

class N {
    private int $n;
    public function __construct(int $n = 0) {
        $this->n = $n;
    }

    public function __invoke(): int {
        return $this->n;
    }
}

$a = new N(5);
$b = fn() => 100;

var_dump($a() - $b()); // -95


И даже на лету передавать аргументы, например мультипликатор:
<?php

class N {
    private int $n;
    public function __construct(int $n = 0) {
        $this->n = $n;
    }

    public function __invoke(int $multiplier = 1): int {
        return $multiplier * $this->n;
    }
}

$a = new N(5);
$b = fn(int $multiplier = 1) => $multiplier * 100;

var_dump($a(100) - $b()); // 400
sandbox.onlinephpfunctions.com/code/331eef7f9ad530...
А можно передавать еще callable :) Крч вот вариант функциональный очень гибкий
Или наоборот в конструкторе зашить мультипликатор, а сами числа передавать на лету, по-разному можно сделать

Вариант 2: Value Object
Можно посомтреть как сделан интерфейс например у объекта DateTime и увидеть, как работает diff() (разница времени) и можно сделать похожий интерфейс

<?php

interface NumericInterface {
    public function add(Numeric $second): NumericInterface;
    public function toInt(): int;
}

class Numeric implements NumericInterface {
    private $n;
    
    public function __construct($n = 0) {
        $this->n = $n;
    }

    public function add(Numeric $second): self {
        return new self($second->n +  $this->n);
    }
    
    
    public function toInt(): int {
        return $this->n;
    }
}

$num1 = new Numeric(10);
$num2 = new Numeric(18);

$result = $num1->add($num2)->toInt();

var_dump($result); // 28
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы