为noob问题道歉,但我对Scala很新。
我有以下Scala类:
class Test {
class Request {def getValue(): String = {"request"}}
class Response {def getValue(): String = {"response"}}
case class MyRequest(message: String) extends Request
case class MyResponse(message: String) extends Response
val myFunction: (Request) => Response = doSomething
private val functions = scala.collection.mutable.Map[String, (Request) => Response](
"myFunction" -> myFunction
)
def doSomething(request: MyRequest): MyResponse = {
null
}
}
无法使用以下错误进行编译:
type mismatch;
found : Test.this.MyRequest => Test.this.MyResponse
required: Test.this.Request => Test.this.Response
val myFunction: (Request) => Response = doSomething
如果我将myFunction的声明和函数更改为:
,它会起作用val myFunction: (MyRequest) => MyResponse = doSomething
private val functions = scala.collection.mutable.Map[String, (MyRequest) => MyResponse](
"myFunction" -> myFunction
)
但这不是我想要的 - 我希望能够将具有不同具体类型(所有扩展请求或响应)的其他功能添加到地图中。所以我想将地图声明为采用Request或Response的任何子类。
知道我在这里做错了吗?
答案 0 :(得分:2)
您可以将doSomething
的参数类型更改为Request
,而不是MyRequest
,它会起作用:
def doSomething(request: Request): MyResponse = {
null
}
这是为什么?那么你不能将具有更具体的参数类型的函数赋值给具有较少特定参数类型的变量。如果doSomething
的参数类型为MyRequest
且doSomething
正文中我们调用的方法仅在MyRequest
上可用且在Request
上不可用,如果有人用Request
的不同实现调用myFunction,下面的例子会发生什么?我们会打破类型安全。
val myFunction: (Request) => Response = doSomething
我们可以在Function1
特征的参数化类型中看到这一点:
trait Function1[-T1, +R]
-T1
表示函数的参数是逆变的,这意味着具有较少特定参数类型的函数计为子类型(即Request => Response
函数可以分配给类型为{{1}的变量})。 MyRequest => Response
表示函数返回类型是协变的,这意味着具有更具体返回类型的+R
计为子类型(即Function
可以分配给Request => MyResponse
类型的变量)。