Hooks on Interfaces

Hooks on Interfaces and Promoted Properties

An interface (Interfaces and Generators) can now declare a property: public int $priceCents { get; } promises a readable one, { get; set; } a writable one. A class satisfies it with a plain, hooked or virtual property, and abstract classes declare abstract properties the same way. Hooks also work on promoted constructor parameters.

A property contract met by a stored property and by a computed onePHP
<?php
interface Priced { public int $priceCents { get; } }        // a property in an interface
final class Book implements Priced {
  public function __construct(
    public string $title { set => trim($value); },           // hook on a promoted property
    public int $priceCents = 0,                               // a plain property satisfies it
  ) {}
}
final class Bundle implements Priced {
  public function __construct(private array $items) {}
  public int $priceCents {                                    // virtual: summed on each read
    get => array_sum(array_map(fn(Priced $p) => $p->priceCents, $this->items));
  }
}
$b = new Book('  LAMP Stack Development ', 3990);
echo "[{$b->title}] ", new Bundle([$b, new Book('PHP Pocket Guide', 1500)])->priceCents, "\n";
Output
[LAMP Stack Development] 5490

The contract hides how the value is produced, so Bundle could switch from computing to caching without touching a caller. Declare interface properties only for data; behavior still belongs in methods.