Scala 有一个自身类型(self-type) 的东西,由来已久,居然今天才发现。如果一个类或 trait 指明了 self-type 类型(包括类和特质),它的子类型或是对象也必须是相应的类型。它产生的效果与继承(或 mixin) 颇有几分相似。self-type 的语法是 this 的别名: 某一类型(class 或 trait)
, 直接看一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class User(val name: String) trait Tweeter { this: User => //这个表示 Tweeter 本身也必须是一个 User,它的子类型必须想办法符合这一要求 def tweet(tweetText: String) = { println(s"$name: $tweetText") } } class VerifiedTweeter(val username: String) extends User(username) with Tweeter { //Tweeter 要求这个类必须是一个 User, 所以需要继承自 User 类 } val v = new VerifiedTweeter("Yanbin") v.tweet("Hello") |
上面 this: User =>
中的 this
只是一个别名,可以是 self
或任何有效标识(如 abc: User
),这里使用 this
等于未指定别名,与原本的 this 重叠了。如果声明为非 this
的话则可以这么用
1 2 3 4 5 6 |
trait Tweeter { abc: User => def tweet(tweetText: String) = { println(s"${this.name}-${abc.name}: $tweetText") } } |
this
永远都在,同时 abc
与 this
是完全一样的效果。
注(2018-02-14): 这个语法只是用作 this 别名的话,后面可以不用接类型,例如
1 2 3 4 |
trait Tweeter { abc => .... //代码中 abc 就是 this 的别名,它们是等效的 } |
如果在声明 VerifiedTweeter
类只是混入 Tweeter 特质会怎么样呢?以下两种声明都将产生同样的编译错误
如果 User
也是一个 trait,那么声明 VerifiedTweeter1
时可以同时混入 User
, 即
1 |
trait VerifiedTweeter1 extends Tweeter with User |
由于前面 User
也是一个类,所以需要让 mixin Tweeter
的类继承自 User
, 就是
1 2 3 |
class VerifiedTweeter(val username: String) extends User(username) with Tweeter { } |
self-type
可以指定多重类型,那么声明子类型或创建实例时也要符合多种类型
1 2 3 4 5 6 7 8 9 10 11 |
trait User trait Animal trait Tweeter { this: User with Animal => } class VerifiedTweeter extends Tweeter with User with Animal //直接创建实例 new Tweeter with User with Animal |
还有一种结构类型的 self-type
, 更像是匿名类型的 self-type
, 不是指定类型名而是类型必须实现的方法,例如
this: {def say: Unit} =>
要求在 Tweeter 中必须实现该方法,如
1 2 3 4 5 6 7 8 9 10 11 12 |
class Tweeter extends User { def say: Unit = { println("say something") } } //或者创建匿名的 User 类及实例 val user = new User { def say: Unit = { println("say something") } } |
最后,注意一下 this: User =>
这个语法后不能用大括号括起后续的代码
1 2 3 4 5 6 7 |
trait Tweeter { this: User => { def tweet(tweetText: String) = { println(s"$name: $tweetText") } } } |
以上代码编译没有问题,但创建的 Tweeter
实例是看不到 tweet(...)
方法的。
链接:
本文链接 https://yanbin.blog/scala-self-type-understanding/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。