Jac
Jac

Reputation: 551

How to create param for superclass constructor without early initialiser in Scala

Since Scala 2.13 early initialisers are deprecated.

How can I create a value to pass to a superclass which should be computed (based on other constructor arguments) and completely private, so on class initialisation it cannot be passed?

An example of what I have done until today is:

abstract class JmsServiceInitialiser(val qConfig: Config)

class ActiveMQService(
  val configA: ConfigElement,
  val configB: ConfigElement
) extends {
  val config: Config = {
    println(configA)
    println(configB)
    ...
    configA + configB
  }
} with JmsServiceInitialiser(config)

(This is just a sample with fake classes names, since I cannot share my source code)

If I define a trait I am not aware on how to pass the value to a superclass without exposing it and overriding it in the class constructor.

I saw Dotty (Scala 3) allows trait parameters, but Scala 2.13 does not.

Please provide a snippet with explanation if you know the solution! Thanks!

Upvotes: 2

Views: 105

Answers (2)

francoisr
francoisr

Reputation: 4585

First, if you have control over JmsServiceInitialiser, I would investigate the possibility of making qConfig a def to avoid this problem altogether.

If you absolutely want to keep the definitions the way they are, and still keep things relatively clean, you can simply create a wrapper for running your early initializer.

class Config
class ConfigElement {
  def +(e: ConfigElement): Config = ???
}

abstract class JmsServiceInitialiser(val config: Config)

class Early(val a: ConfigElement, val b: ConfigElement) {
  val c: Config = a + b 
}

class ActiveMQService(early: Early) extends JmsServiceInitialiser(early.c) {
  val a = early.a
  val b = early.b
}

If you don't want to declare an Early class, you can also simply pass a way to define c from a and b in this way:

class ActiveMQService(val a: ConfigElement, val b: ConfigElement, f: (ConfigElement, ConfigElement) => Config) 
  extends JmsServiceInitialiser(f(a,b))

Both these solutions are a bit ugly, and I would suggest thinking hard about whether you actually need a, b and c=a+b as class members.

Upvotes: 2

Jac
Jac

Reputation: 551

I found out this works by simply computing the variable when passing it to the superclass:

abstract class JmsServiceInitialiser(val qConfig: Config)

class ActiveMQService(
  val configA: ConfigElement,
  val configB: ConfigElement
) extends JmsServiceInitialiser({
  println(configA)
  println(configB)
  ...
  configA + configB
})

Please post your answer if you got a better solution.

Upvotes: 0

Related Questions