3

次のように、クラスにいくつかの演算子を定義するとします。

class A {
    def +(f: Float) = /* ... */
}

val a: A = new A

これによりa + 1f、十分に簡単に行うことができます。ライブラリのユーザーも書き込みできるようにしたい場合はどうすればよい1f + aですか? どうすればそれを実装できますか?

4

2 に答える 2

11

Scala 2.9 では、この暗黙的な変換をインポートできます。

implicit def floatPlusAExtender (x: Float) = 
  new {
    def + (a: A) = a + x
  }

そして好きなように使ってください。Scala 2.10 以降では、この変換を次のように行う方がよいでしょう。

implicit class FloatPlusAExtender (x: Float) {
  def + (a: A) = a + x
}

または次のようにさらに良い:

implicit class FloatPlusAExtender (val x: Float) extends AnyVal {
  def + (a: A) = a + x
}

最後の方法はValue Classと呼ばれ、前の 2 つの方法とは異なり、この機能をオーバーヘッドなしで提供します。(ありがとう、axel22) これも 2.10 に付属する新しいものです。

Aまたは、次のように変更することもできます。

class A {
  def + (x: Float) = /* ... */
  def +: (x: Float) = this + x
}

次のように使用します。

1f +: a

最後のアプローチが望ましいです。

于 2012-07-07T16:12:31.050 に答える
3

1 つのアプローチはpimp-my-library-patternです。

class FloatWithPlusA(f: Float) {
  def +(a: A) = a + f
}

implicit def floatPlusA(f: Float): FloatWithPlusA =
  new FloatWithPlusA(f)

val a: A = new A
a + 1.0f  /* a.+(1.0f) */
1.0f + a  /* floatPlusA(1.0f).+(a) */

もう 1 つのアプローチは、右結合メソッドを追加することですが、2 つの演算子の構文が異なるという明らかな欠点があります。

class A {
  val f: Float = 1.0f

  def +(f: Float) = this.f + f
  def +:(f: Float) = this.f + f
}

val a: A = new A
a + 1.0f
1.0f +: a
于 2012-07-07T16:13:27.563 に答える