1

Scalaでの継承を通じて不変リストを作成することは可能ですか?MenuBarを作成する基本特性があります。MenuBarには、標準のヘッダー(File、Edit、View / Window、Helpなど)があります。継承する特性を使用して、メニュー見出しにサブアイテムを追加できるようにします。メニューを動的に作成したいので、メニューを開いてサブツリーを作成するときに呼び出される関数のリストがあります。関数のリストはコンパイル時にわかるので、不変のリストであると便利です。

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 {}

リストの内容はコンパイル時にわかっているので、とにかくそれを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 {}

ただし、null例外をスローせずに初期化することはできません。valリストを怠惰にすることも役に立たないので、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 list効率をlazy val list上げるために に置き換えることは可能かもしれませんが、どのコンストラクターでも呼び出されていないことを確認する必要があります。

于 2012-09-24T20:28:53.007 に答える