在 Scala 中,如何使用多个构造函数子类化 Java 类?

发布于 2024-09-10 23:02:47 字数 271 浏览 7 评论 0原文

假设我有一个具有多个构造函数的 Java 类:

class Base {
    Base(int arg1) {...};
    Base(String arg2) {...};
    Base(double arg3) {...};
}

如何在 Scala 中扩展它并仍然提供对 Base 的所有三个构造函数的访问?在 Scala 中,子类只能调用其超类的构造函数之一。我该如何解决这个规则?

假设 Java 类是我无法更改的遗留代码。

Suppose I have a Java class with multiple constructors:

class Base {
    Base(int arg1) {...};
    Base(String arg2) {...};
    Base(double arg3) {...};
}

How can I extend it in Scala and still provide access to all three of Base's constructors? In Scala, a subclass can only call one of it's superclass's constructors. How can I work around this rule?

Assume the Java class is legacy code that I can't change.

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

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

发布评论

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

评论(4

过期情话 2024-09-17 23:02:47

人们很容易忘记特征可以扩展类。如果您使用特征,则可以推迟决定调用哪个构造函数,如下所示:

trait Extended extends Base {
  ...
}

object Extended {
  def apply(arg1: Int) = new Base(arg1) with Extended
  def apply(arg2: String) = new Base(arg2) with Extended
  def apply(arg3: Double) = new Base(arg3) with Extended
}

Scala 2 特征本身可能没有构造函数参数,但您可以通过使用抽象成员来解决这个问题。

(Scala 3 允许特征具有构造函数参数。)

It's easy to forget that a trait may extend a class. If you use a trait, you can postpone the decision of which constructor to call, like this:

trait Extended extends Base {
  ...
}

object Extended {
  def apply(arg1: Int) = new Base(arg1) with Extended
  def apply(arg2: String) = new Base(arg2) with Extended
  def apply(arg3: Double) = new Base(arg3) with Extended
}

Scala 2 traits may not themselves have constructor parameters, but you can work around that by using abstract members instead.

(Scala 3 lets traits have constructor parameters.)

憧憬巴黎街头的黎明 2024-09-17 23:02:47

编辑 - 这是来自 scala 邮件列表上的一个问题,我认为这里重复了。我的答案涉及提供三个不同的构造函数(即复制 Java 设计),并且不扩展类

假设每个构造函数最终创建状态 S对象的,使用“静态”方法创建一个伴生对象来创建此状态

object Base {
  private def stateFrom(d : Double) : S = error("TODO")
  private def stateFrom(s : Str) : S = error("TODO")
  private def stateFrom(i : Int) : S = error("TODO")
} 

然后创建一个采用该状态的私有构造函数和遵循主构造函数的(公共)重载构造函数

import Base._
class Base private(s : S) { //private constructor takes the state
  def this(d : Double) = this(stateFrom(d)) 
  def this(str : String) = this(stateFrom(str))
  def this(i : Int) = this(stateFrom(i))
  //etc
}

EDIT - this is from a question on the scala mailing list which I thought was duplicated here. My answer relates to providing three different constructors (i.e. replicating the Java design), and not extending the class

Assuming that each of your constructors ultimately create the state S of the object, create a companion object with "static" methods to create this state

object Base {
  private def stateFrom(d : Double) : S = error("TODO")
  private def stateFrom(s : Str) : S = error("TODO")
  private def stateFrom(i : Int) : S = error("TODO")
} 

Then create a private constructor taking the state and (public) overloaded constructors which defer to the primary constructor

import Base._
class Base private(s : S) { //private constructor takes the state
  def this(d : Double) = this(stateFrom(d)) 
  def this(str : String) = this(stateFrom(str))
  def this(i : Int) = this(stateFrom(i))
  //etc
}
吻风 2024-09-17 23:02:47

我会选择最通用的一个(在本例中为 String),并在满足其他条件时自行进行内部转换。

尽管我承认这不是最好的解决方案,而且我觉得它有些不对劲。 :-(

I would pick the most generic one (in this case, String) and do the internal conversion yourself if it meets the other criteria.

Although I admit this is not the best solution and something strikes me as wrong about it. :-(

手心的温暖 2024-09-17 23:02:47

这是一个愚蠢的答案,可能会起作用,但如果 Java 类有太多构造函数,则可能会花费太多精力,但是:

用 Java 编写一个子类,该子类实现一个构造函数,该构造函数接受各种其他构造函数的所有输入并调用根据输入的存在或不存在(通过使用“null”或某种哨兵值)构建其超类的正确构造函数,然后在 Scala 中对该 Java 类进行子类化,并将哨兵值分配为默认参数。

This is a silly answer that would probably work somewhat but might be too much effort if the Java class has way too many constructors, but:

Write a subclass in Java that implements a constructor that takes all the inputs the various other constructors would and calls the proper constructor of its superclass based on the presence or absence of inputs (via usage of "null" or some sort of sentinel values), then subclass that Java class in Scala and assign the sentinel values as default parameters.

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