Scala - trait 成员初始化:使用 trait 修改类成员 [英] Scala - trait member initialization: use traits to modify class member

查看:62
本文介绍了Scala - trait 成员初始化:使用 trait 修改类成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能标题不太清楚.这是我的问题.

Probably the Title is not so clear. This is my problem.

假设我有一个特性,它定义了一个具有一系列配置参数的应用程序.这些参数包含在 Map 中,其中一些具有默认值.

Let's say I have a trait that defines an application with a series of configuration parameters. These parameters are contained in a Map, some of them have default values.

trait ConfApp {
  val dbName: String
  lazy val conf: scala.collection.mutable.Map[String, Any] = scala.collection.mutable.Map("db" -> dbName, "foo" -> "bar")
}

所以我可以创建一个自定义应用程序如下:

So I can create a custom application as follows:

class MyApp extends ConfApp {
  override val dbName = "my_app_db"

  // print app configuration parameters
  println(conf)

  def add() = {...}
  ...
}

val M1 = new Myapp    // Map(db -> my_app_db, foo -> bar)

我想创建其他特性来设置一些其他配置参数.换句话说,我希望能够执行以下操作:

I would like to create other traits that set some other configuration parameters. In other words I would like to be able to do something like:

class MyApp2 extends ConfApp with LogEnabled {
  override val dbName = "my_app2_db"
  // print app configuration parameters
  println(conf)

  def add() = {...}
  ...
}

val M2 = new Myapp2    // Map(db -> my_app_db, foo -> bar, log -> true)

到目前为止,我已经设法做到以下几点:

So far I've managed to do the following:

trait LogEnabled {
  val conf: scala.collection.mutable.Map[String, Any]
  conf("log") = true
}

trait LogDisabled {
  val conf: scala.collection.mutable.Map[String, Any]
  conf("log") = false
}

trait ConfApp {
  val dbName: String
  lazy val conf: scala.collection.mutable.Map[String, Any] = scala.collection.mutable.Map("db" -> dbName, "foo" -> "bar")
}

class MyApp extends ConfApp {
  val dbName = "my_app_db"
  println(conf)
}

class MyApp2 extends ConfApp with LogDisabled {
  val dbName = "my_app_db"
  println(conf)
}

val M = new MyApp         // Map(db -> my_app_db, foo -> bar)
val M2 = new MyApp2       // Map(log -> false, foo -> bar, db -> null)

但是正如您在 M2 中看到的,db 参数是 null.我不明白我做错了什么.

but as you can see in M2 the db parameter is null. I can't understand what I'm doing wrong.

老实说,我完全不喜欢这种使用可变 Map 的方法,但我还没有设法做得更好.

Sincerely, I don't like at all this approach with mutable Map, but I've not managed to do something better.

推荐答案

你仍然可以这样使用不可变的Map:

You can still use an immutable Map this way:

scala> trait ConfApp {
     |   val dbName: String
     |   def conf: Map[String, Any] = Map("db" -> dbName, "foo" -> "bar")
     | }
defined trait ConfApp

scala> trait LogEnabled extends ConfApp {
     |   override def conf = super.conf.updated("log", true)
     | }
defined trait LogEnabled

scala> trait LogDisabled extends ConfApp {
     |   override def conf = super.conf.updated("log", false)
     | }
defined trait LogDisabled

scala> class MyApp extends ConfApp {
     |   val dbName = "my_app_db"
     |   println(conf)
     | }
defined class MyApp

scala> class MyApp2 extends ConfApp with LogDisabled {
     |   val dbName = "my_app_db2"
     |   println(conf)
     | }
defined class MyApp2

scala> new MyApp
Map(db -> my_app_db, foo -> bar)
res0: MyApp = MyApp@ccc268e

scala> new MyApp2
Map(db -> my_app_db2, foo -> bar, log -> false)
res1: MyApp2 = MyApp2@59d91aca

scala> new ConfApp with LogDisabled with LogEnabled {
     |   val dbName = "test1"
     |   println(conf)
     | }
Map(db -> test1, foo -> bar, log -> true)
res2: ConfApp with LogDisabled with LogEnabled = $anon$1@16dfdeda

scala> new ConfApp with LogEnabled with LogDisabled  {
     |   val dbName = "test2"
     |   println(conf)
     | }
Map(db -> test2, foo -> bar, log -> false)
res3: ConfApp with LogEnabled with LogDisabled = $anon$1@420c2f4a

如果你需要一个 val conf 而不是 def conf 你可以这样做:

If you need to have a val conf instead of def conf you could do this:

scala> class MyApp extends ConfApp {
     |   val dbName = "my_app_db"
     |   override val conf = super.conf
     |   println(conf)
     | }
defined class MyApp

scala> new MyApp
Map(db -> my_app_db, foo -> bar)
res4: MyApp = MyApp@17ebbd2a

这篇关于Scala - trait 成员初始化:使用 trait 修改类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆