As you can see, there are several possible ways how to achieve what you asked for. However, it is not obvious which one is the best way, since that depends on what you'd like to put your emphasis on (conciseness, reuse, performance) and how your actual code looks. Some things worth having in mind are:
With solutions along the line of @maackle's, each instantiation of the form
val b = new ClassB { override val argA = 3 }
will result in an anonymous class class AnonSubB extends ClassB that is created behind the scenes. If you want to focus on conciseness, then this is probably the way to go, but the anonymous classes might slow down compilation if their number increases.
@paradigmatic's solution
class ClassB(i: Int) extends ClassA(i) { ... }
val cb = new ClassB(3)
is nearly as concise and does not result in anonymous classes, but has the disadvantage that the default value of argA as specified by ClassA is not reused (which it is in @maackle's solution). You could repeat the value, i.e., declare ClassB as
class ClassB(i: Int = 1) extends ClassA(i) { ... }
but this is error-prone, since you have to change the default value in various places, should it ever need to be changed.
I also like to offer a solution of my own, where the focus lies on reusing default values without creating anonymous classes, but which is less concise:
/* 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