2016-09-30 5 views
0

FastUtilsのようなフレームワークをScalaで使用する場合、フレームワーク自体に特殊なデータ構造があるため、効果的な特殊化に基づいて適切なコードを生成するにはどうすればよいですか?つまり、どのように専門化され、適切なコードを実行するのかをプログラムでどのように把握していますか?だから、そのような場合にパスに関連する型付けをどう扱うのですか? objectscharについては特殊化に基づいてコードパスを実行する方法

class Container[@specialized T](var window: Int) { 
    val data = new ObjectArrayList[T](window) 
} 

については

私はそれになりたい:

class Container[@specialized T](var window: Int) { 
    val data = new CharArrayList(window) 
} 

しかし、これはTの専門に基づくべきです。私はこれを置くことになっている場合は、異なるsudoのコードは、おそらく

class Container[@specialized T](var window: Int) { 
    val data = specialisationOf(T) match { 
    case "Char" => new CharArrayList(window) 
    case "Int" => new IntegerArrayList(window) 
    ... 
    ... 
    ... 
    case _ => new ObjectArrayList[T](window) 
    } 
} 
+0

私はすでに手動の専門化を行っています。私は最小限の再定義でそれをしたいと思っています。ありがとうポインタがありますが、これは私が後になっている問題を解決しません。 –

+0

異なる 'ArrayList'型は特別なメソッドを持つ共通のスーパータイプを持っていないので、あなたの質問に書いた方法ではできません。 (ほとんど) 'data'を呼び出すたびに、' match'をもう一度やって、最も具体的な型にキャストしなければなりません。それはおそらく、実行時の手動タイプ比較のオーバーヘッドのボクシングオーバーヘッドを置き換えるだけです。 –

答えて

1

ようになり、すでにthis questionで説明したように、あなたは型クラスの専門実装をカプセル化することができます。これは多かれ少なかれ次のコードのようになります。

import it.unimi.dsi.fastutil.ints.IntArrayList 
import it.unimi.dsi.fastutil.chars.CharArrayList 
import it.unimi.dsi.fastutil.objects.ObjectArrayList 

class Container[@specialized(Int,Char) T](window: Int)(implicit impl: ContainerImpl[T]) { 
    impl.init(window) 

    def add(element: T) = impl.add(element) 
    override def toString = impl.toString 
} 

trait ContainerImpl[@specialized(Int,Char) T] { 
    def init(window: Int): Unit 
    def add(element: T): Unit 
    def toString: String 
} 

object ContainerImpl extends LowerPriorityImplicits { 
    implicit def intContainer = new ContainerImplInt 
    implicit def charContainer = new ContainerImplChar 
} 

trait LowerPriorityImplicits { 
    implicit def anyContainer[T] = new ContainerImplT[T] 
} 

final class ContainerImplInt extends ContainerImpl[Int] { 
    var data: IntArrayList = _ 
    def init(window: Int) = data = new IntArrayList(window) 
    def add(element: Int) = data.add(element) 
    override def toString = data.toString 
} 

final class ContainerImplChar extends ContainerImpl[Char] { 
    var data: CharArrayList = _ 
    def init(window: Int) = data = new CharArrayList(window) 
    def add(element: Char) = data.add(element) 
    override def toString = data.toString 
} 

final class ContainerImplT[T] extends ContainerImpl[T] { 
    var data: ObjectArrayList[T] = _ 
    def init(window: Int) = data = new ObjectArrayList(window) 
    def add(element: T) = data.add(element) 
    override def toString = data.toString 
} 

addの実装は常に同じに見えますが、dataに呼び出されるメソッドは、毎回異なる過負荷であることに注意してください。これをより多態的な方法で記述する場合は、最も具体的なaddメソッドを選択せず​​、IntまたはCharをボックスにする必要があります。

関連する問題