首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Scala中的自定义和多个构造函数继承?

Scala中的自定义和多个构造函数继承?
EN

Stack Overflow用户
提问于 2015-10-02 23:28:14
回答 3查看 533关注 0票数 1

据我所知,自定义构造函数的语义通常是通过伴生对象添加到类中的。那么,有没有办法在继承类的同时继承一个自定义构造函数呢?

一方面,我发现伴随对象不是沿着case类综合继承的,另一方面,我不知道有一种方法可以在类本身内创建自定义构造函数,以便继承它们。然而,对我来说,继承自定义构造函数似乎是一个非常有效的用例。那么在Scala中是否以某种(简单的)方式支持它呢?

天真的意图演示:

代码语言:javascript
运行
复制
class A {}
object A {
  def apply(n: Int) = {
    println(n)
    new A
  }
}

class B extends A {}

object Test {
  val a1 = A
  val a2 = A(3)
  val b1 = B    // compile error
  val b2 = B(3) // compile error

附注:我甚至发现the arcane/deviant technique of defining this custom constructors导致了一个自定义构造函数,实际上它不会被继承(它确实适用于创建自定义构造函数,但很奇怪,不幸的是,这些构造函数不会被继承)。演示代码:

代码语言:javascript
运行
复制
class A {
  def this(n: Int) = {
    this
    println(n)
  }
}

class B extends A {}

object Test {
  val a1: A = new A
  val a2: A = new A(3)
  val b1 = new B    
  val b2 = new B(3) // compile error
}

Intent Edit的澄清:

考虑到这个问题,“构造函数”和“伴生工厂方法”是可以互换的。

EN

回答 3

Stack Overflow用户

发布于 2015-10-03 00:49:29

你不能直接继承构造函数,因为你不能,你也不能继承没有一点工作就使用它们的东西。但是您可以抽象出构造函数调用之外的任何东西。

让我们假设我们有

代码语言:javascript
运行
复制
class Foo(text: String) {
  override def toString = "Foo: " + text
}
object Foo {
  def apply(text: String) = new Foo(text)  // Auto-generated for case class
  def apply(i: Int) = new Foo(
    if (i > 0) i.toString
    else if (i == 0) ""
    else s"negative ${0L - i}"
  )
}

然后我们决定

代码语言:javascript
运行
复制
class Bar(text: String) extends Foo(text) {
  override def toString = "Bar: " + text
}

现在,我们该如何处理object Bar呢?我们创建了一个特征,将对象创建与构造函数参数的计算分离和抽象,而不是重新编写所有的逻辑:

代码语言:javascript
运行
复制
trait FooCompanionLike[A <: Foo] {
  def apply(text: String): A    // I am abstract!
  def apply(i: Int): A = apply(
    if (i > 0) i.toString
    else if (i == 0) ""
    else s"negative ${0L - i}"
  )
}

现在我们可以

代码语言:javascript
运行
复制
object Foo extends FooCompanionLike[Foo] {
  def apply(text: String) = new Foo(text)
}
object Bar extends FooCompanionLike[Bar] {
  def apply(text: String) = new Bar(text)
}

因此,您不能完全摆脱样板,但您可以将其简化为从一个特征和单个方法调用扩展。

如果您这样做(其中抽象apply与构造函数完全匹配),您甚至可以让case类工作,而无需在附带中手动定义抽象apply方法:

代码语言:javascript
运行
复制
case class Baz(text: String) extends Foo(text) {
  override def toString = "Baz: " + text
}
object Baz extends FooCompanionLike[Baz] {
  // Nothing here!  Auto-generated apply works!
}
票数 2
EN

Stack Overflow用户

发布于 2015-10-03 01:30:46

简短的回答:没有直接的方法;试着变通并抵制这种渴望。

票数 1
EN

Stack Overflow用户

发布于 2015-10-03 00:15:24

Scala中的构造函数定义在类的主体中,并在类名之后接受参数。

代码语言:javascript
运行
复制
class A(i: Int) {
  println(i)
}

本例中的println(i)是构造函数逻辑。如果现在扩展A,如下所示:

代码语言:javascript
运行
复制
class B(i: Int) extends A(i)

实例化Bval b1 = new B(2),你会看到构造函数确实是继承的。

正如您已经发现的,Scala允许您通过定义名为this的函数来定义替代构造函数。但是这些替代构造函数必须调用主构造函数。

我的理解是,任何Scala类实际上只有一个构造函数,可选的构造函数只是在其中进行过滤。例如:

代码语言:javascript
运行
复制
class A(x: Int, y: Int) {
  // do some constructing!

  def this(x: Int) = {
    this(x, 1) // provide a default value for y
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32910646

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档