Ниже приведен конкретный пример ситуации, с которой я иногда сталкиваюсь с параметризованными типами. В принципе, есть параметры типа, которые, как я знаю, совместимы, но я не знаю, как доказать это для некоторых частей кода.
Я пишу маршрутизатор запросов, который сопоставляет URL-адреса с функциями обработчика. Ниже приведен упрощенный код. Я создаю List[Route]
, где Route
- это пара UrlMatcher, Function
.
class Route[A](matcher: UrlMatcher[A], handler: HandlerFunction[A])
abstract class UrlMatcher[A] {
def match(url: String): Option[A] // None if no match
Параметр типа A
предназначен для «аргументов», которые средство сопоставления может извлечь из URL-адреса. Они будут переданы функции-обработчику. Например, UrlMatcher[Int]
, который видит путь URL-адреса вида «/ users / 123», может передать 123 функции getUser(id: Int)
. Маршрутизатор может выглядеть так:
val routes = ArrayBuffer[Route[_]]
def callHandler(url: String) {
for (r <- routes) {
val args = r.matcher.matchUrl(url)
if (args.isDefined)
r.handler(args.get) // <--- error here
}
Проблема в том, что я получаю ошибки несоответствия типов, потому что не знаю, как сказать, что эти два типа одинаковы.
type mismatch; found: args.type (with underlying type Option[Any])
required: _$1
Я знаю, что могу переделать его так, чтобы Route
имел такой метод, как matchAndCall
, но я бы хотел сохранить этот логический поток, если это возможно.
Обновить / изменить
Я не совсем понимаю экзистенциальные типы, но я пробовал это ...
val routes = ArrayBuffer[T forSome { type T }]()
И это устранило ошибку несоответствия выше. Однако у меня есть еще один, куда я вставлял ArrayBuffer
.
def route[P](matcher: UrlMatcher[P], handler: Handler[P]): AbstractRoute = {
val route = new Route(matcher, handler)
otherRoutes.append(route) // error here
route
}
Теперь ошибка ...
type mismatch; found : Route[P] required: Route[T forSome { type T }] Note: P <: T
forSome { type T }, but class Route is invariant in type P. You may wish to define
P as +P instead. (SLS 4.5)
Почему P
несовместимо с T
, поскольку они не ограничивают T
?