An abstract class cannot be instantiated; children must implement its abstract methods, which suits a template method. final forbids extending a class or overriding a method, constant (8.1) or property (8.4); PHP 8.5 allows it on promoted parameters, implying public.
<?php
abstract class Discount {
public function __construct(final public string $code) {} // PHP 8.5: final promoted
abstract protected function amountOff(int $sub): int; // no body
public function apply(int $sub): int { return max(0, $sub - $this->amountOff($sub)); }
}
final class PercentOff extends Discount {
public function __construct(string $code, private int $pct) { parent::__construct($code); }
protected function amountOff(int $sub): int { return intdiv($sub * $this->pct, 100); }
}
echo new PercentOff('SAVE10', 10)->apply(4200), "\n";
try { new Discount('X'); } catch (Error $e) { echo $e->getMessage(), "\n"; }Output
3780 Cannot instantiate abstract class Discount
Breaking final is a compile-time fatal error that stops the whole file: a class Bad that redeclares $code gets "Cannot override final property Discount::$code", and one extending PercentOff gets "Class Bad cannot extend final class PercentOff". Make leaf classes final.