首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >scala中存在类型的混淆

scala中存在类型的混淆
EN

Stack Overflow用户
提问于 2014-07-09 06:06:23
回答 2查看 220关注 0票数 3

我很难理解scala中的存在主义类型,但无法理解。这是我的测试代码:

代码语言:javascript
复制
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是什么意思?如果有人能给我详细的解释,我真的很感激,谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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")的推断是什么类型

代码语言:javascript
复制
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}IntString等的超型,T forSome {type T}是所有类型的超型,也就是Any

scala> a(0) res35: Any =1

您可能想知道为什么结果是Any类型,而不是T类型。与以下方面进行比较:

代码语言:javascript
复制
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位于括号内,所以一对元素的类型.

代码语言:javascript
复制
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的子类型。我们知道值aT实例化为Any,但是当类型检查时,重要的不是值的真实类型,而是它声明的类型。StringT的一个亚型吗?不,因为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 )的子类型。StringAny的一个子类型吗?是的,所以任务成功了。

关于存在要素的最后一件事是:当T只需实例化一次时,类型推断效果最好。早些时候,我们看到(a(0), a(1))生成了一对元素,它们都具有相同的(未知)类型。我真的很惊讶这能起作用。在下面的非常类似的例子中,a(0)a(1)也应该具有相同的类型,因此分配应该成功,但它没有成功。

代码语言:javascript
复制
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]都有效的函数中。

代码语言:javascript
复制
scala> def modifyArray[T](arr: Array[T]) =
     |   arr(0) = arr(1)
modifyArray: [T](arr: Array[T])Unit

现在我们可以通过将我们的函数应用到a来执行赋值,这次它确实成功了。

代码语言:javascript
复制
scala> modifyArray(a)

scala> a
res3: Array[_] = Array(2.2, 2.2, 3)
票数 4
EN

Stack Overflow用户

发布于 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类型仍然是已知的,并且所有的表达式都是与它有关的类型。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24646416

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档