Как запустить и различные пути кода на основе специализации
При использовании такой среды, как 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
, Если я хочу выразить это иначе, код 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)
}
}
1 ответ
Как уже объяснялось в этом вопросе, вы можете инкапсулировать специализированную реализацию в классе типов. Это будет выглядеть более или менее как следующий код.
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
нужно будет в штучной упаковке.