下面是我有时在使用参数化类型时遇到的一种情况的具体实例。基本上,我知道有些类型参数是兼容的,但我不知道如何向代码的某些部分证明这一点。
我正在编写一个将 url 映射到处理函数的请求路由器。下面是一些简化的代码。我创建了一个List[Route]
,其中 aRoute
基本上是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
type 参数A
用于匹配器可能从 URL 中提取的“参数”。它们将被传递给处理函数。例如,UrlMatcher[Int]
看到像“/users/123”这样的 URL 路径的 a 可以将 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
?