我很难理解scala中的存在主义类型,但无法理解。这是我的测试代码:
scala> val a: Array[T] forSome {type T} = Array(1,2.2,"3")
a: Array[_] = Array(1, 2.2, 3)
scala> val b: Array[T forSome {type T}] = Array(1,2.2,"3")
b: Array[T forSome { type T }] = Array(1, 2.2, 3)
scala> a(0)
res35: Any = 1
scala> b(0)
res36: Any = 1
scala> a(0) = "x"
<console>:10: error: type mismatch;
found : String("x")
required: T
a(0) = "x"
^
scala> b(0) = "x"我被告知Array[T] forSome {type T}是指任何类型的数组,如ArrayInt、ArrayString等,Array[T forSome {type T}]是指ArrayAny。但是根据我的测试代码的结果,我看不到这种差异,编译错误消息也令人困惑。required: T是什么意思?如果有人能给我详细的解释,我真的很感激,谢谢!
发布于 2015-10-16 05:27:36
我被告知
Array[T] forSome {type T}是指任何类型的数组,如ArrayInt、ArrayString等。
是这样的。您可能会惊讶地看到,Array(1,2.2,"3")值被接受为Array[T] forSome {type T}类型的值,尽管Array(1,2.2,"3")显然不是Array[Int]或Array[String]类型的值。为了了解发生了什么,让我们问Scala它对Array(1,2.2,"3")的推断是什么类型
scala> val x = Array(1,2.2,"3")
x: Array[Any] = Array(1, 2.2, 3)啊哈!所以有一个类型T,即Any,所以x有类型Array[T]。这就是为什么Array(1,2.2,"3")被接受为Array[T] forSome {type T}类型值的原因。
Array[T forSome {type T}]的意思是ArrayAny
同样正确。类型<type expression involving T> forSome {type T}是在特定T上实例化<type expression involving T>的所有类型的超级类型。所以Array[T] forSome {type T}是Array[Int],Array[String]等的超型,而T forSome {type T}是Int,String等的超型,T forSome {type T}是所有类型的超型,也就是Any。
scala> a(0) res35: Any =1
您可能想知道为什么结果是Any类型,而不是T类型。与以下方面进行比较:
scala> (a(0), a(1))
res0: (T, T) forSome { type T } = (1,2.2)如您所见,Array[T]元素的类型实际上是T。只是当我们只从数组中获取一个元素时,它的类型是T forSome { type T },它简化为Any。
scala> b(0) res36: Any =1
这一次,Any类型是非常期望的,因为Array[T forSome {type T}]元素的类型是T forSome {type T},也就是Any。
注意,由于forSome位于括号内,所以一对元素的类型.
scala> (b(0), b(1))
res1: (Any, Any) = (1,2.2)...is (T forSome {type T}, T forSome {type T}),又名(Any, Any)。
scala> a(0) = "x“:10:错误:类型错配;找到: String( "x”)必需:T(0)=“x”^
分配给Array[T]的值的类型必须是T的子类型。我们知道值a的T实例化为Any,但是当类型检查时,重要的不是值的真实类型,而是它声明的类型。String是T的一个亚型吗?不,因为a可以是Array[Int],而String不能被放入Array[Int]。
scala> b(0) = "x“scala> b res2: ArrayT forSome { type T}= Array(x,2.2,3)
分配给Array[T forSome {type T}]的值的类型必须是T forSome {type T} (即Any )的子类型。String是Any的一个子类型吗?是的,所以任务成功了。
关于存在要素的最后一件事是:当T只需实例化一次时,类型推断效果最好。早些时候,我们看到(a(0), a(1))生成了一对元素,它们都具有相同的(未知)类型。我真的很惊讶这能起作用。在下面的非常类似的例子中,a(0)和a(1)也应该具有相同的类型,因此分配应该成功,但它没有成功。
scala> a(0) = a(1)
<console>:12: error: type mismatch;
found : (some other)T(in value a)
required: T(in value a)
a(0) = a(1)
^为了向Scala显示这样的赋值是类型安全的,我们可以将它封装在一个对任何Array[T]都有效的函数中。
scala> def modifyArray[T](arr: Array[T]) =
| arr(0) = arr(1)
modifyArray: [T](arr: Array[T])Unit现在我们可以通过将我们的函数应用到a来执行赋值,这次它确实成功了。
scala> modifyArray(a)
scala> a
res3: Array[_] = Array(2.2, 2.2, 3)发布于 2014-07-09 08:43:00
这和Array[Any]不一样。Array[T forSome { type T; }]意味着您不关心Array内部的类型。您可以在Array上编写泛型方法,例如:def swap(arr : Array[T forSome { type T; }]) = arr(0) = arr(1);。但是Array类型仍然是已知的,并且所有的表达式都是与它有关的类型。
https://stackoverflow.com/questions/24646416
复制相似问题