Scala:如何设置抽象超类构造函数中定义的实例字段?

Scala:如何设置抽象超类构造函数中定义的实例字段?,scala,inheritance,parameters,constructor,arguments,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

分为两类:

 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这样的子类,所以如果不需要重写就好了 “val argA:Int=1”在每个类定义中。即使在这种情况下,事情也会变得模糊不清

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

只需将参数传递给ClassA即可:

class ClassB extends ClassA(3) { ... }

在实例化时重写argA:

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

根据你写的,这似乎是做你想做的事情的最简洁的方式。不过,根据您的实际使用情况,您可能会找到一些不太麻烦的方法,通过在伴生对象上定义一些方法来实例化对象。

只需在类定义中传递它:

abstract class ClassA {
    val argA: Int = 1
    def func1() {
        println(argA)
    }
}

class ClassB extends ClassA {
    def func2() {
        println("B: %d" format argA)
    }
}

val b = new ClassB { override val argA = 3 }
b.func1()
class ClassB( i: Int ) extends ClassA(i) { ... }

val cb = new ClassB( 3 )

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


通过@maackle的解决方案,表单的每个实例化

val b = new ClassB { override val argA = 3 }
将导致在后台创建一个匿名类
类AnonSubB扩展类b
。如果您想关注简洁性,那么这可能是一种方法,但是如果匿名类的数量增加,它们可能会减慢编译速度


@范式解

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

“如何在实例化b时传递argA=3”,不扩展。默认值应保持为1。
val b=new ClassB
在实例化b时将传递argA=3<根据您的问题,code>ClassB不接受args。如果需要,您必须编写类B(argA:Int=1)扩展类A(argA)。如果您有一大堆默认参数,您可能希望将它们抽象成一个case类,您可以使用
copy
在该类上更改值。