1

是否可以通过 Scala 中的继承来构建不可变列表?我有一个创建 MenuBar 的基本特征。MenuBar 将具有标准标题:文件、编辑、视图/窗口、帮助等。我希望继承特征能够将子项添加到菜单标题。我希望动态创建菜单,因此将有一个函数列表,在打开菜单以创建子树时将调用这些函数。由于函数列表将在编译时已知,因此如果它可以是一个不可变列表会很好。

Scala 中是否有任何方法可以通过构造函数/初始化层次结构创建不可变列表?如果不是在 Scala 中,是否有任何语言提供此功能?

用一个使用可变列表的简单示例来说明问题。TrA 和 TrB 彼此独立编写:

trait Base
{
  val list = scala.collection.mutable.LinkedList[String]()
}
trait TrA extends Base
{
  list += "A"
}
trait TrB extends Base
{
  list += "B"
}

val ab = new TrA with TrB {}

由于 List 的内容在编译时是已知的,是否有使其成为val 不可变列表?当然,任何可变集合都可以通过 def 调用公开为不可变集合。

以下将编译:

trait Base
{ val list: List[String] = Nil }

trait TrA extends Base
{ val list = "A" :: super.list }

trait TrB extends Base
{ val list = "B" :: super.list }

val ab = new TrA with TrB {}

但是如果不抛出空异常就无法初始化。使 val list 变得懒惰也无济于事,因此需要 0__ 的解决方案。

4

2 回答 2

4

这与我记得的一个较老的问题非常相似;我再也找不到它了,所以我尝试重建方法:

trait Base {
  protected def contribute : List[String] = Nil

  val list = contribute
}

trait TrA extends Base {
   override protected def contribute = "A" :: super.contribute
}

trait TrB extends Base {
   override protected def contribute = "B" :: super.contribute
}

val x = new TrA with TrB {}
x.list  // List(B, A)
val y = new TrB with TrA {}
y.list  // List(A, B)
于 2012-09-24T21:05:19.323 回答
0

我会隐藏列表的可变部分,以便只有后代Base可以添加到它(没有别的):

trait Base {
  private val theList = scala.collection.mutable.LinkedList[String]()

  protected def add(item: String) {
    theList += item;
  }

  // return only an immutable copy of the list
  def list: Seq[String] = theList.toSeq; // or .toList, .toSet, etc.
}

trait TrA extends Base {
  add("Apple")
}

trait TrB extends Base {
  add("Orange")
}

虽然行为不端的后代仍然可以在以后添加一些项目,但从外部修改列表是不可能的。也许可以用替换def listlazy val list获得一些效率,但你必须确保它没有在任何构造函数中被调用。

于 2012-09-24T20:28:53.007 回答