假设我们有以下特征和类定义
trait Model extends Product
class X[T <: Model] {}
给出上面我可以创建 X 的实例如下。
val x = new X
编译器不会抱怨。在这种情况下推断的类型是Nothing
. 我想知道如何在编译时防止这种情况发生,以便在不提供显式类型的情况下不允许创建 X 的实例,即是Model
?
假设我们有以下特征和类定义
trait Model extends Product
class X[T <: Model] {}
给出上面我可以创建 X 的实例如下。
val x = new X
编译器不会抱怨。在这种情况下推断的类型是Nothing
. 我想知道如何在编译时防止这种情况发生,以便在不提供显式类型的情况下不允许创建 X 的实例,即是Model
?
class X[T <: Model] {}
类定义意味着T
类型具有作为类型的上限Model
。并且Nothing
是所有其他类型的子类型。这就是Scala 编译器不抱怨的原因。
将逆变器T
的类型class X
设为
class X[-T <: Model] {}
这样当你定义
val x = new X
Scala 编译器将其视为
x: X[Model] = X@7c9bdee9
我认为这有效:
trait Model
case class M() extends Model // one subclass of Model, for testing
// use implicit to force T to be convertible to Model
// which works for actual Model subclasses but not Nothing
class X[T<:Model](implicit f: (T) => Model)
new X
error: type mismatch;
found : <:<[Nothing,Nothing]
required: T => Model
new X[M] // ok
但是,您仍然可以明确给出Nothing
类型参数(奇怪...):
new X[Nothing] // ok
我会选择上述方法,但另一个想法是将Model 子类的类作为参数显式传递:
class X[T<:Model](tClass: Class[T])
new X(classOf[M]) // ok
new X(classOf[Nothing])
error: type mismatch;
found : Class[Nothing](classOf[scala.Nothing])
required: Class[T]
Note: Nothing <: T, but Java-defined class Class is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: T`. (SLS 3.2.10)