0

私は scala を初めて使用するので、Lift 担当者が Record API をどのように実装したかについて理解できません。ただし、問題はこの API についてではなく、Scala 全般についてです。Lift で使用されるクラス パターン内のオブジェクトがどのように機能するかに興味があります。

class MainDoc private() extends MongoRecord[MainDoc] with ObjectIdPk[MainDoc] {
  def meta = MainDoc

  object name extends StringField(this, 12)
  object cnt extends IntField(this)
}

object MainDoc extends MainDoc with MongoMetaRecord[MainDoc]

上のスニペットでは、Lift でレコードがどのように定義されているかを確認できます。興味深いのは、フィールドがオブジェクトとして定義されていることです。API を使用すると、次のようにインスタンスを作成できます。

val md1 = MainDoc.createRecord
  .name("md1")
  .cnt(5)
  .save

これはおそらくapplyメソッドを使用して行われますか?しかし同時に、次のようなことを行うことで値を取得できます。

val name = md1.name

これはどのように機能しますか?クラスのスコープ内にある場合、オブジェクトはそれほど静的ではありません。それとも、内部表現の単なるコンストラクタークラスですか? すべてのフィールドを反復処理するにはどうすればよいですか? リフレクションを使用しますか?

ありがとう、オットー

4

2 に答える 2

3

オット、

あなたは正しい軌道に乗っていません。実際にはフィールドをオブジェクトとして定義する必要はありません。例を次のように書くこともできます

class MainDoc private() extends MongoRecord[MainDoc] with ObjectIdPk[MainDoc] {
  def meta = MainDoc

  val name = new StringField(this, 12)
  val cnt= new IntField(this)
}

object MainDoc extends MainDoc with MongoMetaRecord[MainDoc]

net.liftweb.record.Field トレイトには、set と同等の apply メソッドが含まれています。そのため、オブジェクトをインスタンス化した後でフィールドを名前で割り当てることができます。

あなたが言及したフィールド参照:

val name = md1.name

name を StringField として入力します。もしあなたが思っていたことが

val name: String = md1.name

これはコンパイルに失敗します (Field[T] => T を変換する暗黙のスコープがない限り)。フィールドの文字列値を取得する適切な方法は次のとおりです。

val name = md1.name.get

レコードはリフレクションを使用してフィールドを収集します。クラス内でオブジェクトを定義すると、コンパイラはオブジェクト インスタンスを保持するフィールドを作成します。リフレクションの観点からは、オブジェクトは、前に説明したフィールドを定義する別の方法と非常によく似ています。それぞれの定義はおそらくフィールド型のサブクラスを作成しますが、それは

val name = new StringField(this, 12) {
  override def label: NodeSeq = <span>My String Field</span>
}
于 2012-06-05T18:20:40.577 に答える
1

あなたはそれがapply方法であることについて正しいです。Record のField基本クラスは、いくつかのapplyメソッドを定義します。

def apply(in: Box[MyType]): OwnerType
def apply(in: MyType): OwnerType

を返すことOwnerTypeで、呼び出しを連鎖させることができます。

objectフィールドを定義するための の使用に関しては、最初は私も戸惑いました。識別子は、特定のスコープ内のobjectオブジェクトを定義します。シングルトン パターンobjectのショートカットと考えると便利ですが、それよりも柔軟です。Scala 言語仕様(セクション 5.4)によると:

これは、次の遅延値の定義とほぼ同じです。
lazy val m = new sc with mt1 with ... with mtn { this: m.type => stats }

<中略/>

上記の展開は、トップレベル オブジェクトに対しては正確ではありません。これは、変数とメソッドの定義がパッケージ オブジェクトの外側の最上位に表示されないためです (§9.3)。代わりに、最上位オブジェクトは静的フィールドに変換されます。

すべてのフィールドの繰り返しに関して、RecordオブジェクトはallFieldsを返すメソッドを定義しますList[net.liftweb.record.Field[_, MyType]]

于 2012-06-05T18:16:51.893 に答える