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.