Scala泛型方法重写

发布于 2024-10-10 20:36:56 字数 942 浏览 2 评论 0原文

我有一个抽象类:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

请持续率性 2024-10-17 20:36:56
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 的返回值(或 Foo 的参数) code>bar1 或 bar2),在这样的设置中,您对对象(假设它名为 obj)的所有了解就是它是一个 Foo< /code>,您需要使用obj.T类型作为变量的类型。

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 Foo all share Foo as a superclass, but to hold the return value of bar2 (or the parameters to bar1 or 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.T as the type of the variable.

┾廆蒐ゝ 2024-10-17 20:36:56

为了让 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
}

To make Ken Blum's second version a little bit nicer you can use self types:

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
}
夕嗳→ 2024-10-17 20:36:56

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 的所有其他函数。

T needs to be a type parameter on the Foo class that you inherit from, not on the methods themselves.

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 Foo don'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.

谁许谁一生繁华 2024-10-17 20:36:56

理想情况下,您可以结合上面提到的内容,即

trait Foo[T <: Foo[T]] { self:T =>

“[T <: Foo[T]]”意味着 T 是 Foo[T] 的子类,
和“自我:T =>”意味着 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
    }        
  }

}

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.

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
    }        
  }

}
秉烛思 2024-10-17 20:36:56

您可以参数化 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!

You can parameterize Foo to accomplish some of the effect easily:

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.

Also, some of what you seem to want doesn't make sense if you give an actual implementation in Foo. If Foo promises to take any Foo but 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.

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!
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文