【问题标题】:Managing dependency graph via mixins in scala在 Scala 中通过 mixins 管理依赖关系图
【发布时间】:2017-05-03 08:14:58
【问题描述】:

我有一个需要 2 个特征的类,这两个特征都需要相同的特征。我该如何在这种情况下添加它

class RandomTest extends AbstractTestCase {
  "asdasd" should "asdsda" in {
    val a = new Application with XYZAppName with Session with MetricsPublisher

    a.a()
  }

  abstract class Application extends Session with MetricsPublisher {

    println("Application")
    def a() : Unit = { println("application.a")}
  }



  trait RequiredAppContext {
    println("RequiredAppContext")
    val appName : String
  }

  trait MetricsPublisher extends RequiredAppContext {
    this:RequiredAppContext =>
    println("MetricsPublisher")
  }
  trait Session extends RequiredAppContext{
    this:RequiredAppContext =>
    println("Session")
    lazy val appNameoverload = func(appName)
    def func(value:String ) {println("appNameoverload "+appName)}

  }


  // implmentations
  trait XYZAppName extends RequiredAppContext {
    println("XYZAppName")
    override val appName = "xyz"
  }
}

这是该程序的输出:

 [scalatest] RequiredAppContext 
 [scalatest] Session 
 [scalatest] MetricsPublisher 
 [scalatest] Application 
 [scalatest] XYZAppName
 [scalatest] application.a

将 XYZAppName 初始化移动到 Session 之前的最佳方法是什么?

【问题讨论】:

    标签: scala dependency-injection mixins


    【解决方案1】:

    Scala 的线性化算法,管理特征图初始化顺序和解决菱形继承问题,按声明顺序遍历(非循环)继承图,满足初始化父节点的要求,但省略所有已初始化的重复项。这里要注意的是,要初始化某个类,您需要先初始化它的基类,以及扩展它的所有特征。 Scala 甚至不允许在extendsnew 之后的任何位置指定基类,除了第一个 - 你只能使用with 添加特征。对于a 基类的(匿名)类是Application

    a.type
      -> Application
        -> Session
          -> RequiredAppContext
        -> MetricsPublisher
          -> RequiredAppContext // omitted
      -> XYZAppName
        -> RequiredAppContext  // omitted
      -> Session // omitted
        -> RequiredAppContext  // parent omitted
      -> MetricsPublisher // omitted
        -> RequiredAppContext  // parent omitted
    

    因此,您唯一的选择是修改继承层次结构,将 Application 转换为 trait 并在 a 的定义中使用 XYZAppName 对其重新排序:

    trait Application extends Session with MetricsPublisher
    ...
    val a = new XYZAppName with Application with Session with MetricsPublisher
    // RequiredAppContext
    // XYZAppName
    // Session
    // MetricsPublisher
    // Application
    

    然而,该解决方案不能涵盖所有可能的情况——如果你的抽象类有构造函数,你就不能把它变成一个特征(ongoing work 允许在未来版本的 Scala 中使用特征参数,但它远未完成) .如果基类是在外部代码中定义的,这也不是一个选项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-14
      • 1970-01-01
      • 2015-06-06
      • 1970-01-01
      • 1970-01-01
      • 2015-12-03
      • 2015-10-27
      • 1970-01-01
      相关资源
      最近更新 更多