为什么人们在Scala中的另一个对象中定义类,特征,对象?

Saw*_*yer 26 scala lift

好的,我会解释为什么我会问这个问题.这几天我开始阅读Lift 2.2源代码.如果您之前正好读过电梯源代码,那就太好了.

在Lift中,我发现,定义内部类和内部特征的使用非常频繁.

对象菜单有2个内部特征和4个内部类.对象Loc有18个内部类,5个内部特征,7个内部对象.

有很多代码写得像这样.我想知道为什么作者这样写.

  • 是因为这是作者的个人品味还是语言功能的强大运用?
  • 对于这种用法有任何权衡吗?

Rex*_*err 22

在2.8之前,您必须在包和对象之间进行选择.包的问题是它们不能自己包含方法或val.所以你必须将所有这些放在另一个对象中,这可能会变得很尴尬.注意:

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)
  }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以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)
  }
}
Run Code Online (Sandbox Code Playgroud)

这并不是一个巨大的差异,但它会让用户同时导入encrypt._和/ encrypt.Encrypt._或不得不Encrypt.encryptInt一遍又一遍地写作.为什么不直接使用对象,就像在第一个模式中一样?(实际上没有性能损失,因为嵌套类实际上并不是Java内部类;它们只是JVM知道的常规类,但是用花哨的名称告诉你它们是嵌套的.)

在2.8中,你可以拥有你的蛋糕并吃它:把东西称为包对象,编译器会为你重写代码,所以它实际上看起来像引擎盖下的第二个例子(除了对象Encrypt实际上是在package内部调用),但就行为而言,行为就像第一个例子 - vals和defs就在那里,而不需要额外的导入.

因此,在2.8之前启动的项目通常使用对象来封装大量的东西,就好像它们是一个包.2.8之后,其中一个主要动机已被删除.(但要明确的是,使用一个对象仍然没有受到伤害;更多的是它在概念上具有误导性,而不是它对性能或其他方面产生负面影响.)

(PS请,请不要尝试实际加密任何方式,除非作为一个例子或笑话!)