| 530 | class MethodTemplateDemo |
| 531 | { |
| 532 | public function demo(): void |
| 533 | { |
| 534 | $locator = new ServiceLocator(); |
| 535 | $locator->get(Pen::class)->write(); // class-string<T> → T |
| 536 | |
| 537 | Factory::create(Pen::class)->write(); // static @template |
| 538 | resolve(Marker::class)->highlight(); // function @template |
| 539 | |
| 540 | $mapper = new ObjectMapper(); |
| 541 | $mapped = $mapper->wrap(new Pen()); |
| 542 | $mapped->first(); // → Pen (T resolved from argument) |
| 543 | |
| 544 | $mapper->wrap(new Product())->first()->getPrice(); // new expression arg → Product |
| 545 | |
| 546 | // Chained instantiation preserves constructor-inferred generics |
| 547 | (new ObjectMapper())->wrap(new Pen())->first()->write(); // (new ...)->method() chain with generics |
| 548 | |
| 549 | // Variadic class-string<T> → union return type |
| 550 | $locator2 = new ServiceLocator(); |
| 551 | $union = $locator2->getAny(Pen::class, Marker::class); |
| 552 | $union->write(); // A|B from variadic class-string<T> |
| 553 | $union->highlight(); |
| 554 | |
| 555 | // Nested generic return: @return Box<T> with class-string<T> param |
| 556 | $boxed = $locator->wrap(Pen::class); |
| 557 | $boxed->unwrap()->write(); // Box<T>::unwrap() → Pen |
| 558 | } |
| 559 | } |
| 560 | |
| 561 | |