我不确定我的标题中是否有正确的术语,但这有什么区别:
class Container[A <% Int] { def addIt(x: A) = 123 + x }
和此:
class Container[A](value: A) { def addIt(implicit evidence: A =:= Int) = 123 + value }
我想问的问题是为什么我会使用一种类型绑定另一种形式?是否只是能够在代码的不同部分应用绑定的类型(例如在参数列表与正文中)?
此外,文档说方法可能会询问类型的“证据”,而不是使用其他对象进行类型检查,然后提供第二个代码段。他们指的是什么样的证据?
注意:这是关于高级类型的this文章。
答案 0 :(得分:4)
查看边界适用于您希望使用 viewable 类型作为其他类型的情况。在您的示例中,您希望A
可查看为Int
。这意味着我们希望A => Int
范围内的任何隐式转换。
即。它与:
相同class Container(implicit evidence: A => Int) { def addIt(x: A) = 123 + x }
他们也是deprecated。这应该足以避免它们。
类型边界不是第二个示例的正确术语。它们用于严格限制上面或下面的参数类型。 类型绑定将如下所示:
class Container[A <: Int] { def addIt(x: A) = 123 + x }
在此示例中,A
必须严格限制在Int
之上。隐式转换不适用。
我不确定您的第二个示例是否真的有名称,但它与 view bounds 的不同之处在于它需要类型为{{1}的实例看到here。它类似于=:=
见证人的=:=
与A
相同的视图界限,因此允许Int
明确转换为A
。但是,它需要存在类型类Int
的实例,而不仅仅是来自=:=[A, Int]
的任何隐式转换。
你的两个例子虽然有点根本不同。第一个要求类本身的视图绑定,其中第二个需要方法的类型证据。也就是说,第一个示例不允许A => Int
的实例存在(没有可用的隐式转换),但第二个示例。第二个示例很乐意允许您构建Container[String]
,但不允许您使用Container[String]
方法,除非您有addIt
的证据。
通过证据,我们指的是隐式转换为我们对(String =:= Int
)感兴趣的类型,或者是类型为A => Int
的类型的实例平等。对于实际相同的类型,我们会在Predef (earlier link)中自动生成这些类型。