Scala trait嵌套属性定义问题及内部匿名Trait实现咨询
嘿,作为从Java转Scala的新手,你碰到的都是Scala trait和匿名对象实现的小细节问题,我来一步步帮你修正并解释清楚~
第一部分:修正你的原代码
你的代码主要有三个小错误,我先给你修正后的可运行版本,再逐个解释:
trait Person { def name: String def age: Int def address: Address // 修正:这里是声明返回Address类型的抽象成员,不是extends } trait Address { def streetName: String def streetNumber: Int def city: String } object aPerson extends Person { override val name = "John" override val age = 25 // 修正:必须加val,因为要实现Person里的抽象def age override val address = new Address { // 修正:匿名对象要显式混入Address trait override def streetName = "Main St." override def streetNumber = 120 override def city = "Sometown" } }
错误点解释:
- Person trait里的address声明错误:你写的
def address extends Address是Scala不支持的语法,正确的写法是def address: Address——这是在声明一个抽象成员,要求实现它的类/对象提供一个Address类型的成员(可以是val或def,Scala里val可以覆盖def,因为val是一种特殊的无参数def)。 - override age时缺少val:Person里的
age是抽象def,你在实现的时候必须用override val(或者override def)来定义具体值,不然编译器会认为你没有正确实现抽象成员。 - 匿名对象没有混入Address trait:你直接写
object { ... }创建的是一个普通匿名对象,并不是Address类型的。必须用new Address { ... }的方式,让这个匿名对象混入Addresstrait,这样才能满足Person对address类型的要求。
第二部分:附加问题——把Address放在Person内部
当然可以!如果Address只在Person相关的代码里使用,完全可以把它定义成Person的内部trait,这样不会污染外部命名空间,让文件结构更整洁。代码示例如下:
trait Person { // 把Address作为Person的内部trait,作用域仅限Person内部 trait Address { def streetName: String def streetNumber: Int def city: String } def name: String def age: Int def address: Address // 这里的Address就是上面定义的内部trait } object aPerson extends Person { override val name = "John" override val age = 25 // 创建内部trait的匿名实现,用this.Address明确指向Person内部的Address override val address = new this.Address { override def streetName = "Main St." override def streetNumber = 120 override def city = "Sometown" } }
小提示:
创建内部trait的匿名对象时,this.Address可以简化成Address(因为在Person的实现类里,默认会优先找内部的trait),不过写this.会更清晰,尤其是当外部也有同名trait的时候。
内容的提问来源于stack exchange,提问作者J-bob
相关产品推荐
相关产品推荐

