mixin系统的背后动机之一是消除传统的依赖注入。这种“组件风格(component style)”编程的高潮是是.
在我们的使用中,我们发现Scala本身删除了很多经典(构造函数)依赖注入的语法开销,我们更愿意就这样用: 它更清晰,依赖仍然植根于(构造)类型,而类构造语法是如此微不足道而变得轻而易举。有些无聊,简单,但有效。对模块化编程时使用依赖注入,特别是,组合优于继承—这使得程序更加模块化和可测试的。当遇到需要继承的情况,问问自己:在语言缺乏对继承支持的情况下如何构造程序?答案可能是令人信服的。
依赖注入典型的使用到 trait (译注:可以理解为和Java中Interface相似)
这是常见的注入工厂 — 用于产生其他对象的对象。在这些例子中,更青睐用简单的函数而非专有的工厂类型。
mkStream(PublicTweets).subscribe { tweet => publicCount += 1 }
mkStream(DMs).subscribe { tweet => dmCount += 1 }
}
保持traits简短并且是正交的:不要把分离的功能混在一个trait里,考虑将最小的相关的意图放在一起。例如,想象一下你要做一些IO的操作:
trait IOer {
def read(n: Int): Array[Byte]
分离两个行为:
可以将它们以混入(mix)的方式实现一个IOer : new Reader with Writer…接口最小化促使更好的正交性和更清晰的模块化。
Scala有很丰富的可见性修饰。使用这些可见性修饰很重要,因为它们定义了哪些构成公开API。公开APIs应该限制,这样用户不会无意中依赖实现细节并限制了作者修改它们的能力:
它们对于好的模块化设计是至关重要的。一般来说,扩展公开APIs比收缩公开的APIs容易的多。差劲的注释(annotation)也能危害到你代码向后的二进制兼容性。(译注:comments和annotation都可翻译成注释,但意义不同。annotation在Java和Scala有特定的含义)
private[this]
private val x: Int = ...
它对这个类的所有实例来说都是可见的(但对其子类不可见)。大多情况,你想要的是 private[this] 。
private[this] val: Int = ..
这个修饰限制了它只对当前特定的实例可见。Scala编译器会把private[this]翻译为一个简单的字段访问(因为访问仅限于静态定义的类),这样有时有助于性能优化。
单例类型
在Scala中创建单例类型是很常见的,例如:
在这种情况下,可以通过声明返回类型来限制可见性:
...
}
不要在正常情况下使用结构类型。结构类型有着便利且强大的特性,但不幸的是在JVM上的实现不是很高效。
然而——由于实现的怪癖——它提对执行反射(reflection)供了很好的简写形式。
val obj: AnyRef