Валентин @vudaltsov
Полиморфизм — возможность существования чего-либо в различных формах.
function array_map(callable $callback, array $array): array
{
// ...
}
$callable = 'date';
$callable = static fn (int $time) => new DateTimeImmutable("@$time");
$callable = [new DateTimeImmutable(), 'modify'];
$callable = [DateInterval::class, 'createFromDateString'];
$callable = new class {
private const string FORMAT = 'd.m.Y';
public function __invoke(string $time): DateTimeImmutable
{
return DateTimeImmutable::createFromFormat(self::FORMAT, $time);
}
};
function array_map(callable $callback, array $array): array
{
// одинаковая логика для любого callback
}
/**
* @template TKey of array-key
* @template TInputValue
* @template TOutputValue
* @param callable(TInputValue): TOutputValue $callback
* @param array<TKey, TInputValue> $array
* @return array<TKey, TOutputValue>
*/
function array_map(callable $callback, array $array): array
{
// одинаковая логика для любого массива
}
array_map($callback, $array, $array2);
/**
* @template TInputValue
* @template TInputValue2
* @template TOutputValue
* @param callable(TInputValue, TInputValue2): TOutputValue $callback
* @param array<TInputValue> $array
* @param array<TInputValue2> $array2
* @return list<TOutputValue>
*/
function array_map(callable $callback, array $array, array $array2): array
{
// кастомная логика для нескольких массивов
}
var_dump(array_map(null, ['a', 'b', 'c'], [0, 1]));
array(3) {
[0] => array(2) {
[0] => string(1) "a"
[1] => int(0)
}
[1] => array(2) {
[0] => string(1) "b"
[1] => int(1)
}
[2] => array(2) {
[0] => string(1) "c"
[1] => NULL
}
}
/**
* @template TInputValue
* @template TInputValue2
* @param array<TInputValue> $array
* @param array<TInputValue2> $array2
* @return list<array{TInputValue, TInputValue2}>
*/
function array_map(null $callback, array $array, array $array2): array
{
// zip-логика
}
function array_map(?callable $callback, array $array, array ...$arrays): array
{
if ($callback === null) {
// zip-логика
}
if (count($arrays) > 0) {
// логика для нескольких массивов
}
// логика для одного массива
}
fun <TKey, TInputValue, TOutputValue> array_map(
callback: (TInputValue) -> TOutputValue,
array: Map<TKey, TInputValue>,
): Map<TKey, TOutputValue>
fun <TInputValue, TInputValue2, TOutputValue> array_map(
callback: (TInputValue, TInputValue2) -> TOutputValue,
array: Map<Any, TInputValue>,
array2: Map<Any, TInputValue2>,
): List<TOutputValue>
fun <TInputValue, TInputValue2> array_map(
array: Map<Any, TInputValue>,
array2: Map<Any, TInputValue2>,
): List<Pair<TInputValue, TInputValue2>>
interface I
{
public function do(string $a): iterable;
}
final class C implements I
{
public function do(
int|string $a,
SplFileInfo $b = new SplFileInfo(__FILE__),
): array
{
return [];
}
}
interface Website {}
final class Yii implements Website {}
final class Symfony implements Website {}
interface Developer
{
public function fix(Yii|Symfony $site): void;
public function build(): Yii|Symfony;
}
interface Developer
{
public function fix(Yii|Symfony $site): void;
public function build(): Yii|Symfony;
}
final class Taylor
{
public function fix(Symfony|Laravel $site): void
{
// fix bugs...
}
public function build(Lamborgini $lamborgini): Symfony|Laravel
{
if (random_int(0, 1) === 1) {
return new Symfony();
} else {
return new Laravel();
}
}
}
interface Developer
{
public function fix(Yii|Symfony $site): void;
public function build(): Yii|Symfony;
}
final class Vasya implements Developer
{
public function fix(Yii|Symfony|Laravel $site): void
{
// fix bugs...
}
public function build(?Lamborgini $lamborgini = null): Yii
{
if ($lamborgini === null) {
sleep(10);
}
return new Yii();
}
}
interface I
{
public function do(string $a): iterable;
}
final class C implements I
{
public function do(
int|string $a,
SplFileInfo $b = new SplFileInfo(__FILE__),
): array
{
return [];
}
}
interface Developer
{
public function fix(Yii|Symfony $site): void;
public function build(): Yii|Symfony;
}
final class Petya implements Developer
{
public function fix(Yii|Symfony $site): void
{
// fix bugs...
}
public function build(): Yii
{
// build...
}
}
interface Developer
{
public function fix(Yii|Symfony $site): void;
public function build(): Yii|Symfony;
}
final class Petya implements Developer
{
public function fix(Yii|Symfony $site): void
{
// fix bugs...
}
public function build(): Yii
{
sleep(1000);
return new Yii();
}
}
Subtype requirement. Let φ(x) be a property provable about objects x of type T. Then φ(y) should be true for objects y of type S where S is a subtype of T.
Subtype requirement. Let φ(x) be a property provable about objects x of type T. Then φ(y) should be true for objects y of type S where S is a subtype of T.
interface Website {}
final class Yii implements Website {}
final class Symfony implements Website {}
/**
* @template TWebsite of Website
*/
final class Portfolio
{
/**
* @var list<TWebsite>
*/
private array $websites = [];
/**
* @param TWebsite $website
*/
public function add(Website $website): void
{
$this->websites[] = $website;
}
/**
* @return list<TWebsite>
*/
public function all(): array
{
return $this->websites;
}
}
/** @template TWebsite of Website */
final class Portfolio
{
/** @param TWebsite $website */
public function add(Website $website): void { /** ... */ }
/** @return list<TWebsite> */
public function all(): array { /** ... */ }
}
/**
* @param Portfolio<Website> $portfolio
*/
function display(Portfolio $portfolio): void
{
var_dump($portfolio->all());
}
/**
* @var Portfolio<Symfony> $valentinsPortfolio
*/
$valentinsPortfolio = new Portfolio();
display($valentinsPortfolio);
/** @template TWebsite of Website */
final class Portfolio
{
/** @param TWebsite $website */
public function add(Website $website): void { /** ... */ }
/** @return list<TWebsite> */
public function all(): array { /** ... */ }
}
/**
* @param Portfolio<Website> $portfolio
*/
function addYii(Portfolio $portfolio): void
{
$portfolio->add(new Yii());
}
/**
* @var Portfolio<Symfony> $valentinsPortfolio
*/
$valentinsPortfolio = new Portfolio();
addYii($valentinsPortfolio);
/**
* @param Portfolio<Website> $portfolio
*/
function addYii(Portfolio $portfolio): void
{
$portfolio->add(new Yii());
}
/**
* @var Portfolio<Symfony> $valentinsPortfolio
*/
$valentinsPortfolio = new Portfolio();
addYii($valentinsPortfolio);
/**
* @template TWebsite of Website
*/
final class Portfolio
{
/** @param TWebsite $website */
public function add(Website $website): void { /** ... */ }
/** @return list<TWebsite> */
public function all(): array { /** ... */ }
}
@template (invariant) TWebsite:
Portfolio<Symfony> ⊆ Portfolio<Symfony>
Portfolio<Website> ⊆ Portfolio<Website>
Portfolio<Symfony> ⊄ Portfolio<Website>
/**
* @param Portfolio<Website> $portfolio
*/
function addYii(Portfolio $portfolio): void
{
$portfolio->add(new Yii());
}
/**
* @var Portfolio<Symfony> $valentinsPortfolio
*/
$valentinsPortfolio = new Portfolio();
addYii($valentinsPortfolio);
/**
* @param Portfolio<Website> $portfolio
*/
function display(Portfolio $portfolio): void
{
var_dump($portfolio->all());
}
/**
* @var Portfolio<Symfony> $valentinsPortfolio
*/
$valentinsPortfolio = new Portfolio();
display($valentinsPortfolio);
/**
* @param Portfolio<Website> $portfolio
*/
function display(Portfolio $portfolio): void
{
var_dump($portfolio->all());
}
/**
* @var Portfolio<Symfony> $valentinsPortfolio
*/
$valentinsPortfolio = new Portfolio();
display($valentinsPortfolio);
@template (covariant) TWebsite:
Portfolio<Symfony> ⊆ Portfolio<Symfony>
Portfolio<Website> ⊆ Portfolio<Website>
Portfolio<Symfony> ⊆ Portfolio<Website>
/**
* @template-covariant TWebsite of Website
*/
final class Portfolio
{
/** @param TWebsite $website */
public function add(Website $website): void { /** ... */ }
/** @return list<TWebsite> */
public function all(): array { /** ... */ }
}
/**
* @template-covariant TWebsite of Website
*/
interface PortfolioRead
{
/** @return list<TWebsite> */
public function all(): array;
}
/**
* @template TWebsite of Website
* @implements PortfolioRead<TWebsite>
*/
final class Portfolio implements PortfolioRead
{
/** @param TWebsite $website */
public function add(Website $website): void { /** ... */ }
public function all(): array { /** ... */ }
}
/**
* @param PortfolioRead<Website> $portfolio
*/
function display(PortfolioRead $portfolio): void
{
var_dump($portfolio->all());
}
/**
* @var Portfolio<Symfony> $valentinsPortfolio
*/
$valentinsPortfolio = new Portfolio();
display($valentinsPortfolio);
/** @template TWebsite of Website */
final class Portfolio
{
// ...
}
/**
* @param Portfolio<covariant Website> $portfolio
*/
function display(Portfolio $portfolio): void
{
var_dump($portfolio->all());
}
/**
* @var Portfolio<Symfony> $valentinsPortfolio
*/
$valentinsPortfolio = new Portfolio();
display($valentinsPortfolio);
/**
* @param Portfolio<covariant Website> $portfolio
*/
function addYii(Portfolio $portfolio): void
{
$portfolio->add(new Yii());
}
/**
* @var Portfolio<Symfony> $valentinsPortfolio
*/
$valentinsPortfolio = new Portfolio();
addYii($valentinsPortfolio);
@vudaltsov / Пых / PHP Point / PHP умирает?!