如何在Lift Framework中使用类模式中的对象?

时间:2012-06-05 16:59:36

标签: scala lift mapper

我是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

这一切如何运作?在类的范围内,对象不是静态的。或者它们只是一些内部表示的构造函数类?如何迭代所有字段,你使用Reflection?

谢谢, 奥托

2 个答案:

答案 0 :(得分: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 trait确实包含一个与set等效的apply方法。这就是为什么你可以在实例化对象后按名称分配字段。

您提到的字段参考:

val name = md1.name

将类型名称键入StringField。如果你在想什么

val name: String = md1.name

将无法编译(除非在范围内隐含转换Field [T] => T)。检索字段的String值的正确方法是

val name = md1.name.get

记录确实使用反射来收集字段。在类中定义对象时,编译器将创建一个字段来保存对象实例。从反射的角度来看,该对象看起来非常类似于我之前提到的定义字段的替代方式。每个定义可能会创建字段类型的子类,但这与

没有区别
val name = new StringField(this, 12) {
  override def label: NodeSeq = <span>My String Field</span>
}

答案 1 :(得分:1)

你认为它是apply方法是正确的。记录的Field base class定义了一些apply方法。

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

通过返回OwnerType,您可以将调用链接在一起。

关于使用object来定义字段,一开始也让我很困惑。 object标识符定义特定范围内的对象。尽管将object视为singleton pattern的快捷方式很方便,但它比这更灵活。根据{{​​3}}(第5.4节):

  

它大致等同于以下懒惰值的定义:
    lazy val m = new sc with mt1 with ... with mtn { this: m.type => stats }

&LT;剪断/&GT;

  

上面给出的扩展对于顶级对象不准确。它不可能是因为变量和方法定义不能出现在a的顶层   包对象(第9.3节)。相反,顶级对象被转换为静态字段。

关于迭代所有字段,Record个对象定义了allFields方法,该方法返回List[net.liftweb.record.Field[_, MyType]]