Scala泛型方法重写
我有一个抽象类:
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{
...
}
}
非常感谢任何帮助!
谢谢。
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
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在此版本中,
Foo
的不同子类都共享Foo
作为超类,但保存bar2
的返回值(或Foo
的参数) code>bar1 或bar2
),在这样的设置中,您对对象(假设它名为obj
)的所有了解就是它是一个Foo< /code>,您需要使用
obj.T
类型作为变量的类型。In this version, different subclasses of
Foo
all shareFoo
as a superclass, but to hold the return value ofbar2
(or the parameters tobar1
orbar2
) in a setting where all you know about your object (let's say it's namedobj
) is that it's aFoo
, you need to use the typeobj.T
as the type of the variable.为了让 Ken Blum 的第二个版本更好一点,你可以使用 self 类型:
To make Ken Blum's second version a little bit nicer you can use self types:
T
需要是您继承的Foo
类上的类型参数,而不是方法本身的类型参数。在此版本的代码中,
Foo
的不同子类实际上没有共同的超类型,因为它们是从Foo
的不同参数化扩展而来的。当您需要使用常见的超类型时,您可以使用引用Foo[T]
的参数化方法,但我倾向于更喜欢我在其他答案中发布的抽象类型解决方案,因为它不将泛型的详细信息泄漏给必须处理 Foos 的所有其他函数。T
needs to be a type parameter on theFoo
class that you inherit from, not on the methods themselves.Different subclasses of
Foo
don't actually have a common supertype in this version of the code, because they extend from different parameterizations ofFoo
. You can use parameterized methods that refer toFoo[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.理想情况下,您可以结合上面提到的内容,即
“[T <: Foo[T]]”意味着 T 是 Foo[T] 的子类,
和“自我:T =>”意味着 Foo[T] 是 T 的子类,并且用一种有点奇怪的方式来告诉 Foo[T] 与 T 完全相同。
只有这样,我才能使以下代码编译并按预期工作:
Ideally you combine things mentioned above, i.e.
"[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.
Only with that I could make following code compile and work as intended:
您可以参数化
Foo
来轻松实现某些效果:如果您想排除第二种情况,则使用 Scala 中的当前功能没有直接的方法可以做到这一点。
另外,如果您在 Foo 中给出实际的实现,那么您似乎想要的一些内容就没有意义。如果
Foo
承诺接受任何Foo
但你给它一个坚持只需要Food
的方法,那么如果你向它传递一个Foo
的不同子类(例如Fool
)。所以编译器不会让你这样做。You can parameterize
Foo
to accomplish some of the effect easily:If you want to rule out the second case, there's no straightforward way to do it with the current features in Scala.
Also, some of what you seem to want doesn't make sense if you give an actual implementation in
Foo
. IfFoo
promises to take anyFoo
but you give it a method that insists on only aFood
, it will break if you you pass it a different subclass ofFoo
(e.g.Fool
). So the compiler won't let you do that.