scalaabstract-classtraits

Use default value for Scala trait or abstract class in a case class that implements it


Is there a way to get a version of this code to use the default value defined in the trait?

trait A {      // alternately `abstract class A`
 def x: String
 def y: Int = 1
}

final case class B(x: String, y: Int) extends A

val b = B("ok") // -> errors out
// I'd like this to turn into a B("ok", 1), 
// by using the default y value from A, but this doesn't work
// and similarly something like
object B {
 def apply(x: String): B = {B(x, A.y)}
} 
// doesn't work either

Solution

  • Based on you are not providing anything else than that code, I can only suggest how to make it compile but I don't think the design is exactly good.

    For the first approach

    trait A {
      def x: String
      def y: Int = 1
    }
    
    object DefaultA extends A {
      def x = ??? // you need something here, which means a default impl for this singleton
    }
    
    final case class B(x: String, override val y: Int = DefaultA.y) extends A
    
    val b = B("ok") // this will compile
    

    For the second case

    trait A {
      def x: String
      def y: Int = 1
    }
    
    final case class B(x: String, override val y: Int) extends A
    
    object B {
      def apply(x: String): B =
        // here you create an anonymous instance of the trait but again 
        // you have to provide an implementation for the other method
        B(x, (new A { override def x: String = ??? }).y)
    
    }
    

    If method x and y has no relation, you could use in different traits/classes/singletons