scala Scala泛型方法覆盖
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4626904/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
scala generic method overriding
提问by Jannik Luyten
I have an abstract class :
我有一个抽象类:
abstract class Foo(...){
def bar1(f : Foo) : Boolean
def bar2(f : Foo) : Foo
}
multiple classes extend Foo and override the methods
多个类扩展 Foo 并覆盖方法
class FooImpl(...) extends Foo{
override def bar1(f : Foo) : Boolean {
...
}
override def bar2(f : Foo) : Foo {
...
}
}
Is it possible, using generics (or something) to make the overriding methods have the parametertype of the subclass implementing it? Like this :
是否有可能使用泛型(或其他东西)使覆盖方法具有实现它的子类的参数类型?像这样 :
class FooImpl(...) extends Foo{
override def bar1(f : FooImpl) : Boolean {
...
}
override def bar2(f : FooImpl) : FooImpl {
...
}
}
I was thinking something along the line of the following, but that didn't seem to work...
我正在考虑以下内容,但这似乎不起作用......
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{
...
}
}
Any help is much appreciated!
任何帮助深表感谢!
Thank you.
谢谢你。
回答by Ken Bloom
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
}
In this version, different subclasses of Fooall share Fooas a superclass, but to hold the return value of bar2(or the parameters to bar1or bar2) in a setting where all you know about your object (let's say it's named obj) is that it's a Foo, you need to use the type obj.Tas the type of the variable.
在这个版本中,Foo所有的不同子类都Foo作为一个超类共享,但是要在一个设置中保存bar2(或参数 tobar1或bar2)的返回值,在该设置中,您对对象(假设它的名称obj)的全部了解是它是 a Foo,您需要使用类型obj.T作为变量的类型。
回答by Landei
To make Ken Blum's second version a little bit nicer you can use self types:
为了让 Ken Blum 的第二个版本更好看,你可以使用 self 类型:
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
}
回答by Ken Bloom
Tneeds to be a type parameter on the Fooclass that you inherit from, not on the methods themselves.
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
}
Different subclasses of Foodon't actually have a common supertype in this version of the code, because they extend from different parameterizations of Foo. You can use parameterized methods that refer to Foo[T]when you need to work with the common supertype, but I tend to prefer the abstract type solution I posted in my other answer, becuase it doesn't leak the details of the generics to all of the other functions that have to deal with Foos.
Foo在这个版本的代码中, 的不同子类实际上没有共同的超类型,因为它们从 的不同参数化扩展而来Foo。您可以使用参数化方法,这些方法指的是Foo[T]何时需要使用通用超类型,但我倾向于更喜欢我在其他答案中发布的抽象类型解决方案,因为它不会将泛型的详细信息泄露给所有其他人必须处理 Foos 的函数。
回答by Baturinsky
Ideally you combine things mentioned above, i.e.
理想情况下,您将上述内容结合起来,即
trait Foo[T <: Foo[T]] { self:T =>
"[T <: Foo[T]]" means T is subclass of Foo[T], AND "self:T =>" means that Foo[T] is subclass of T, and together it is a little weird way to tell that Foo[T] is exactly same as T.
"[T <: Foo[T]]" 表示 T 是 Foo[T] 的子类,而 "self:T =>" 表示 Foo[T] 是 T 的子类,这两者结合起来有点奇怪Foo[T] 与 T 完全相同。
Only with that I could make following code compile and work as intended:
只有这样,我才能使以下代码按预期编译和工作:
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
}
}
}
回答by Rex Kerr
You can parameterize Footo accomplish some of the effect easily:
您可以参数化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...
If you want to rule out the second case, there's no straightforward way to do it with the current features in Scala.
如果您想排除第二种情况,使用 Scala 中的当前功能没有直接的方法来做到这一点。
Also, some of what you seem to want doesn't make sense if you give an actual implementation in Foo. If Foopromises to take any Foobut you give it a method that insists on only a Food, it will break if you you pass it a different subclass of Foo(e.g. Fool). So the compiler won't let you do that.
此外,如果您在Foo. 如果Foo承诺接受任何Foo但你给它一个只坚持 a 的方法,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!

