2014-04-30 15 views
0

我只是写一些Scala代码:如何理解代码`VAL X:猫[_ <:字符串] =新的猫[字符串]`

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

它可以被编译,但我不很好理解。

你可以看到我宣布的x类型为Cat[_ <: String],这意味着

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

但是,我能做些什么与x当它有这种特殊类型的?是否有任何条件需要我这样申报x以备后用?

+0

你可以用'x'做任何你可以用'Cat [T]'做的事情,其中​​'T'是'String'(加上更多)。我在Scala的这方面并不太强,但你应该看看这个页面(http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/)。也考虑改写你的问题。这是不是很清楚你问什么。 – Andrey

回答

0

Cat的的类型参数是一种存在类型。他们的动机大部分是与Java的通配符相当,所以Scala可以继续与Java进行互操作,尽管它的(精神)泛型。从Martin Odersky intervew引用:

比尔:请问,如果你没有 必要担心通配符的Java的兼容性问题,生 类型,并删除已添加存在的类型。如果Java具有物化类型,没有原始类型或通配符,那么Scala是否具有存在类型? Martin Odersky:如果Java具有物化类型并且没有原始类型或 通配符,我认为我们不会有那么多用于存在的类型,我怀疑它们会在Scala中。

这里是一个blog post由斯卡拉开发者讨论存在的类型回来时,他们被添加到语言之一。通过更深入地讨论它们,这里是blog post

1

你不明白,因为你选择了一个不好的例子。这也正是像Java变化,所以,举例来说,你可以这样做:

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

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

即使Java的List与其实现类不在同一变种(因为没有在Java中没有这样的概念,除其他事项外) ,你可以声明'x'是一个“共同变体”List,并为其指定一个子类,在这种情况下为Object

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

0

但是,如果它有这种特殊类型,我该怎么办?

这种类型不是特别特殊。你可以例如它传递给它取这个类型等方法,但你也可以做同样的,如果你声明它是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