2

列挙の値を保持し、列挙の可能な値へのアクセスも許可するジェネリック クラスを作成したいと考えています。たとえば、プロパティ エディタについて考えてみましょう。プロパティの現在の値を知る必要があり、プロパティに対して有効な他の値も知る必要があります。また、列挙のタイプを事前に知る必要はありません。あらゆる種類の列挙を操作できる必要があります。

私の最初の考えは次のようなものでした:

class EnumerationProperty[T <: Enumeration](value:T)

ただし、列挙型の T は型ではなく、オブジェクトであるため、これは機能しません。私が試した他のバリエーションは次のとおりです。

class EnumerationProperty[T <: Enumeration](value:T.Value)
class EnumerationProperty[T <: Enumeration.Value](value:T)

(なぜこれらが機能しないのかについては、興味深い理由ではないと思われるため、詳しくは説明しません。)

4

3 に答える 3

5

質問の最初の部分。次のように、一般的な列挙値のホルダーを定義できます。

case class EnumerationProperty[T <: Enumeration#Value](value:T)

しかし、列挙オブジェクトを明示的に渡さずにすべての列挙値を取得する方法がわかりません。列挙にはvalues()、すべての値を取得するメソッドがあります。Enumeration#Value には Enumeration へのリンクがありますが、プライベート アクセスがあります

于 2013-01-22T05:37:44.067 に答える
3

あなたのユース ケース (プロパティ エディター) では、最良の解決策は scala 2.10 で利用可能な scala リフレクションに依存することだと思います。クラスのTypeTagを指定すると、そのすべてのメンバーとその値の完全な型 (消去なし) を取得し、そこからプロパティ エディターに入力できます。列挙型の場合は、 を使用TypeTagして次の方法で値を取得します: Scala 2.10 リフレクションを使用して、列挙型の値を一覧表示するにはどうすればよいですか?


さて、あなたは scala リフレクションを使いたくない、あるいは使えないかもしれません。それが本当なら、あなたはワームの缶全体を開いています:) TL;DR:これは標準を使用して不可能であるEnumerationため、おそらく Ptharien's Flame's answer に示されているように列挙値を明示的にラップする必要がありますのフォークEnumeration)。以下に、私のすべての試みについて詳しく説明します。ご容赦ください。

残念ながら、私には不明な理由で (シリアライゼーションの問題に関係していると思われますが)、そのインスタンスEnumeration.Valueを指すフィールドがありません。Enumerationがどのように実装されているかを考えるとEnumeration、これは簡単に実装できますが、もちろん、Enumeration を fork してバージョンを変更する以外には何も言えません (これは、まさにこの目的のために行ったものであり、さらにシリアライゼーションとリフレクションの適切なサポートを追加するために行ったものですが、掘り下げます)。

を変更できない場合はEnumeration、拡張するだけでよいでしょうか? 実装をもう一度見ると、次のようなものが機能しているように見えます。

class EnumerationEx extends Enumeration {
  protected class ValEx(i: Int, name: String) extends Val(i, name) {
    @transient val enum: Enumeration = EnumerationEx.this
  }
  override protected def Value(i: Int, name: String): Value = new ValEx(i, name)  
}

object Colors extends EnumerationEx {
  val Red, Green, Blue = Value
}

欠点は、EnumerationExの代わりに明示的に拡張する列挙に対してのみ機能Enumerationすることですが、何もないよりはましです。

残念ながら、これは単にdef Value ...final が宣言されているためにコンパイルされEnumerationないため、オーバーライドする方法がありません。(分岐Enumerationによってこれを回避できることに注意してください。実際には、カスタムの列挙型を使用する道を既に進んでいるので、そうしない理由はありません。判断はあなたに任せます)。

したがって、ここに別の見方があります:

class EnumerationEx extends Enumeration {
  class ValueWithEnum( inner: Value ) {
    @transient val enum: Enumeration = EnumerationEx.this
  }
  implicit def valueToValue( value: Value ): ValueWithEnum = new ValueWithEnum( value )
}

実際、期待どおりに動作します。というかそうらしい。

scala> object Colors extends EnumerationEx {
     |   val Red, Green, Blue = Value
     | }
defined module Colors

scala> val red = Colors.Red
red: Colors.Value = Red

scala> red.enum.values
res58: Enumeration#ValueSet = Colors.ValueSet(Red, Green, Blue)

万歳?いいえ、 からValueへの変換は、列挙型のインスタンス化時ではなく、 へのValueWithEnumアクセス時にのみ行われるためです。言い換えれば、呼び出し時に、コンパイラーは列挙型の正確な静的型を知る必要があります (コンパイラーは、赤の型がだけでなく であることを静的に認識している必要があります)。そして、あなたが言及したユースケース(プロパティエディター)では、列挙値のタイプを取得するためにJavaリフレクション(すでにスカラリフレクションを使用しないと想定しています)にのみ依存でき、Javaリフレクションは( extends ) のタイプとして。したがって、基本的にここで立ち往生しています。あなたの最善の策は、最初にscalaリフレクションを使用することです。red.enumColorsenumColors.ValueEnumeration# ValueEnumeration#ValEnumeration#ValueColors.Red

于 2013-01-22T09:26:56.063 に答える
0
class EnumProps[E <: Enumeration](val e: E)(init: e.Value) {...}

次に、 と を使用ee.Valueてクラスを実装できます。

于 2013-01-22T06:10:47.703 に答える