好吧,我会解释我为什么问这个问题。这些天我开始阅读Live2.2源代码。如果您以前碰巧读过lift源代码,这是很好的。
在Lift中,我发现,定义内部类和内在特性是非常常用的。
对象菜单具有2个内部特征和4个内部类。对象Loc有18个内部类,5个内部特征,7个内部对象。
有很多代码都是这样写的。我想知道作者为什么这样写。
发布于 2011-01-13 16:09:49
在2.8之前,您必须在包和对象之间进行选择。包的问题是它们不能单独包含方法或值。所以你必须把所有的东西都放进另一个物体里,这会很尴尬。观察:
object Encrypt {
private val magicConstant = 0x12345678
def encryptInt(i: Int) = i ^ magicConstant
class EncryptIterator(ii: Iterator[Int]) extends Iterator[Int] {
def hasNext = ii.hasNext
def next = encryptInt(ii.next)
}
}现在您可以import Encrypt._并访问方法encryptInt以及类EncryptIterator。手巧!
相比之下,
package encrypt {
object Encrypt {
private[encrypt] val magicConstant = 0x12345678
def encryptInt(i: Int) = i ^ magicConstant
}
class EncryptIterator(ii: Iterator[Int]) extends Iterator[Int] {
def hasNext = ii.hasNext
def next = Encrypt.encryptInt(ii.next)
}
}这并没有太大的不同,但它使用户同时导入了encrypt._和encrypt.Encrypt._,或者不得不一遍又一遍地编写Encrypt.encryptInt。为什么不像第一种模式那样只使用对象呢?(实际上不存在性能损失,因为嵌套类实际上并不是幕后的Java内部类;据JVM所知,它们只是常规类,但是有一些花哨的名称,告诉您它们是嵌套的。)
在2.8中,你也可以吃蛋糕:把这个东西叫做包对象,编译器会为你重写代码,这样它实际上看起来就像引擎盖下的第二个例子(除了Encrypt实际上在内部被称为package ),但是在名称空间方面,它的行为就像第一个例子--就命名空间而言--这些值和防御程序就在那里,而不需要额外的导入。
因此,在2.8之前启动的项目通常使用对象来封装大量的东西,就像它们是一个包一样。在2.8之后,主要动机之一已被删除。(但要明确的是,使用对象仍然没有坏处;更重要的是它在概念上具有误导性,而不是它对性能或诸如此类的负面影响。)
(请注意,请不要试图用这种方式加密任何东西,除非是作为一个例子或一个笑话!)
发布于 2011-01-13 15:48:12
当您想要使用抽象类型变量时,有时需要在对象中放置类、特征和对象,请参见类型
发布于 2011-01-13 14:50:47
两者都可以。除其他外,内部类/特性的实例可以访问其父类的变量。内部类必须使用父实例创建,父实例是外部类型的实例。
在其他情况下,它可能只是将密切相关的事情分组的一种方式,如您的object示例所示。注意,特征LocParam是密封的,这意味着所有子类都必须位于同一个编译单元/文件中。
https://stackoverflow.com/questions/4681323
复制相似问题