我正在努力理解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}
表示任何类型的数组,例如Array [Int],Array [String]等。Array[T forSome {type T}]
表示数组[Any]。但根据我的测试代码的结果,我看不出这种差异,编译错误信息也令人困惑。 required: T
的含义是什么?如果有人能给出详细解释,我很感激,谢谢!
答案 0 :(得分:3)
我被告知
sed -i '$s/,$//' select_stmnt.txt
表示任何类型的数组,例如Array [Int],Array [String]等。
那是对的。您可能会惊讶地发现值Array[T] forSome {type T}
被接受为Array(1,2.2,"3")
类型的值,即使Array[T] forSome {type T}
显然不是Array(1,2.2,"3")
类型的值也不是{{1} }}。要了解正在发生的事情,请让Scala告诉我Array[Int]
的推断类型:
Array[String]
啊哈!因此,有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}]
在特定<type expression involving T> forSome {type T}
实例化的所有类型的超类型。所以<type expression involving T>
是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)
。
(T forSome {type T}, T forSome {type T})
您为(Any, Any)
指定的值的类型必须是scala> a(0) = "x"
<console>:10: error: type mismatch;
found : String("x")
required: T
a(0) = "x"
^
的子类型。我们知道值Array[T]
已将T
实例化为a
,但在进行类型检查时,它不是重要的值的真实类型,它是声明的类型。 T
的子类型是Any
吗?不,因为String
可能是T
而a
无法放入Array[Int]
。
String
您为Array[Int]
分配的值的类型必须是scala> b(0) = "x"
scala> b
res2: Array[T 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)
为了向Scala显示这样的赋值是类型安全的,我们可以将它包装在适用于任何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)
^
我们现在可以通过将我们的函数应用于Array[T]
来执行赋值,这次它确实成功了。
scala> def modifyArray[T](arr: Array[T]) =
| arr(0) = arr(1)
modifyArray: [T](arr: Array[T])Unit
答案 1 :(得分:0)
它与Array[Any]
不同。 Array[T forSome { type T; }]
表示您并不关心Array
内的哪种类型。您可以在数组上编写泛型方法,例如:def swap(arr : Array[T forSome { type T; }]) = arr(0) = arr(1);
。但是数组类型保持已知,所有表达式都是相对于它进行了类型检查。