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
)

しかし、これは私が望んでいるものではありません。さまざまな具体的な型 (すべて Request または Response を拡張する) を持つ他の関数をマップに追加できるようにしたいと考えています。そのため、リクエストまたはレスポンスの任意のサブクラスを取得するマップを宣言したいと思います。

ここで何が間違っているのか分かりますか?

4

1 に答える 1

2

の引数の型doSomethingRequestではなくに変更すると、次のMyRequestように動作します。

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

どうしてこれなの?より具体的な引数の型を持つ関数を、より具体的な引数の型を持つ変数に代入することはできません。doSomethingの引数の型がMyRequestあり、 の本体で でdoSomethingのみ使用可能でMyRequest、 では使用できないメソッドを呼び出した場合Request、誰かが の異なる実装で myFunction を呼び出した場合、以下の例で何が起こるでしょうRequestか? 型の安全性を破っていたでしょう。

val myFunction: (Request) => Response = doSomething

Function1これは、トレイトのパラメーター化された型で確認できます。

trait Function1[-T1, +R]

これ-T1は、 Function の引数が反変であることを意味します。これは、より具体的な引数の型を持たない Function がサブタイプとしてカウントされることを意味します (つまり、Request => ResponseFunction は type の変数に割り当てることができますMyRequest => Response)。関数の+R戻り値の型が共変であることを意味します。これはFunction、より具体的な戻り値の型を持つ s がサブタイプとしてカウントされることを意味します (つまりRequest => MyResponse、 type の変数に割り当てることができますRequest => Response)。

于 2013-09-05T22:03:57.197 に答える