Scala类型重写
在下面两个答案后编辑 我试图编译下面的Scala代码Scala类型重写,scala,Scala,在下面两个答案后编辑 我试图编译下面的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 =
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)
}
有什么想法吗
基本上,我想定义一个像上面C这样的泛型类,并在子类(C1)上具有正确类型的方法
在soSthg中对C调用泛型方法之前,一切都很好
谢谢
新编辑部分
非常感谢您的回复。
查看下面的代码,我希望避免出现异常
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[Boolean])的签名确实是个问题
这将有助于:
def doSthg2[T <: C](csl : List[T]) { csl(0).x(csl(1)) }
def doSthg2[TC1
编译良好。请注意,您可以在此处删除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)
}
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)
}
如上所述定义C&C1没有问题。问题是您正在向e1.x传递类型为C(不是C1)的参数,因此违反了C1.x方法签名
就编译器而言:
您正在建模一个以trait/classC
在doSthg
内部,valse1
和e2
都是层次结构中的某种类型。对于e1和e2,唯一可以确定的是e1.type
和e2.type
都是C
的子类型。不能保证e1
和e2
是同一类型(或者是彼此的子类型)-即使类层次结构很浅(只有一个子类,C1
)。您可以在将来的任何时候通过在新的.class/.jar文件中添加C
的新子类型进行扩展(可能是由这台计算机上此编译器的.scala/.java文件生成的,甚至可能是由另一台计算机上的另一个编译器生成的!)
您选择了您的方法C1.x
不灵活-它的参数必须是C1
类型,而不是任何C
。因此,e1.x
不能接受“任意”的e2如上所述定义C&C1没有问题。问题是您正在向e1.x传递一个类型为C(不是C1)的参数因此违反了C1.x方法签名
就编译器而言:
您正在建模一个以trait/classC
在doSthg
内部,valse1
和e2
都是层次结构中的某种类型。对于e1和e2,唯一可以确定的是e1.type
和e2.type
都是C
的子类型。不能保证e1
和e2
是同一类型(或者是彼此的子类型)-即使类层次结构很浅(只有一个子类,C1
)。您可以在将来的任何时候通过在新的.class/.jar文件中添加C
的新子类型进行扩展(可能是由这台计算机上此编译器的.scala/.java文件生成的,甚至可能是由另一台计算机上的另一个编译器生成的!)
您已经选择了您的方法C1.x
不灵活-它的参数必须是C1
类型,而不是任何C
。因此,e1.x
确实不能接受“任意”的e2。类似的方法可以工作:def doSthg2[T确实。类似的方法可以工作:def doSthg2[T]