Cake Pattern: как поделиться экземпляром?

У меня есть компонент конфигурации в моем проекте Scala.

Очевидно, я не хочу иметь более одного экземпляра этого компонента. Я использую шаблон торта, но я не уверен, как настроить его в соответствии с моими требованиями:

// 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 ?

2 ответа

Решение

Что-то вроде этого?

// 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

Как уже упоминалось, вы хотите использовать синглтон, и поэтому должны сделать MyConfig использовать config который инициализируется в объекте. На второй вопрос, в вашей сути, следующая ошибка:

[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

Другие вопросы по тегам