在以下两个答案之后编辑 我正在尝试编译以下Scala代码。
abstract class C {
type T <: C
def x(other: T): (T, T)
}
class C1 extends C {
override type T = C1
override def x(other: C1): (C1, C1) = (this, this)
}
def doSthg(cs1 : List[C]) {
val e1 = cs1(0)
val e2 = cs1(1)
e1.x(e2)
}
但是失败并显示以下消息:
Description Resource Path Location Type
type mismatch; found : e2.type (with underlying type Chromo[G]) required: e1.C PI3.sc /GA/src/org/jts/ga line 76 Scala Problem
type mismatch; found : e2.type (with underlying type org.jts.ga.MI2.C) required: e1.T MI2.sc /GA/src/org/jts/ga line 18 Scala Problem
有什么想法吗?
基本上,我想在上面定义一个像C这样的泛型类,并在子类(C1)上使用正确类型的方法。
在soSthg中对C调用泛型方法之前,一切都很好。
由于
新编辑部分
非常感谢您的回复。 看下面的代码,我希望避免使用asInstanceOf。
abstract class G[T](val t: T) {
def ~(): G[T]
}
abstract class C[T](val g: List[G[T]]) {
def x(other: C[T]): (C[T], C[T])
}
class G1(override val t: Boolean) extends G[Boolean](t){
override def ~() = new G1(!t)
}
class C1(override val g: List[G1]) extends C[Boolean](g) {
override def x(other: C[Boolean]): (C[Boolean], C[Boolean]) = {
val go = other.g.map(e => e.asInstanceOf[G1])
//val go = other.g
val nc1 = new C1(go)
(nc1, nc1) // for demo
}
}
x的签名(其他:C [布尔])确实是个问题。
这样可行:
def doSthg2[T <: C](csl : List[T]) { csl(0).x(csl(1)) }
如何避免asInstanceOf?
答案 0 :(得分:10)
C1
编译好。请注意,您可以在此处删除override
关键字:
class C1 extends C {
type T = C1
def x(other: C1): (C1, C1) = (this, this) // do you mean (other, this)?
}
doSthg
无效:您无法证明e2
是e1.T
。这按预期工作:
def doSthg(e1: C)(e2: e1.T) {
e1.x(e2)
}
或者这个:
abstract class C {
...
def create(): T
}
def doSthg(e1: C) {
val e2 = e1.create()
e1.x(e2)
}
对于原始的doSthg
方法,x
应接受C
的任何实例:
trait C {
def x(other: C): (C, C)
}
答案 1 :(得分:1)
定义C&amp; C是没有问题的C1如上。问题是你将一个参数传递给了类型为C(而不是C1)的e1.x,因此违反了你的C1.x方法签名。
就编译器而言:
C
doSthg
内,val e1
&amp; e2
是层次结构中的某种类型。对于e1&amp; e2,唯一确定的事情是e1.type
和e2.type
都是C
的子类型。 没有保证e1
和e2
具有相同的类型(或者是彼此的子类型) - 即使类层次结构非常浅(只是一个子类,{ {1}})。你可以通过在将来的任何一点在新的.class / .jar文件中添加C1
的新子类型来扩展(可能是从这台机器上的编译器的.scala / .java文件生成的,甚至是由不同的编译器生成的)在另一台机器上!)C
不灵活 - 它的参数必须是C1.x
类型,而不是C1
。因此,C
不能将“任意”e1.x
作为参数。因此编译器根据您的设计决策做正确的事情。解决方案:
e2 <: C
获取C1.x
C
(可能同时在C1内移动doSthg)