【Scalaタイプシステム】暗黙変換と暗黙パラメータ

4714 ワード

暗黙的変換
暗黙変換はimplicit修飾を用いた単一パラメータを持つ一般的な関数である.この関数は自動的に適用され、値は1つのタイプから別のタイプに変換されます.例:
整数nを分数n/1に変換し、定義implicit def int2Fraction(n: Int) = Fraction(n, 1)は、次の式で値を求めるときに、val result = 3 * Fraction(4, 5)コンパイラがint 2 Fraction(3)を呼び出し、整数をFractionオブジェクトに変換し、Fractionクラスの*メソッド定義に従って計算する.
暗黙的変換は、既存のクラスライブラリに機能を追加します.
私たちはjavaのためにio.Fileクラスは、Scalaでファイルを読み込むreadメソッドを追加し、readまたは目的の機能を提供するタイプを定義します.
class RichFile(val from: File) { def read = Source.fromFile(from.getPath).mkString }

次に、元のFileタイプを新しい定義のタイプに変換する暗黙的な変換を提供します.
implicit def file2RichFile(from: File) = new RichFile(from)

これにより、readメソッドをFileオブジェクト上で呼び出すことができ、RichFileオブジェクトに暗黙的に変換されます.
暗黙的変換のルール
スコープ規則
暗黙変換関数の使用可能な場所:
  • ソースまたはターゲットタイプの共生オブジェクトにある暗黙関数
  • 現在の役割ドメインに位置する単一の識別子で表すことができる暗黙関数
  • .
    暗黙関数がConversionsオブジェクトの中にある場合、そのオブジェクトはcomにある.xxx.yyyパッケージでは、導入文はimport com.xxx.yyy.Conversions._であるべきです.
    曖昧な規則がない
    暗黙的に変換された適用シーン:
  • 式のタイプが予想されるタイプと異なる場合:たとえばsqrt(Fraction(1, 4))でsqrtはDoubleのパラメータを期待し、コンパイラはfraction 2 Doubleのような暗黙関数を呼び出してFractionオブジェクトをDoubleオブジェクトに変換します.
  • オブジェクトが存在しないメンバーにアクセスする場合:たとえばnew File("README").readでは、Fileにはreadメソッドがありません.コンパイラはfile 2 RichFileを呼び出し、RichFileで定義されたreadメソッドを呼び出します.
  • オブジェクトがメソッドを呼び出し、そのメソッドのパラメータが入力パラメータと一致しないと宣言した場合:たとえば3 * Fraction(4, 5)では、Intクラスの*メソッドはFractionをパラメータとして受信せず、コンパイラはint 2 Fractionを呼び出して暗黙的に変換します.

  • コンパイラが暗黙的な変換を使用しない場合:
  • コードが暗黙変換を適用せずにコンパイルできる場合、暗黙変換は使用されません.
  • コンパイラは、複数の変換を同時に実行しようとしないので、暗黙的な変換は単一の呼び出しです.
  • の二義的な変換はエラーであり、コンパイラはエラーを報告します.

  • 暗黙パラメータ
    関数またはメソッドには、implicitとマークされたパラメータのリストを付けることができます.この場合、コンパイラはデフォルト値を検索し、関数またはメソッドに提供します.例:
    case class Delimiters(left: String, right: String)
    
    def quote(what: String)(implicit delims: Delimiters) =
      delims.left + what + delims.right
    
    implicit val quoteDelimiters = Delimiters("<<", ">>")
    quote("Scala Programming")を呼び出すと、コンパイラはDelimitersのタイプの暗黙的な値を検索し、<<Scala Programming>>を出力します.
    コンパイラの検索場所:
  • 現在の役割ドメインのすべての使用可能な単一識別子は、タイプ要件を満たすvalおよびdef
  • を指す.
  • 要求されたタイプに関連付けられたタイプの繁盛オブジェクト.関連するタイプには、要求されるタイプ自体と、そのタイプパラメータが含まれます.

  • 暗黙パラメータによる暗黙変換
    比較的小さな値を得るために汎用関数を提供します.def smaller[T](a: T, b: T) = if (a < b) a else bここでは、aとbのタイプに<オペレータがあるかどうか分からないため、コンパイラは通過しません.解決策は、変換関数を表す暗黙的なパラメータorderを追加することです.
    def smaller(a: T, b: T)(implicit order: T => Ordered[T])
      = if(order(a) < b) a else b

    Ordered[T]特質には、パラメータとしてTを受け入れる<方法があるため、コンパイラは、コンパイル時にTを認識し、T=>Ordered[T]タイプの暗黙的定義が役割ドメインに存在するか否かを判定する.これにより、smaller(40, 2)またはsmaller("AA", "BB")を呼び出すことができる.注意、orderは単一のパラメータを持つ関数であり、implicitラベルが付けられているので、暗黙的なパラメータだけでなく、暗黙的な変換でもあります.では、関数体重でorderの表示呼び出しを省略できます.
    def smaller[T](a: T, b: T)(implicit order: T => Ordered[T])
      = if (a < b) a else b

    aには<のメソッドがないため、order(a)を呼び出して変換します.
    転載は作者Jason Dingとその出所jasondingを明記してください.top Githubブログホームページ(http://blog.jasonding.top/)CSDNブログ(http://blog.csdn.net/jasonding1354)簡書ホームページ(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)Google検索jasonding 1354私のブログのホームページに入ります