说我有:
trait A
class B extends A
class C extends A
有没有办法配置类型参数,以便:
class Foo[AType <: A with canCreateInstance]
def newAType : AType = new AType
这个想法是,Foo只能使用实现A的类,如B或C,但不能使用A本身。
答案 0 :(得分:0)
尝试为特征提供伴侣对象。伴随对象将是返回AType
。
使用伴侣对象:
trait Queue[T]{
def head:T
def tail:Queue[T]
def enqueue(x:T):Queue[T]
}
object Queue{
def apply[T](xs: T*): Queue[T] =
new QueueImpl[T](xs.toList)
private class QueueImpl[T](
private val leading:List[T],
private val trailing:List[T]=Nil
) extends Queue[T]
{
// methods in here
}
}
也许这更简单:
object A{
def aType(...):A = new B(...)
def aType(...):A = new C(...)
/* classes */
private class C(...) extends A
private class B(...) extends A{
// blah blah
}
}
答案 1 :(得分:0)
创建给定类型实例的最常用方法是使用工厂样式作为评论中提到的@ bluenote10。
为此,我们首先创建一个工厂定义
// factory definition
trait CanCreateInstance[T] {
def create: T
}
然后,在我们班上,我们要求一个给定类型的工厂
class Foo[T <: A](implicit factory: CanCreateInstance[T]) {
def newT: T = factory.create
}
我们可以将一些默认工厂添加到CanCreateInstance
object CanCreateInstance {
// define default availble instance creators
implicit def bFactory = new CanCreateInstance[B] {
def create = new B
}
}
然后我们可以像这样使用它
val fooB = new Foo[B]
val newB = fooB.newT
如果我们需要Foo
能够创建另一种类型的实例,我们可以简单地提供工厂。
implicit val cFactory = new CanCreateInstance[C] {
def create = new C
}
val fooC = new Foo[C]
val newC = fooC.newT
如果默认工厂不可用,此构造允许Foo
的任何用户提供工厂。例如,您可以为A
提供工厂
implicit val aFactory = new CanCreateInstance[A] {
def create = new A {}
}
如果您需要在运行时从未知类型创建实例而不创建工厂,则需要深入研究TypeTag
。有关该信息,请访问:Scala: What is a TypeTag and how do I use it?