11

infix組み込み型 (Double など) にメソッドを追加して、演算子を使用できるようにしたいと考えています。それは可能ですか?

4

2 に答える 2

19

はいといいえ。はい、 にメソッドを追加したようdouble見せることができます。例えば:

class MyRichDouble(d: Double) {
  def <>(other: Double) = d != other
}

implicit def doubleToSyntax(d: Double) = new MyRichDouble(d)

<>このコードは、以前は使用できなかった演算子を type の任意のオブジェクトに追加しますDoubledoubleToSyntaxメソッドがスコープ内にあり、修飾なしで呼び出すことができる限り、次のことが機能します。

3.1415 <> 2.68     // => true

Double答えの「いいえ」の部分は、実際にはクラスに何も追加していないという事実から来ています。代わりに、必要なメソッドを定義する新しい型への変換を作成しDoubleています。これは、多くの動的言語が提供するオープン クラスよりもはるかに強力な手法です。また、たまたま完全に型安全です。:-)

注意すべきいくつかの制限事項:

  • この手法では、既存のメソッドを削除または再定義することはできません。新しいメソッドを追加するだけです
  • 目的の拡張メソッドを使用できるようにするには、暗黙的な変換メソッド (この場合はdoubleToSyntax) がスコープ内にある必要があります。

慣用的には、暗黙的な変換は、シングルトン オブジェクト内に配置されてインポ​​ートされるか (例: import Predef._)、またはトレイト内に配置されて継承されます (例: class MyStuff extends PredefTrait)。

余談ですが、Scala の「中置演算子」は実際にはメソッドです。<>メソッドを中置できるようにする魔法はありません。パーサーは単にその方法でそれを受け入れます。必要に応じて、「通常のメソッド」を中置演算子として使用することもできます。たとえば、Streamクラスはtake、単一のIntパラメーターを取り、 new を返すメソッドを定義しますStream。これは次のように使用できます。

val str: Stream[Int] = ...
val subStream = str take 5

str take 5式は文字どおり と同じstr.take(5)です。

于 2008-11-18T07:50:53.413 に答える
2

この機能は、エラー推定を実行するクラスを実装するのに役立ちました。

object errorEstimation {
  class Estimate(val x: Double, val e: Double) {
    def + (that: Estimate) =
      new Estimate(this.x + that.x, this.e + that.e)
    def - (that: Estimate) =
      new Estimate(this.x - that.x, this.e + that.e)
    def * (that: Estimate) =
      new Estimate(this.x * that.x,
                   this.x.abs*that.e+that.x.abs*this.e+this.e*that.e)
    def / (that: Estimate) =
      new Estimate(this.x/that.x,
                   (this.x.abs*that.e+that.x.abs*this.e)/(that.x.abs*(that.x.abs-that.e)))
    def +- (e2: Double) =
      new Estimate(x,e+e2)
    override def toString =
      x + " +- " + e
  }
  implicit def double2estimate(x: Double): Estimate = new Estimate(x,0)
  implicit def int2estimate(x: Int): Estimate = new Estimate(x,0)

  def main(args: Array[String]) = {
    println(((x: Estimate) => x+2*x+3*x*x)(1 +- 0.1))
    // 6.0 +- 0.93
    println(((x: Estimate) => (((y: Estimate) => y*y + 2)(x+x)))(1 +- 0.1))
    // 6.0 +- 0.84
    def poly(x: Estimate) = x+2*x+3/(x*x)
    println(poly(3.0 +- 0.1))
    // 9.33333 +- 0.3242352
    println(poly(30271.3 +- 0.0001))
    // 90813.9 +- 0.0003
    println(((x: Estimate) => poly(x*x))(3 +- 1.0))
    // 27.037 +- 20.931
  }
}
于 2008-11-18T08:28:35.193 に答える