1

为这个菜鸟问题道歉,但我对 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
)

但这不是我想要的——我希望能够将具有不同具体类型(都扩展请求或响应)的其他功能添加到地图中。因此,我想将地图声明为采用请求或响应的任何子类。

知道我在这里做错了什么吗?

4

1 回答 1

2

您可以将参数类型更改doSomethingRequest, 而不是MyRequest它将起作用:

def doSomething(request: Request): MyResponse = {
    null
}

为什么是这样?好吧,您不能将具有更特定参数类型的函数分配给具有不太特定参数类型的变量。如果在 的主体中doSomething有一个参数类型和 ,我们调用了一个仅在 on 上可用而不在 on 上可用的方法,如果有人用不同的实现来调用 myFunction ,在下面的示例中会发生什么?我们会破坏类型安全性。MyRequestdoSomethingMyRequestRequestRequest

val myFunction: (Request) => Response = doSomething

我们可以在Function1trait 的参数化类型中看到这一点:

trait Function1[-T1, +R]

-T1意味着函数的参数是逆变的,这意味着具有较少特定参数类型的函数算作子类型(即,Request => Response可以将函数分配给类型的变量MyRequest => Response)。这+R意味着 Function 返回类型是协变的,这意味着Function具有更具体返回类型的 s 算作子类型(即Request => MyResponse可以分配给 type 的变量Request => Response)。

于 2013-09-05T22:03:57.197 回答