2

Scalawags#2 の録画を少し見ていて気がついたのですが、型消去に関するこの部分があり、Dick Wall はリフレクションが最終的に足を噛むことになると指摘しています。

そこで、私はかなり頻繁に行っていることについて考えていました (Scala コレクションの実装も見ました)。システムを型パラメーターとして受け取るシリアライザーを備えたシステムがあるとします。

trait Sys[S <: Sys[S]] { type Tx }
trait FooSys extends Sys[FooSys]

trait Serializer[S <: Sys[S], A] {
  def read(implicit tx: S#Tx): A
}

現在、値パラメーターなしAでシリアライザーを構築できる型が多数あるため、基本的にシステム型パラメーターは「中空」です。また、私の例ではシリアライザーが頻繁に呼び出されるため、インスタンス化を節約しています。

object Test {
  def serializer[S <: Sys[S]] : Serializer[S, Test[S]] =
    anySer.asInstanceOf[Ser[S]]

  private val anySer = new Ser[FooSys]

  private final class Ser[S <: Sys[S]] extends Serializer[S, Test[S]] {
    def read(implicit tx: S#Tx) = new Test[S] {} // (shortened for the example)
  }
}
trait Test[S <: Sys[S]]

私はこれが正しいことを知っていますが、もちろん、asInstanceOf悪臭があります. このアプローチに対する提案はありますか?2つのことを追加させてください

  • 型パラメーターを trait のコンストラクターからメソッドに移動することSerializerreadオプションではありません ( でパラメーター化された値引数を必要とする特定のシリアライザーがありますS)
  • の型コンストラクタ パラメータに分散を追加することSerializerはオプションではありません
4

1 に答える 1

2

序章:

私はあなたの例に少し混乱しており、あなたの質問を誤解している可能性があります. と の間に特定のタイプの再帰があると感じてSいますTx.S#Txの問題anySer

暫定回答:

コンパイル時に、 の任意のインスタンスに対して、Ser[T]明確に定義された型パラメーターがあります。インスタンス化時に保存する必要があるため、特定の型に対してT単一の anySer があります。Ser[T]A

あなたが言っていることは、 aはanySer[A]と同じように機能するということです。これは、タイプ A とタイプ S の関係に応じて、2 つの方法で説明できます。Ser[S]S

  1. この変換がすべての場合に可能である場合A<:<SCOVARIANTシリアライザーはあり、anySer を として初期化できますSer[Nothing]。Nothing は Scala のすべてのクラスのサブクラスであるため、anySer は常にSer[Whatever]

  2. この変換がすべての場合に可能である場合 S<:<ACONTRAVARIANTシリアライザーはあり、anySer を として初期化できますSer[Any]。Any は Scala のすべてのクラスのサブクラスであるため、anySer は常にSer[Whatever]

  3. 前のケースのいずれでもない場合は、次のことを意味します。

    def serializer[S <: Sys[S]] : Serializer[S, Test[S]] =
    anySer.asInstanceOf[Ser[S]]
    

    シリアライザーが機能しない S がいくつかあるため、実行時に恐ろしいエラーが発生する可能性があります。これが発生する可能性のある S がない場合、クラスは 1 または 1 のいずれかに分類されます。

編集後のコメント

型が本当に不変である場合、キャストによる変換は不変関係を壊します。あなたが書いたコードに関するあなた自身の知識に基づいて、何も悪いことが起こらないことを知っているので、あなたは基本的に型システムに不自然な変換を実行させています。この場合、キャストは正しい方法です。コンパイラが正式にチェックできる型とは異なる型を強制しており、これを明示的にしています。操作が合法であり、コンパイラーが推測できず、最終的に「非公式」の関係が常に保持されることを確認するための美しい単体テストを添付できないことを知っている理由について、大きなコメントを付けることもできます。

一般に、このプラクティスは細心の注意を払って使用する必要があると思います。厳密に型指定された言語の利点の 1 つは、コンパイラが正式な型チェックを実行することで、初期のエラーを検出するのに役立ちます。故意に壊すと、この大きなメリットが失われます。

于 2013-01-18T12:30:01.347 に答える