【问题标题】:Cake Pattern: How to share an instance?Cake Pattern:如何共享一个实例?
【发布时间】:2013-02-01 18:45:07
【问题描述】:

我的 Scala 项目中有一个配置组件。

显然我不想拥有多个该组件的实例。我正在使用 cake pattern,但我不确定如何调整它以满足我的要求:

// Library
// =================================================
trait ConfigComp {

  trait Config {
    def get(k: String): String
  }

  def config: Config
}

trait QueueComp {
  self: ConfigComp =>

  class Queue {
    val key = config.get("some-key")
  }

  lazy val queue = new Queue
}

// Application
// =================================================

trait MyConfig extends ConfigComp {

  lazy val config = new Config {
    println("INITIALIZING CONFIG")

    def get(k: String) = "value"
  }
}

object Frontend extends QueueComp with MyConfig
object Backend  extends QueueComp with MyConfig

Frontend.queue.key
Backend.queue.key

打印:

INITIALIZING CONFIG
INITIALIZING CONFIG

如何让蛋糕图案分享Config的匿名实例?

【问题讨论】:

  • 如果您希望在类之间共享某些东西(即仅存在于一个示例中的东西),请将其放入对象中并从将要混入的该特征中访问对象值。
  • 谢谢,我试过了,但遇到了“类型不兼容”的错误:gist.github.com/4693853
  • 查看您的 sn-p 下方的评论。如果有人可以解释“具有不兼容的类型”错误,我仍然会等待,但作为一种临时解决方法,这应该会很好。
  • 感谢您的帮助!
  • 在您的要点中,您可以通过将def config: Config 更改为def config: ConfigComp#Config 来使嵌套特征起作用。寻找 scala 的路径相关类型(例如看这个问题:stackoverflow.com/questions/2183954/…)。

标签: scala cake-pattern


【解决方案1】:

这样的?

// Library
// =================================================
trait Config {
  def get(k: String): String
}

trait ConfigComp {
  def config: Config
}

trait QueueComp {
  self: ConfigComp =>
  class Queue {
    val key = config.get("some-key")
  }
  lazy val queue = new Queue
}

// Application
// =================================================

object SingleConfig extends ConfigComp {
  lazy val config = new Config {
    println("INITIALIZING CONFIG")
    def get(k: String) = "value"
  }
}

object Frontend extends QueueComp with ConfigComp {
  val config = SingleConfig.config
}
object Backend  extends QueueComp with ConfigComp {
  val config = SingleConfig.config
}

Frontend.queue.key
Backend.queue.key

如果您的 Config 特征放在 ConfigComp 中,我无法解决这些类型错误:

error: type mismatch;
 found   : MyConfig.Config
 required: Frontend.Config
    (which expands to)  Frontend.Config
                override def config = MyConfig.config

error: type mismatch;
 found   : MyConfig.Config
 required: Backend.Config
    (which expands to)  Backend.Config
                override def config = MyConfig.config

【讨论】:

  • Config 拉出特征似乎是唯一的解决方案,所以我接受了这个
【解决方案2】:

正如 om-nom-nom 所提到的,您正在寻找使用单例,因此应该让 MyConfig 使用在对象中初始化的 config。对于第二个问题,在您的gist 中,出现以下错误:

[error] overriding method config in trait ConfigComp of type => MyConfig.this.Config;
[error]  lazy value config has incompatible type
[error]   lazy val config = MyConfig.config
[error]            ^
[error] one error found

基本上可以准确地告诉您问题所在。 MyConfig.this.Config 不等于对象 MyConfig.this.Config。为了更清楚,让我们将代码更改为以下内容:

object MyConfigSingleton extends ConfigComp {
  val config = new Config {
    println("INITIALIZING CONFIG")
    def get(k: String) = "value"
  }
}

trait MyConfig extends ConfigComp {
  lazy val config = MyConfigSingleton.config
}

这里输入MyConfig.this.Config != MyConfigSingleton.this.Config

【讨论】:

  • 感谢您的解释! -似乎没有解决方案Config 嵌套在ConfigComp 内,是吗?无论如何,这可能是糟糕的设计;-)
猜你喜欢
  • 1970-01-01
  • 2021-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多