Scala 抽象类方法,返回一个新的对应类子对象

发布于 2024-12-27 01:03:29 字数 352 浏览 2 评论 0原文

我的脑海中有以下类:

abstract class MyClass (data: MyData) {

  def update(): MyClass = {
    new MyClass(process())
  }

  def process(): MyData = {
    ...
  }

}

但是,抽象类无法实例化,因此 new MyClass(process()) 行是一个错误。我的问题是 - 有没有办法告诉编译器,对于 MyClass 的每个子类,我想创建一个恰好属于该子类的对象?在所有子类中完整地编写这个方法似乎有点过分了。使用类或方法的类型参数我自己无法实现这一点。

I have the following class in my mind:

abstract class MyClass (data: MyData) {

  def update(): MyClass = {
    new MyClass(process())
  }

  def process(): MyData = {
    ...
  }

}

However, abstract classes cannot be instantiated so the line new MyClass(process()) is an error. My question is - is there any way to tell the compiler that in case of each of the child classes of MyClass I want to create an object of exactly that child class? It seems an overkill to write this method awhole in all child classes. Playing with type parameters of the class or method I could not acheive that myself.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

往事风中埋 2025-01-03 01:03:29

像这样的事情怎么样? MyClass 使用具体类型进行参数化。当然,所有具体类都必须实现一个实际返回 Self 新实例的方法。

trait MyClass[+Self <: MyClass[Self]] {
  def update(): Self = {
    makeNew(process())
  }

  def process(): MyData = {
    // ...
  }

  protected def makeNew(data: MyData): Self
}

class Concrete0 extends MyClass[Concrete0] {
  protected def makeNew(data: MyData) = new Concrete0
}

class RefinedConcrete0 extends Concrete0 with MyClass[RefinedConcrete0] {
  override protected def makeNew(data: MyData) = new RefinedConcrete0
}

信用:IttayD 对他的答案的第二次更新这个问题

How about something like this? MyClass is parametrized with the concrete type. Of course, all concrete classes have to implement a method that actually returns a new instance of Self.

trait MyClass[+Self <: MyClass[Self]] {
  def update(): Self = {
    makeNew(process())
  }

  def process(): MyData = {
    // ...
  }

  protected def makeNew(data: MyData): Self
}

class Concrete0 extends MyClass[Concrete0] {
  protected def makeNew(data: MyData) = new Concrete0
}

class RefinedConcrete0 extends Concrete0 with MyClass[RefinedConcrete0] {
  override protected def makeNew(data: MyData) = new RefinedConcrete0
}

Credit: IttayD’s second update to his answer to this question.

万劫不复 2025-01-03 01:03:29

为了完全避免在所有子类中实现几乎相同的方法,您需要使用反射。我想如果你选择了 Scala,这将是你最后的选择。
因此,这里是如何最大限度地减少重复代码:

// additional parameter: a factory function
abstract class MyClass(data: MyData, makeNew: MyData => MyClass) {

  def update(): MyClass = {
    makeNew(process())
  }
  def process(): MyData = {
    ...
  }
}

class Concrete(data: MyData) extends MyClass(data, new Concrete(_))

通过这种方式,您可以仅重复实例化子类所需的最短片段。

To completly avoid implementing almost identical method in all subclasses you would need to use reflection. I guess that would be your last resort if you have chosen Scala.
So here is how to minimize the repetitive code:

// additional parameter: a factory function
abstract class MyClass(data: MyData, makeNew: MyData => MyClass) {

  def update(): MyClass = {
    makeNew(process())
  }
  def process(): MyData = {
    ...
  }
}

class Concrete(data: MyData) extends MyClass(data, new Concrete(_))

This way you repeat only the shortest fragment required to instantiate the subclass.

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