简体   繁体   中英

Implementing scala trait with property that is class object

I have a simple trait

trait SomeTrait {
  val sourceData: SourceData
}

SourceData class has constructor parameter p: Array[String] . Now, when I extend this trait in Object, we must provide implementation for sourceData.

object SomeObject extends SomeTrait {
  override val sourceData: SourceData = ???
  def main(sysArgs: Array[String]){...}
}

But what if class SourceData needs sysArgs from main method, how can I override sourceData in main method, not in body of SomeObject. Something like this:

object SomeObject extends SomeTrait {
  def main(sysArgs: Array[String]){
    override val sourceData: SourceData = new SourceData(sysArgs)
  }
}

I do not want to use var, as val immutability is preferred. And also I want to have trait with no implementation in order to force all sub classes to implement sourceData. What other solution I have for this?

You can't avoid mutability in this situation. sourceData must have a value before main is called, and main must be able to change that value, so the value must be mutable.

One option is to make sourceData a def (which is a good idea anyway) and have it access a private var in SomeObject :

trait SomeTrait {
  def sourceData: SourceData
}

object SomeObject extends SomeTrait {
  private var mySource: SourceData = ???
  def sourceData = mySource

  def main(sysArgs: Array[String]) = {
    mySource = new SourceData(sysArgs)
  }
}

The root problem here is having a top-level object that needs run-time initialisation. This is required because SomeObject is a top-level object that is accessed directly from other parts of the code.

The solution to this is dependency injection rather than a global object .

trait SomeTrait {
  def sourceData: SourceData
}

object SomeObject {
  case class SomeData(sourceData: SourceData) extends SomeTrait

  def main(sysArgs: Array[String]) = {
    val theSource = SomeData(SourceData(sysArgs))

    // Pass this instance to the rest of the code that needs it
    restOfTheProgram(theSource)
  }
}

The rest of the code uses the instance of SomeTrait that is passed to it rather than using SomeObject directly.

There is no way to do that in Scala. You need to have a class inherit SomeTrait and instantiate it from the main method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM