Как вы указали, в C ++ есть шаблоны. Короче говоря, C ++ говорит, что «существует тест для всех типов T, такой, что тест компилируется». Это облегчает неявное добавление ограничений на T, но, с другой стороны, они неявные и могут быть трудными для понимания пользователем вашего класса без чтения кода.
Параметрический полиморфизм Scala (он же generics) работает намного больше, чем ML, Haskell, Java и C #. В Scala, когда вы пишете «класс Test [T]», вы говорите «для всех T существует тип Test [T]» без ограничений. Проще рассуждать формально, но это означает, что вы должны быть откровенны в отношении ограничений. Например, в Scala вы можете сказать «класс Test [T <: Foo]», чтобы сказать, что T должен быть подтипом Foo. </p>
C # имеет способ добавить ограничение к T в отношении конструкторов, но, к сожалению, Scala этого не делает.
Есть несколько способов решить вашу проблему в Scala. Один типобезопасен, но более многословен. Другой не безопасен.
типобезопасный способ выглядит как
class Test[T](implicit val factory : () => T) {
val testVal = factory
}
Тогда у вас может быть множество фабрик для типов, полезных в вашей системе
object Factories {
implicit def listfact[X]() = List[X]()
implicit def setfact[X]() = Set[X]()
// etc
}
import Factories._
val t = new Test[Set[String]]
Если пользователям вашей библиотеки нужны свои собственные фабрики, они могут добавить свой собственный эквивалент объекта фабрики. Одним из преимуществ этого решения является то, что можно использовать все, что связано с фабрикой, независимо от того, существует ли конструктор без аргументов.
Не слишком безопасный для типов способ использует отражение и функцию в Scala, называемую манифестами, которая позволяет обойти ограничение Java в отношении стирания типа
class Test[T](implicit m : Manifest[T]) {
val testVal = m.erasure.newInstance().asInstanceOf[T]
}
В этой версии вы все еще пишете
class Foo
val t = new Test[Foo]
Однако, если нет доступного конструктора без аргументов, вы получаете исключение времени выполнения вместо статической ошибки типа
scala> new Test[Set[String]]
java.lang.InstantiationException: scala.collection.immutable.Set
at java.lang.Class.newInstance0(Class.java:340)