3

私のコントロールの外にあるfoo既存のタイプのメソッドを提供したいとします。A私の知る限り、Scalaでこれを行うための標準的な方法は、を実装Aするある型への暗黙の変換を実装することfooです。今、私は基本的に2つのオプションを見ています。

  1. 次の目的のために、別の、場合によっては非表示のクラスを定義します。

    protected class Fooable(a : A) {
      def foo(...) = { ... }
    }
    implicit def a2fooable(a : A) = new Fooable(a)
    
  2. 匿名クラスをインラインで定義します。

    implicit def a2fooable(a : A) = new { def foo(...) = { ... } }
    

バリアント2)は、特に多くのタイプパラメータが発生する場合、確かに定型文が少なくなります。一方、1)でグローバルに1つのクラスが作成されるのではなく、(概念的には)変換ごとに1つのクラスが作成されるため、オーバーヘッドが増えるはずです。

一般的なガイドラインはありますか?コンパイラ/VMは2)のオーバーヘッドを取り除くので、違いはありませんか?

4

2 に答える 2

7

別のクラスはリフレクションを使用するため、別のクラスを使用するとパフォーマンスが向上します。

それを考慮してください

new { def foo(...) = { ... } }

本当に

new AnyRef { def foo(...) = { ... } }

現在、AnyRefメソッドはありませんfoo。Scala では、この型は実際にAnyRef { def foo(...): ... }は であり、 を削除すると、構造型AnyRefとして認識されるはずです。

コンパイル時に、この時間を前後に渡すことができ、どこでもメソッドfooが呼び出し可能であることがわかります。ただし、JVM には構造型がなく、インターフェイスを追加するにはプロキシ オブジェクトが必要です。これにより、参照の等価性が失われるなどの問題が発生します (つまり、オブジェクトはそれ自体の構造型バージョンと等しくなりません)。

それを回避する方法は、構造型のキャッシュされたリフレクション呼び出しを使用することでした。

したがって、パフォーマンスが重要なアプリケーションに Pimp My Library パターンを使用する場合は、クラスを宣言します。

于 2011-03-07T19:36:40.533 に答える