3v4l.org

run code in 300+ PHP versions simultaneously
<?php abstract class Number { abstract public function primitive(): mixed; abstract public function add(Number $other): Number; abstract protected function addIntNumber(IntNumber $other): Number; abstract protected function addFloatNumber(FloatNumber $other): Number; public static function from(int|float $primitive): Number { return match (true) { is_int($primitive) => new IntNumber($primitive), is_float($primitive) => new FloatNumber($primitive), default => throw new InvalidArgumentException('blah blah'), }; } } class IntNumber extends Number { public function __construct( private int $value ) {} public function primitive(): int { return $this->value; } public function add(Number $other): Number { return $other->addIntNumber($this); } protected function addIntNumber(IntNumber $other): IntNumber { return new IntNumber($this->primitive() + $other->primitive()); } protected function addFloatNumber(FloatNumber $other): FloatNumber { return new FloatNumber((float) $this->primitive() + $other->primitive()); } } class FloatNumber extends Number { public function __construct( private float $value ) {} public function primitive(): float { return $this->value; } public function add(Number $other): Number { return $other->addFloatNumber($this); } protected function addIntNumber(IntNumber $other): FloatNumber { return new FloatNumber($this->primitive() + (float) $other->primitive()); } protected function addFloatNumber(FloatNumber $other): FloatNumber { return new FloatNumber($this->primitive() + $other->primitive()); } } $primitives = [1, 2, 7.13, 5.012]; $numbers = array_map([Number::class, 'from'], $primitives); $carry = new IntNumber(0); foreach ($numbers as $number) { $carry = $carry->add($number); echo '$number: ', get_class($number), ' ', $number->primitive(), PHP_EOL; echo '$carry: ', get_class($carry), ' ', $carry->primitive(), PHP_EOL; echo PHP_EOL; }

preferences:
30.97 ms | 404 KiB | 5 Q