如何理解代码`val x:Cat [_&lt ;: String] = new Cat [String]`

时间:2014-04-30 14:33:44

标签: scala type-systems existential-type

我只是写了一些scala代码:

class Cat[T]
val x: Cat[_ <: String] = new Cat[String]

它可以编译,但我不太了解。

您可以看到我将x的类型声明为Cat[_ <: String],这意味着

Cat[ T forSome { type T <: String; }]

但是,当x具有此特殊类型时,我该怎么办?是否有任何条件我必须声明x这样以便以后使用?

3 个答案:

答案 0 :(得分:1)

你不明白,因为你选了一个糟糕的例子。这与Java方差完全相同,因此,例如,您可以这样做:

import java.utii.{ArrayList, List => JList}

val x: JList[_ <: Object] = new ArrayList[String]

尽管Java的List及其实现类不是共同变体(因为Java中没有这样的概念,除其他外),你可以声明&#39; X&#39;是一个&#34;共同变体&#34; List,并为其指定一个子类,在本例中为Object

您的示例很糟糕,因为您选择Cat[String]而不是Cat的子类的String

答案 1 :(得分:0)

CatCat[_ <: String]的类型参数是一种存在类型。他们的动机很大程度上与Java的通配符相当,因此Scala可以继续与Java互操作,尽管它是(精神病)泛型。引用Martin Odersky intervew

  比尔维纳斯:如果不这样做,你会添加存在类型吗?   需要担心Java兼容性问题的原因   类型和擦除。如果Java已经确定了类型,没有原始类型或   通配符,Scala会有存在类型吗?

     

Martin Odersky:如果Java已经确定了类型,没有原始类型或   通配符,我认为我们不会对存在主义有太多用处   类型,我怀疑他们会在Scala。

这是一个blog post,其中一个Scala开发人员在将它们添加到语言时讨论了存在类型。通过更深入地讨论它们来blog post

答案 2 :(得分:0)

  

但是,当它具有这种特殊类型时,我能用x做什么?

这种类型并不特别特别。你可以,例如将它传递给采用此类型的方法等,但如果您将其声明为Cat[String],那么您也可以这样做,这是更具体的

  

是否有任何条件我必须声明x这样以供以后使用?

一种可能性是您希望覆盖x

class Foo {
  val x: Cat[_ <: Object] = new Cat[Object]
}

class Bar extends Foo {
  override val x: Cat[_ <: Object] = new Cat[String]
}

class Baz extends Bar {
  override val x: Cat[_ <: Object] = new Cat[File]
}

如果没有FooBar中的类型签名,这些覆盖都不可能。