Kirill
Но там будет ошибка в LoginResponse потом, т.к. getResponseClassName должен возвращать TResponse, а у тебя там захардкожен LoginResponse
Kirill
в данном примере кода работать будет, однако сама иерархия кривая и строчка /** @var Request<TResponse> $request */ будет работать до тех пор, пока TResponse внутри instanceof LoginResponse
Вадим
Вадим
подскажите где почитать нормально про дженерики?
Вадим
CoreRequestInterface<TResponse>
что означают вот эти угловые скобки?
CoreRequestInterface содержит TResponse?
CoreRequestInterface использует TResponse?
CoreRequestInterface работает с TResponse?
Юра
Вадим
как мне сказать что CoreBaseHandler::handle должен принимать любые реквесты интерфейса CoreRequestInterface и отдавать респонс который содержится в ревесте?
Вадим
Вадим
:)
Kirill
Kirill
типа:
@template TArg of Response
@param Request<TArg> $request
@return TArg
Kirill
Kirill
дженерики - это просто возможность передать конкретный тип как аргумент)
Юра
вообщем
Юра
Type<A> не связан никак с Type<B>
Юра
читай про generic variance
Kirill
ну потому что другие аргументы, да
Юра
но я не смог победить
Kirill
Юра
пофиг
Kirill
да не пофигу)
Юра
нужно явно говорить
Kirill
а ещё мы забываем про ковариантные параметры)
Kirill
и про call-side variance)
Юра
вопрос по дефолту как в пхпстане
Юра
если параметр под дефолту invariant то Type<A> != Type<B> даже если A instanceof B
Kirill
Kirill
B - интерфейс, A - реализация
Kirill
$values = list<B>
Kirill
ты запросто туда можешь пихать реализации
Kirill
в чём проблема?
Kirill
я просто не понимаю твоего "никак не связан"
Kirill
связан напрямую же, если они в цепочке наследования
Вадим
Вадим
но теперь CoreRequestInterface должен быть дженериком
Kirill
Kirill
у тебя не параметр зависит от типа, а сам класс)
Вадим
Kirill
ну вот это уже выглядит как более реально к тому, что тебе нужно
Kirill
ты передаёшь аргумент интерфейса, а должен вернуться респонз из этого интерфейса
Kirill
точнее объект респонза из класса, который возвращается в методе интерфейса, который должен быть инстанс оф КорБазРеквест
Вадим
Kirill
а интерфейс выглядит примерно так, судя по твоему скрину:
/** @template-covariant TResponse of ResponseInteface */
interface CoreRequestInterface
{
/** @return class-string<TResponse> */
public function getReponseClassName(): string;
}
Kirill
влом нормально форматировать код в телеге)
Вадим
Юра
Kirill
а, понял про что ты
Kirill
/** @var list<B> */
$values = [];
$values[] = new A(); // class A implements B
Юра
Угу
Юра
И теперь сделай $c = $values[0]
Kirill
ну $c будет B
Юра
Да
Kirill
только ещё есть такая штука как self-out)
Юра
Но ковариантность это не про B
Юра
Это про List<B>
Kirill
т.е. можно во время вызова подменить аргумент темплейта
Юра
И List<A>
Kirill
и сделать list<A> после вызова
Kirill
https://phpstan.org/writing-php-code/phpdocs-basics#change-type-of-current-object-after-calling-a-method
Юра
У него короче стан ругается что типы не совпадают так как они разные
Юра
Потому что List<A> не равняется по дефолту лист Б
Kirill
ну в твоём варианте Type<B> != Type<A>
Kirill
Юра
Ну так посмотри пхпстан коллекций пхпшных
Kirill
Юра
Kirill
на то что у него стоит Request без типа, а темплейт аргумент захардкожен
Kirill
решается добавлением 1ой строчки
Юра
Напиши два листа с такими типами и попробуй покопировать туда сюда
Вадим
тэк, вроде в песочнице ошибки ушли, пойду в проект
ребята, спасибо!
Kirill
Kirill
это очевидно
Kirill
что ты хочешь этим доказать-то?
Юра
Что по умолчанию ты не можешь заменить MyArray<ParentClass> на MyArray<ChildClass>
Юра
Хоть ChildClass instanceof ParentClass