如果某个类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
}
如果不需要施放,解决方案会获得奖励积分:)
注意:我知道我可以在类或方法级别定义类型约束(请参阅thisOneDefinesItsOwnConstraintType
),但这对我没有帮助,因为我也有一些不需要约束的方法类型(见thisOneDoesNotNeedToConstrainT
)。
答案 0 :(得分:4)
我没有看到一种方法可以做到这一点而没有暗示,因为虽然你可以在类方法上加上一些约束B <: C
,但是你要求B <: T
很难概括,因为我们不知道C
如何与仲裁T
相关联。幸运的是,Scala已经为此构建了一个<:<
类型类。 <:<[B, T]
中生成的Predef
实例将提供B <: C
。
但请不要相信我的意思,这里是scaladoc所说的:
要约束方法参数列表中范围内的任何抽象类型T(不仅仅是方法的自身类型参数),只需添加类型为T&lt;:&lt的隐式参数; U,其中U是必需的上限;或者对于下限,使用:L&lt;:&lt; 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
}
在这里,我们为F
方法的类型参数B
引入contrained
的上限。但是,如果 想要保证B <: T
(不添加其他类型参数),则可以添加隐式B <:< 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
答案 1 :(得分:2)
怎么样:
implicit class AIntOps(a: A[Int]) {
def test(x: Int) = x
}
使用该方法,测试仅针对A[Int]
显示,并且根本不适用于任何其他A