简体   繁体   English

实现 scala 特性,其属性为 class object

[英]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] . SourceData class 具有构造函数参数p: Array[String] Now, when I extend this trait in Object, we must provide implementation for sourceData.现在,当我在 Object 中扩展这个特性时,我们必须为 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.但是,如果 class SourceData 需要来自 main 方法的 sysArgs,我如何才能在 main 方法中而不是在 SomeObject 的主体中覆盖 sourceData。 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.我不想使用 var,因为 val 不变性是首选。 And also I want to have trait with no implementation in order to force all sub classes to implement sourceData.而且我还想拥有没有实现的特征,以强制所有子类实现 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. sourceData在调用main之前必须有一个值,并且main必须能够更改该值,因此该值必须是可变的。

One option is to make sourceData a def (which is a good idea anyway) and have it access a private var in SomeObject :一种选择是将sourceData def (无论如何这是个好主意)并让它访问SomeObject中的private var

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.这里的根本问题是有一个需要运行时初始化的顶级object This is required because SomeObject is a top-level object that is accessed directly from other parts of the code.这是必需的,因为SomeObject是一个顶级object ,可以直接从代码的其他部分访问。

The solution to this is dependency injection rather than a global object .解决方案是依赖注入而不是全局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.代码的SomeTrait使用传递给它的 SomeTrait 实例,而不是直接使用SomeObject

There is no way to do that in Scala. You need to have a class inherit SomeTrait and instantiate it from the main method.在 Scala 中没有办法做到这一点。你需要有一个 class 继承SomeTrait并从main方法实例化它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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