2012-06-05 37 views
0

我是scala的新手,無法理解Lift人如何實現Record API。但是,這個問題不是關於這個API,而是關於Scala的一般問題。我對Lift中使用的類模式中的對象的工作方式感興趣。類框架中的對象如何在Lift Framework中使用?

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 

這可能是由於使用的應用方法做了什麼?但同時你可以通過做這樣的事情來獲得價值:

val name = md1.name 

這是如何工作的?在課堂範圍內的對象是不是靜態的。或者他們只是一些內部表示的構造函數類?如何迭代所有字段,你使用反射?

感謝, 奧托

回答

1

你說的沒錯它作爲apply方法。 Record的Field base class定義了幾個apply方法。

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

通過返回OwnerType,您可以將調用鏈接在一起。

關於使用object來定義字段,我也開始困惑。 object標識符定義特定範圍內的對象。儘管將object作爲singleton pattern的快捷方式很方便,但它比這更靈活。根據Scala Language Spec(第5.4節):

這大致相當於一個懶惰值以下德音響nition:
lazy val m = new sc with mt1 with ... with mtn { this: m.type => stats }

<剪斷/>

膨脹給出以上對於頂層對象並不準確。這不可能是因爲變量和方法的定義不能出現在包對象(§9.3)的頂層以外的頂層。相反,頂層對象被轉換爲靜態字段。

關於迭代在所有領域,Record對象定義一個allFields方法,它返回一個List[net.liftweb.record.Field[_, MyType]]

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性狀確實含有一種適用方法是設置等同。這就是爲什麼您可以在實例化對象後按名稱分配字段的原因。

字段引用你提到:

val name = md1.name 

會爲StringField鍵入名稱。如果你的想法是

val name: String = md1.name 

將無法​​編譯(除非有一個隱式的範圍內轉換字段[T] => T)。正確的方法檢索該字段的字符串值將是

val name = md1.name.get 

記錄確實使用反射收集字段。在類中定義對象時,編譯器將創建一個字段來保存對象實例。從反思的角度來看,該對象看起來非常類似於我之前提到的定義字段的替代方式。每個定義可能創建一個字段類型的子類,但這與

val name = new StringField(this, 12) { 
    override def label: NodeSeq = <span>My String Field</span> 
} 
沒有什麼不同
相關問題