61

拡張メソッドを書いているとしましょう

implicit class EnhancedFoo(foo: Foo) {
  def bar() { /* ... */ }
}

extends AnyValクラス定義に常に含める必要がありますか? 暗黙のクラスを値クラスにしたくないのはどのような状況ですか?

4

2 に答える 2

56

値クラスについてリストされている制限を見て、それらが暗黙のクラスに適していない場合を考えてみましょう。

  1. 「型が値クラスではない、正確に 1 つの public val パラメーターを持つプライマリ コンストラクターのみが必要です。」したがって、ラップするクラス自体が値クラスである場合、 をimplicit classラッパーとして使用することはできませんが、次のようにすることができます。

    // wrapped class
    class Meters(val value: Int) extends AnyVal { ... }
    
    // wrapper
    class RichMeters(val value: Int) extends AnyVal { ... }
    
    object RichMeters { 
      implicit def wrap(m: Meter) = new RichMeter(m.value)
    }
    

    ラッパーに暗黙的なパラメーターもある場合は、それらをメソッド宣言に移動することを試みることができます。つまり、代わりに

    implicit class RichFoo[T](foo: Foo[T])(implicit ord: Ordering[T]) {
      def bar(otherFoo: Foo[T]) = // something using ord
    }
    

    あなたが持っている

    implicit class RichFoo[T](foo: Foo[T]) extends AnyVal {
      def bar(otherFoo: Foo[T])(implicit ord: Ordering[T]) = // something using ord
    }
    
  2. 「特殊な型パラメータを持っていない可能性があります。」特殊化された型パラメーターを持つクラスをラップする場合、ラッパーを特殊化する必要がある場合があります。

  3. 「ネストされたまたはローカルのクラス、特性、またはオブジェクトを持たない可能性があります」繰り返しますが、ラッパーの実装に役立つ可能性があります。
  4. equals「またはhashCodeメソッドを定義することはできません。」暗黙のクラスも持つべきではないため、無関係equals/hashCodeです。
  5. 「最上位クラスまたは静的にアクセス可能なオブジェクトのメンバーである必要があります」これは、通常、暗黙的なクラスを定義する場所でもありますが、必須ではありません。
  6. 「メンバーとして defs のみを持つことができます。特に、lazy vals、vars、または vals をメンバーとして持つことはできません。」vars やs の賢明なユースケースは思いつきませんが、暗黙のクラスはそれらすべてを持つことができますlazy val
  7. 「別のクラスによって拡張することはできません。」繰り返しますが、暗黙のクラスは拡張できますが、おそらく正当な理由はありません。

さらに、暗黙的なクラスを値クラスにすると、リフレクションを使用してコードの動作が変わる可能性がありますが、リフレクションは通常、暗黙的なクラスを認識しないはずです。

暗黙のクラスがこれらの制限をすべて満たしている場合、それを値クラスにしない理由は考えられません。

于 2013-02-18T07:23:20.440 に答える
-5

値クラス暗黙クラスを混同しているようです。値クラスは拡張する必要AnyValがありますが、拡張のために暗黙クラスを定義する場合、拡張することはめったにありません。

于 2013-02-18T04:38:02.740 に答える