它主要用于依赖注入 http://en.wikipedia.org/wiki/Dependency_injection,例如在蛋糕图案中。存在一个很棒的文章 http://jonasboner.com/real-world-scala-dependency-injection-di/涵盖了 Scala 中许多不同形式的依赖注入,包括 Cake 模式。如果你用谷歌搜索“Cake Pattern and Scala”,你会得到很多链接,包括演示文稿和视频。现在,这里有一个链接另一个问题 https://stackoverflow.com/questions/5172188/understanding-scalas-cake-pattern.
现在,至于自我类型和扩展特质之间有什么区别,这很简单。如果你说B extends A
, then B
is an A
。当你使用自我类型时,B
requires an A
。使用自我类型创建有两个特定要求:
- If
B
被延长,那么你required混入一个A
.
- 当一个具体类最终扩展/混合这些特征时,某些类/特征必须实现
A
.
考虑以下示例:
scala> trait User { def name: String }
defined trait User
scala> trait Tweeter {
| user: User =>
| def tweet(msg: String) = println(s"$name: $msg")
| }
defined trait Tweeter
scala> trait Wrong extends Tweeter {
| def noCanDo = name
| }
<console>:9: error: illegal inheritance;
self-type Wrong does not conform to Tweeter's selftype Tweeter with User
trait Wrong extends Tweeter {
^
<console>:10: error: not found: value name
def noCanDo = name
^
If Tweeter
是一个子类User
,就不会有错误。在上面的代码中,我们required a User
每当Tweeter
被使用,但是User
没有提供给Wrong
,所以我们得到了一个错误。现在,上面的代码仍在范围内,请考虑:
scala> trait DummyUser extends User {
| override def name: String = "foo"
| }
defined trait DummyUser
scala> trait Right extends Tweeter with User {
| val canDo = name
| }
defined trait Right
scala> trait RightAgain extends Tweeter with DummyUser {
| val canDo = name
| }
defined trait RightAgain
With Right
,混合的要求User
很满意。然而,上述第二个要求并没有得到满足:实施的负担User
仍然保留扩展的类别/特征Right
.
With RightAgain
这两个要求都得到满足。 AUser
和一个实施User
提供。
有关更多实际用例,请参阅本答案开头的链接!但是,希望现在你明白了。