Scala:如何设置在抽象父类(super class)构造函数中定义的实例字段?

标签 scala inheritance parameters constructor arguments

给定两个类:

 abstract class ClassA(val argA:Int = 1) {
   def func1 {
     ... argA ... //some operations
     func2
   }
   def func2
 }

class ClassB extends ClassA {
   def func2 {
     ... argA ... //some operations
   }
}

val b = new ClassB
b.func1

如何在实例化 b 时传递 argA=3? 像B这样的child-class会有几十个,不用重写就好了 每个类定义中的“(val argA:Int = 1)”。即使在这种情况下,事情也会变得晦涩难懂。

我发现的最相似的问题是关于获取而不是设置值: question

最佳答案

如您所见,有几种可能的方法可以实现您的要求。但是,哪一个是最好的方法并不明显,因为这取决于您希望强调什么(简洁、重用、性能)以及您的实际代码的外观。一些值得记住的事情是:


使用@maackle 的解决方案,表单的每个实例化

val b = new ClassB { override val argA = 3 }

将导致在幕后创建的匿名类 class AnonSubB extends ClassB。如果你想专注于简洁,那么这可能是要走的路,但如果匿名类的数量增加,它们可能会减慢编译速度。


@paradigmatic 的解决方案

class ClassB(i: Int) extends ClassA(i) { ... }
val cb = new ClassB(3)

几乎一样简洁并且不会产生匿名类,但缺点是 ClassA 指定的 argA 的默认值不会被重用(它是在@maackle 的解决方案中)。您可以重复该值,即将 ClassB 声明为

class ClassB(i: Int = 1) extends ClassA(i) { ... }

但这很容易出错,因为如果需要更改,您必须在各个地方更改默认值。


我还想提供一个我自己的解决方案,重点在于重用默认值而不创建匿名类,但不够简洁:

/* ClassA has a reusable (referenceable) default value */
abstract class ClassA(val argA: Int) {
  def this() = this(ClassA.defaultArgA)
}

object ClassA {
  val defaultArgA = 1
}

/* ClassB reuses ClassA's default value */
class ClassB(x: Int = ClassA.defaultArgA) extends ClassA(x)

/* ClassC has a local (non-referenceable) default value */
class ClassC(x: Int = 10) extends ClassA(x)

println(new ClassB(2).argA) // 2
println(new ClassB().argA)  // 1
println(new ClassC().argA)  // 10

关于Scala:如何设置在抽象父类(super class)构造函数中定义的实例字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13117149/

相关文章:

java - 修复此继承结构的最佳方法?

scala - 类型不匹配,预期 : T, 实际:T

php - jqGrid 设置带有参数化查询的 Select 函数

vba - 是否可以在 Microsoft Access 更新查询中以编程方式传递参数?

scala - 如何在使用 PlaySpecification 编写的 Controller 测试前后执行一组代码?

Eclipse - 将通用项目转换为 Scala 项目

scala - map 上的flatMap给出错误: wrong number of parameters; expected = 1

java - 扩展抽象类后的方法

android - 根据参数在 ListView 中显示项目

java - 当我运行应用程序时,我添加到 JPanel 的组件不会出现