class里定义object有何特殊含义?
fineqtbull
2009-10-10
Lift里Mapper的属性都是用object来定义,好像用object定义的属性是只读的,有点像val定义,但不知区别为何?如有知道的,还请指点一下。
import _root_.net.liftweb.mapper._ import _root_.java.math.MathContext class Expense extends LongKeyedMapper[Expense] with IdPK { def getSingleton = Expense object dateOf extends MappedDateTime(this) object description extends MappedString(this,100) object amount extends MappedDecimal(this, MathContext.DECIMAL64, 2) object account extends MappedLongForeignKey(this, Account) } |
|
alanwu
2009-10-10
可以把object看成是特殊的class,可以认为他是class的单例。
object不是变量因此不能再赋值,但他里面的字段可以赋值。 lift的所有字段都用object表示,更突出lift里所有东西都是有实际业务意义的对象。 比如object dateOf extends MappedDateTime(this) 如果在java中定义model可能就定义为: private Date dateOf; 那么他就是一个日期型字段,和bussiness model没太大关系。在Lift中,默认给这些字段类型定义了很多与业务相关的方法,比如asHtml,toForm,validate等,你也可以override这些默认方法。 这里的object可以当作是java的内类, 访问Scala的内类和访问方法一样用点。 object可以当作是实例化好的,因此不需要实例化,直接用就行了。 例如 Expense expense = Expense.create expense.dateOf(current) 这里是调用了Expense的内类dateOf,再调用了dateOf的apply方法, 等同于 Expense expense = Expense.create expense.dateOf.apply(current) |
|
fineqtbull
2009-10-10
alanwu 写道 ... 可以把object看成是特殊的class,可以认为他是class的单例。 ... 这里所说的单例,是否是指class范围的单例呢?那就有点像java中的static属性了。但是object的定义中传入了this,那应该更像是和class的实例相对应吧。 |
|
alanwu
2009-10-10
fineqtbull 写道 这里所说的单例,是否是指class范围的单例呢?那就有点像java中的static属性了。但是object定义中的传入了this,那应该更像是和class的实例相对应吧。 对的,scala的object和java的static类似,但他确实又是class的变形,可以在里面定义字段,方法,甚至再定义内部类。 |
|
fineqtbull
2009-10-10
alanwu 写道 fineqtbull 写道 这里所说的单例,是否是指class范围的单例呢?那就有点像java中的static属性了。但是object定义中的传入了this,那应该更像是和class的实例相对应吧。 对的,scala的object和java的static类似,但他确实又是class的变形,可以在里面定义字段,方法,甚至再定义内部类。 那是否可以理解为object即定义了类似java中的static类(不包含this引用),又在class的实例构造过程中创建了实例中的只读属性(但可以传入this引用)。 |
|
alanwu
2009-10-10
我的理解是object就是特殊的class
scala没有static,这个可以当做static用 |
|
fineqtbull
2009-10-10
alanwu 写道 我的理解是object就是特殊的class
scala没有static,这个可以当做static用 我想说的是,Scala中class内定义的object定义了相当于Java的类中内嵌static类,而这里的object实例本身并不相当于java中的static属性,而是相当于val属性。据我理解,java中的内嵌staic类与一般内嵌类的差别是static类访问不到外部包含类的实例的this指针;static属性则是另一个概念,它是java类中的是全局范围的属性,可以认为相当于Scala中包范围的object(单例)。 下面是一个模拟Lift中Mapper的例子: trait Mapper { var key : String = "key value" } class MappedString(val mapper:Mapper) { override def toString() : String = { super.toString() + ":" + mapper.key } } class Table1(keyStr : String) extends Mapper { key = keyStr object field1 extends MappedString(this) override def toString() : String = { "field1:"+field1 } } object Main extends Application { val t1 = new Table1("key1") val t2 = new Table1("key2") println(t1) println(t2) println(t1.field1) // var m = new Mapper {}; // t1.field1 = new MappedString(m) //由于是object,不可以赋值 } 下为执行结果: field1:Table1$field1$@22c95b:key1 field1:Table1$field1$@8814e9:key2 Table1$field1$@22c95b:key1 虽然field1是以object来定义的,但是不同的Table1实例有不同的field1属性,所以class中内嵌的object因该不可以称为单例,从效果来看更像val属性。 |
|
alanwu
2009-10-10
fineqtbull 写道 虽然field1是以object来定义的,但是不同的Table1实例有不同的field1属性,所以class中内嵌的object因该不可以称为单例,从效果来看更像val属性。 可以这么理解,所以scala object和java的static有本质区别。 他可以活在类实例上,同一个类不同实例上的object内容不一样, 而java的static是全局的,只能一样。 scala object如果独立存在,那他也能当全局的用。 |
|
night_stalker
2009-10-10
引用 The basic reason for this is that the MetaMapper needs access to
fields for its validation and form functionality; it is more difficult to cleanly define these properties in the MetaMapper if it had to access member vars on each instance since a MetaMapper instance is itself an object. 这种写法的不爽之处在于字段多了,就是满屏幕的 object ... extends ... mapper 和 record 都不太好玩 …… 他们最好向 linq to sql 学习一下 …… 为了敲得快,我写了几个 snippet (vim 的 snipMate),稍微修改可以弄成 netbeans 的 code template: snippet mapper /** ${1:comment} */ class ${2:klass} extends LongKeyedMapper[$2] with IdPK { def getSingleton = $2 ${3} } /** $2 singleton (metamapper) */ object $2 extends $2 with LongKeyedMetaMapper[$2] { } snippet fk MappedLongForeignKey(this, ${1}) snippet oe object ${1} extends ${2} snippet m2m object ${1:other}s extends HasManyThrough( this, ${2:Other}, ${3:JoinModel}, $3.$1, $3.${4}) |
|
alanwu
2009-10-10
Linq应该是纯粹的数据读写,而lift的mapper和record都带有业务功能,所以用途不一样。
像你说的那样,lift的这种方式不纯粹,混合了数据读写(ORM),业务功能,甚至页面展示,这样一个model做下来就比较庞大。好处也是比较明显,就是以业务model为中心,什么都集中在一起,开发起来比较快。 |