给定一个A具有类型参数的类,T我如何进一步约束T特定函数?在下面的示例中,我想强制执行foo只能在T是Int(或子类型,如果您愿意)时调用。即new A[Int]().foo()应该编译,但new A[Double]().foo()不应该编译。
我可以通过隐式转换实现我想要的,T => Int如foo. 然而,这会导致不必要的方法调用 - 隐式找到的证据是身份函数。还有,不好看。。。
class A[T] {
val someValue: T = ???
def foo()(implicit ev: T => Int): Int = ev(someValue)
// some ideas that don't quite work
// def bar[T2 <: Int :EqualTo[T]](t2: T2): T = t2.asInstanceOf[T]
// def bam[T2 <: T with Int](): Int = someValue.asInstanceOf[Int]
def thisOneDefinesItsOwnConstraintType[Z <: Int](z: Z): Z = z
def thisOneDoesNotNeedToConstrainT(t: T): T = someValue
}
Run Code Online (Sandbox Code Playgroud)
如果不需要施法,该解决方案将获得奖励积分:)
注意:我知道我可以在类或方法级别定义类型约束(请参阅 参考资料thisOneDefinesItsOwnConstraintType),但这对我没有帮助,因为我还有一些不需要约束类型的方法(请参阅 参考资料thisOneDoesNotNeedToConstrainT)。
我没有看到没有隐式的方法,因为虽然您可以B <: C对类方法施加一些约束,但您的要求B <: T很难概括,因为我们不知道C与 arbitary有什么关系T。幸运的是,Scala 已经为此提供了一个构造,即<:<类型类。<:<[B, T]生成的实例Predef将提供证据表明B <: C.
但不要只相信我的话,这是scaladoc必须说的:
要限制方法参数列表范围内的任何抽象类型 T(不仅仅是方法自己的类型参数),只需添加类型 T <:< U 的隐式参数,其中 U 是所需的上限;或对于下限,使用:L <:< T,其中 L 是所需的下限。
例如:
class E
class F extends E
class G extends F
class A[T] {
def constrained[B <: F](b: B)(implicit ev: B <:< T): B = b
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们引入了方法的Ffor 类型参数的上限。但是,如果你也想保证(不添加其他类型的参数),你可以添加隐。BcontrainedB <: TB <:< T
scala> val a = new A[E]
a: A[E] = A@5a63f509
scala> a.constrained(new E)
<console>:15: error: inferred type arguments [E] do not conform to method constrained's type parameter bounds [B <: F]
a.constrained(new E)
^
<console>:15: error: type mismatch;
found : E
required: B
a.constrained(new E)
^
scala> a.constrained(new F)
res5: F = F@4a668b6e
scala> a.constrained(new G)
res6: G = G@4de4b452
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
619 次 |
| 最近记录: |