pat*_*rit 32 types scala existential-type
List[T] forSome {type T}和 之间有什么区别List[T forSome {type T}]?我如何用"英语"阅读它们?我应该如何神交的forSome关键字?有哪些实际用途forSome?什么是实用的,比简单的T forSome {type T}用法更复杂?
Tra*_*own 25
这里有很多问题,其中大部分已经在上面评论中链接的答案中得到了相当彻底的解决,所以我会回答你更具体的第一个问题.
List[T] forSome { type T }和之间没有真正有意义的区别List[T forSome { type T }],但我们可以看到以下两种类型之间的区别:
class Foo[A]
type Outer = List[Foo[T]] forSome { type T }
type Inner = List[Foo[T] forSome { type T }]
Run Code Online (Sandbox Code Playgroud)
我们可以将第一个读作" T某些类型的foos列表T".T整个列表都有一个单一的.另一方面,第二个可以被理解为"一个foos列表,其中每个foo都T适用于某些人T".
换句话说,如果我们有一个列表outer: Outer,我们可以说"存在某种类型T,这outer是一个foos的列表T",对于类型列表Inner,我们只能说"为每个元素在列表中,存在一些T这样的元素,即T" foo ".后者较弱 - 它告诉我们较少的清单.
因此,例如,如果我们有以下两个列表:
val inner: Inner = List(new Foo[Char], new Foo[Int])
val outer: Outer = List(new Foo[Char], new Foo[Int])
Run Code Online (Sandbox Code Playgroud)
第一个将编译得很好 - 列表中的每个元素都是Foo[T]一些T.第二个不会编译,因为没有一些T这样的列表中的每个元素都是a Foo[T].
ste*_*hke 23
注意:(更新2016年12月8日)的forSome关键字很可能即将带走的斯卡拉2.13或2.14,根据马丁·奥德斯基的上ScalaX 2016年倾诉着路径依赖的类型或具有匿名类型的属性替换它(A[_]).在大多数情况下这是可能的.如果您的边缘情况不可能,请重构您的代码或放宽您的类型限制.
通常当您使用通用API时,API会保证您可以使用您提供的任何类型(最多一些给定的约束).因此,当您使用时List[T],List API会保证您可以使用T 您提供的任何类型.
对于forSome(所谓的存在量化类型参数),它是相反的.API将提供一种类型(不是你),它保证你,它将使用它提供给你的这种类型.语义是,具体的对象会给你一些类型T.同一个对象也会接受它为您提供的内容.但没有其他对象可以使用这些T,没有其他对象可以为您提供类型的东西T.
"存在量化"的概念是:存在(至少)一种类型T(在实现中)来履行API的合同.但我不会告诉你它是哪种类型.
forSome可以类似地阅读:对于某些类型T,API契约适用.但并非所有类型都是如此T.因此,当您提供某种类型T(而不是隐藏在API实现中的类型)时,编译器无法保证您获得了正确的类型T.所以它会抛出一个类型错误.
因此,当您List[T] forSome {type T}在API中看到时,您可以这样阅读:API将为您提供List一些未知类型T.它很乐意接受这个列表,它将与它一起使用.但它不会告诉你,是什么T.但至少你知道,列表中的所有元素都属于同一类型T.
第二个有点棘手.API再次为您提供了一个List.它将使用某种类型,T而不是告诉你是什么T.但是可以自由地为每个元素选择不同的类型.真实世界的API会为其建立一些约束T,因此它实际上可以使用列表的元素.
forSome在编写API时很有用,其中每个对象代表API的实现.每个实现都将为您提供一些对象,并将接受这些对象.但是你既不能混合不同实现的对象,也不能自己创建对象.相反,您必须始终使用相应的API函数来获取可与该API一起使用的一些对象.forSome实现非常严格的封装.您可以forSome通过以下方式阅读:
对于某些类型,API合约折叠为true.但你不知道它适用于哪种类型.因此,您无法提供自己的类型,也无法创建自己的对象.您必须使用通过API提供的那些
forSome.
这非常非正式,在某些极端情况下甚至可能是错误的.但它应该帮助你理解这个概念.
| 归档时间: |
|
| 查看次数: |
2701 次 |
| 最近记录: |