2016-09-30 11 views
0

При использовании фреймворка как FastUtils с Scala, как вы создаете соответствующий код на основе эффективной специализации, поскольку сама структура имеет специализированные структуры данных? Я., как вы программным образом определяете, что специализируется и выполняете соответствующий код? Итак, как вы относитесь к типизации, связанной с путями в таких случаях.Как работать и разные контуры кода на основе специализации

objects Для

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

Для char Я хочу, чтобы это было:

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

Но это должно быть основано на специализации T. Если я должен поставить это иначе код Судо будет возможно, как

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 не имеют общего супертипа со специализированными методами. В (почти) каждый метод вызывается «данные», вам нужно будет снова выполнить «матч» и применить к самому определенному типу. И это, вероятно, просто заменяет накладные расходы на бокс для накладных расходов вручную. –

ответ

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 необходимо будет вставить в коробку.