0

次のscalaコードがあるとしましょう:

case class Term(c:Char) {
   def unary_+ = Plus(this)
}

case class Plus(t:Term)

object Term {
  implicit def fromChar(c:Char) = Term(c) 
}

今、私はscalaコンソールからこれを取得します:

scala> val p = +'a'
p: Int = 97

scala> val q:Plus = +'a'
<console>:16: error: type mismatch;
found   : Int
required: Plus
   val q:Plus = +'a'
                ^

'+' は Char 型に既に存在するため、暗黙の変換は行われないと思います。Char タイプに適用する前に、デフォルトの動作をオーバーライドし、変換された Term に「+」を適用する方法はありますか?

(ところで、この例は人為的なものであり、別の設計を探しているわけではありません。この例は、問題を説明するためのものです)

4

1 に答える 1

4

いいえ、+暗黙の変換であっても、デフォルトの演算子をオーバーライドする方法はありません。受け取るオブジェクトで定義されていない演算子 (実際にはメソッドです。演算子は単純なメソッドであるため) に遭遇すると、コンパイラはオブジェクトへの暗黙的な変換を探して、この演算子を提供します。ただし、演​​算子がターゲット オブジェクトで既に定義されている場合、変換を検索することはなく、元の演算子が常に呼び出されます。したがって、名前が既存の演算子と競合しない別の演算子を定義する必要があります。

更新: 暗黙的な変換を管理する正確な規則は、Scala 言語仕様で定義されています。

ビューは 3 つの状況で適用されます。

  1. 式 e が T 型で、 T が式の期待される型 pt に準拠していない場合。この場合、e に適用可能で、結果の型が pt に準拠する暗黙的な v が検索されます。検索は、暗黙のパラメーターの場合と同様に進行します。ここで、暗黙のスコープは T => pt のいずれかです。そのようなビューが見つかった場合、式 e は v(e) に​​変換されます。
  2. タイプ T の e を持つ選択 em で、セレクター m が T のメンバーを示さない場合。この場合、e に適用可能なビュー v が検索され、その結果には m という名前のメンバーが含まれます。検索は、暗黙のパラメーターの場合と同様に進行します。ここで、暗黙のスコープは T のスコープです。そのようなビューが見つかった場合、選択 em は v(e).m に変換されます。
  3. タイプ T の e を持つ選択 em(args) で、セレクター m が T の一部のメンバーを示しているが、これらのメンバーのいずれも引数 args に適用できない場合。この場合、e に適用可能なビュー v が検索され、その結果には args に適用可能なメソッド m が含まれます。検索は、暗黙のパラメーターの場合と同様に進行します。ここで、暗黙のスコープは T のスコープです。そのようなビューが見つかった場合、選択 em は v(e).m(args) に変換されます。

つまり、暗黙的な変換は次の 3 つの状況で発生します。

  1. 式が型であるが、関連のない型が予期されるTコンテキストで使用される場合、からへの暗黙的な変換(そのような変換がスコープ内にある場合) が適用されます。T'TT'

  2. オブジェクトに存在しないオブジェクトのメンバーにアクセスしようとすると、オブジェクトからこのメンバーを持つ別のオブジェクトへの暗黙的な変換が適用されます (そのような変換がスコープ内にある場合)。

  3. 対応するオーバーロードのいずれとも一致しないパラメーター リストを使用してオブジェクトのメソッドを呼び出そうとすると、コンパイラは、そのオブジェクトから、この名前のメソッドを持ち、互換性のあるパラメーター リストを使用する別のオブジェクトへの暗黙的な変換を適用します (そのような変換がスコープ内にある場合)。

    完全を期すために、これは実際にはメソッド以外にも適用されることに注意してください (メソッドを持つ内部オブジェクト/値applyも対象となります)。これは、Randall Schulz が以下のコメントで話していたケースであることに注意してください。

したがって、あなたの場合、ポイント(2)と(3)が関連しています。unary_+type に対してすでに存在するという名前のメソッドを定義したいInt場合、ケース (2) は開始されません。また、バージョンに組み込みメソッドと同じパラメーター リストがあるInt.unary_+場合 (どちらもパラメーターなし)、ポイント(3) どちらもキックしません。したがって、を再定義する暗黙を定義することは絶対にできませんunary_+

于 2013-02-28T00:49:06.457 に答える