我有一个抽象类:
abstract class Foo(...){
def bar1(f : Foo) : Boolean
def bar2(f : Foo) : Foo
}
多个类扩展Foo并覆盖方法
class FooImpl(...) extends Foo{
override def bar1(f : Foo) : Boolean {
...
}
override def bar2(f : Foo) : Foo {
...
}
}
是否有可能使用泛型(或其他东西)使重写方法具有实现它的子类的参数类型?像这样:
class FooImpl(...) extends Foo{
override def bar1(f : FooImpl) : Boolean {
...
}
override def bar2(f : FooImpl) : FooImpl {
...
}
}
我正在考虑下面的内容,但这似乎不起作用......
abstract class Foo(...){
def bar1[T <: Foo](f : T) : Boolean
def bar2[T <: Foo](f : T) : T
}
class FooImpl(...) extends Foo{
override def bar1[FooImpl](f : FooImpl) : Boolean {
...
}
override def bar2[FooImpl](f : FooImpl) : FooImpl{
...
}
}
非常感谢任何帮助!
谢谢。
答案 0 :(得分:20)
abstract class Foo{
type T <: Foo
def bar1(f:T):Boolean
def bar2(f:T):T
}
class FooImpl extends Foo{
type T = FooImpl
override def bar1(f:FooImpl) = true
override def bar2(f:FooImpl) = f
}
在此版本中,Foo
的不同子类全部共享Foo
作为超类,但保留bar2
的返回值(或参数bar1
或{ {1}})在一个设置中,您对对象的所有了解(假设它的名称为bar2
)是obj
,您需要使用类型Foo
作为类型变量。
答案 1 :(得分:12)
为了让Ken Blum的第二个版本更好一点,你可以使用自我类型:
abstract class Foo[T] { self:T =>
def bar1(f:T):Boolean
def bar2(f:T):T
}
class FooImpl extends Foo[FooImpl]{
override def bar1(f:FooImpl) = true
override def bar2(f:FooImpl) = f
}
答案 2 :(得分:2)
T
需要是您继承的Foo
类的类型参数,而不是方法本身。
abstract class Foo[T <: Foo[T]]{
def bar1(f:T):Boolean
def bar2(f:T):T
}
class FooImpl extends Foo[FooImpl]{
override def bar1(f:FooImpl) = true
override def bar2(f:FooImpl) = f
}
Foo
的不同子类在此版本的代码中实际上没有共同的超类型,因为它们从Foo
的不同参数化扩展而来。当你需要使用常见的超类型时,可以使用引用Foo[T]
的参数化方法,但我倾向于选择我在其他答案中发布的抽象类型解决方案,因为它不会泄漏泛型的细节所有其他必须处理Foos的功能。
答案 3 :(得分:1)
理想情况下,你要结合上面提到的东西,即
trait Foo[T <: Foo[T]] { self:T =>
“[T&lt;:Foo [T]]”表示T是Foo [T]的子类, 和“自我:T =&gt;”意味着Foo [T]是T的子类,并且一起告诉Foo [T]与T完全相同是一种奇怪的方式。
只有这样我才能使下面的代码编译并按预期工作:
trait Field[T <: Field[T]] { self:T =>
def x2:T
def +(that:T):T
def *(n:BigInt) : T = {
if(n == 1)
this
else if(n == 2)
this.x2
else if(n == 3)
this + this.x2
else {
val p = (this * (n/2)).x2
if (n%2==0)
p
else
p + this
}
}
}
答案 4 :(得分:0)
您可以参数化Foo
以轻松完成某些效果:
abstract class Foo[F <: Foo[F]] { def f: F }
class Food extends Foo[Food] { def f = this } // Yay!
class Fool extends Foo[Food] { def f = new Food } // Uh-oh...
如果你想排除第二种情况,那么使用Scala中的当前功能就没有直接的方法。
此外,如果您在Foo
中提供实际实施,那么您似乎想要的一些内容就没有意义。如果Foo
承诺接受任何Foo
,但你给它一个仅坚持Food
的方法,如果你传递Foo
的不同子类,它将会中断(例如Fool
)。所以编译器不允许你这样做。
abstract class Foo { def bar(f: Foo) : Foo }
class Foot extends Foo { def bar(f: Foo) = this } // Fine!
class Fool extends Foo { def bar(f: Fool) = this } // No good!