Scala:如何强制提供类型

问题描述 投票:3回答:2

假设我们有以下特征和类定义

trait Model extends Product
class X[T <: Model] {}

给出上面我可以创建X的实例如下。

val x = new X

编译器没有抱怨。在这种情况下,推断类型是Nothing。我想知道如何在编译时防止这种情况,以便在不提供显式类型的情况下不允许创建X的实例,即Model的子类型?

scala type-inference scala-generics
2个回答
2
投票

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

2
投票

我认为这有效:

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作为type-arg(奇怪的......):

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)
© www.soinside.com 2019 - 2024. All rights reserved.