我有一种感觉,我面临的问题与Scala的 Type Erasure 有关,但作为一个新手,我不能把手指放在它上面。需要一些帮助。
首先,代码:
class C (val i: Int) {
def mkString() = { println("C.i =" + this.i) }
object C {
implicit val cOrdering = new Ordering [C]
{
def compare (a: C, b: C)=
{
a.i compare b.i;
}
}
然后,我创建了另一个包含类'C'的集合的类:
class ContainerOfC [C] (s:Int) (implicit ordering: cOrdering[C]) {
var internalCollection = new TreeSet[C]()
def + (c:C): ContainerOfC [C] = {
this.internalCollection += c
this
}
def mkStringOfElems () = {
val y = this.internalCollection.toList
println (y.head.i) // <--- Problem here
}
}
这是REPL告诉我的:
error: value i is not a member of type parameter C
println(y.head.i)
^
我已经检查了'y'的类型:它是List [C]。如果是这样,为什么我不允许访问'i'?它是一个构造参数,但它是一个 val 因此,可以作为成员变量处理,不是吗?
我已经浏览了论坛中的其他一些相关帖子,而Manifests和Typetags是可能的方法。但是,我不确定是否需要针对这个简单的用例进入该级别。
答案 0 :(得分:2)
这有一种奇怪和熟悉的感觉“去过那里,完成了”。
你试图改变这个:
class ContainerOfC [C] (s:Int) (implicit ordering: cOrdering[C]) { ... }
在中没有声明中的类型参数C
:
class ContainerOfC(s:Int) (implicit ordering: cOrdering[C]) { ... }
您展示的代码创建了一个类和特定类型C
。当您稍后编写class ContainerOfC[C]
时,C
是一个可以由任何其他标识符命名的类型参数。它与定义class ContainerOfC[A]
相同,其中A
与早期代码中定义的类/类型C
没有任何关系。在您的示例中,类型参数C
将隐藏先前定义的类的名称...错误消息指示C
没有值i
,这是因为编译器是并不是指你所想到的同一个C
。
编辑:这样您就可以快速了解我们是否在同一页面上而不会陷入其他编译错误,这里有一些编辑可以使代码编译并使用更常用的缩进和支撑样式:
class C(val i: Int) {
def mkString() = println("C.i =" + this.i)
}
object C {
implicit val cOrdering = new Ordering[C] {
def compare(a: C, b: C) = a.i compare b.i
}
}
class ContainerOfC(s: Int)(implicit ordering: Ordering[C]) {
var internalCollection = new collection.mutable.TreeSet[C]()
def +(c: C): ContainerOfC = {
this.internalCollection += c
this
}
def mkStringOfElems() = {
val y = this.internalCollection.toList
println(y.head.i)
}
}