Ответ 1
Как вы указываете, у С++ есть шаблоны. Короче говоря, С++ говорит, что "существует тест для всех типов T, чтобы Test компилировал". Это упрощает неявное добавление ограничений на T, но с нижней стороны они неявные и могут быть трудными для понимания пользователем вашего класса без чтения кода.
Scala параметрический полиморфизм (aka generics) работает намного больше, чем ML, Haskell, Java и С#. В Scala, когда вы пишете "class Test [T]", вы говорите "для всех T существует тип Test [T]" без ограничения. Это проще рассуждать о формально, но это означает, что вы должны быть откровенными в отношении ограничений. Например, в Scala вы можете сказать "class Test [T <: Foo]", чтобы сказать, что T должен быть подтипом Foo.
У С# есть способ добавить ограничение к 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]]
Если пользователям вашей библиотеки нужны собственные фабрики, они могут добавить свой собственный эквивалент объекта Factoryories. Одно из преимуществ этого решения заключается в том, что можно использовать что-либо с factory, независимо от того, существует или нет конструктор no-arg.
Не так называемый метод использует отражение и функцию в Scala, называемые манифестами, которые являются способом обойти ограничение Java относительно стирания типа
class Test[T](implicit m : Manifest[T]) {
val testVal = m.erasure.newInstance().asInstanceOf[T]
}
В этой версии вы все еще пишете
class Foo
val t = new Test[Foo]
Однако, если нет конструктора no-arg, вы получаете исключение во время выполнения вместо ошибки статического типа
scala> new Test[Set[String]]
java.lang.InstantiationException: scala.collection.immutable.Set
at java.lang.Class.newInstance0(Class.java:340)