Scala特质(特征)Trait

Scala特质(特征)Trait

场景简介

例:

某助教(TeachingAssistant.class)。他既是学生(Student.class)也是员工(Employee.class)。

理想情况是:

class Student {
    def id: String = ...
    ...
}
​
class Employee {
    def id: String =  ...
    ...
}
​
// 提醒:这是无法实现的多重继承示例
Class TeachingAssistant extends Student, Employee {
    ···
}

问题来了:scala和java一样不允许类从多个超类继承,但为什么不能有多重继承呢?

如果是 毫不相干 的多个类,多重继承只是把他们组合在一起,只要实现各自类中的方法就没问题。但如上面的例子所示,TeachingAssistant类继承了两个id方法,这显然是有冲突和混乱的(调用助教对象中的id方法时,无法确定返回学生id还是员工id)

再复杂些,假定Student类和Employee类都扩展自同一个超类Person:

class Person {
    var name: String = _
}
​
​
class Student extends Person {
    ...
}
​
​
class Employee extends Person {
    ...
}

这就引出了菱形继承问题

Teaching Assistant中的name字段要如何合并呢?又如何被构造呢?——扩展知识:C++的“虚拟基类”

Java的解决办法是采取强限制策略来规避这种使用:类只能扩展自一个超类;它可以实现任意数量的接口【但接口只能包含抽象方法,不能包含字段**Java8的特性中允许接口包含静态方法static和默认方法default,只是看起来似乎违反了接口作为一个抽象定义的理念】

Scala提供“特质”而非接口来解决这个问题。

特质比java接口更强大

首先,特质最大的特点就是可以同时拥有抽象方法和具体方法,与此同时一个基类可以像实现接口一样实现多个特质。

// 例如有一个Logger的特质(包含抽象方法)
trait Logger {
    // 这是个抽象方法(但不需要用abstract特别声明,因为特质中没有实现的方法默认就是抽象的)
    def log(msg: String): Unit
}
​
// 子类可以给出具体实现
// 用的是extends,而不是implements
class ConsoleLogger extends Logger {
    // 不需要写override,写上也没事
    def log(msg: String): Unit = {
        println(msg)
    }
}
​
// --------------------------------我是分割线-----------------------------------------
​
// 再例如有一个ConsoleLogger的特质(包含具体方法)
trait ConsoleLogger {
    def log(msg: String): Unit = {
        println(msg)
    }
}
​
// 子类使用ConsoleLogger
class SavingsAccount extends Account with ConsoleLogger {
    // 当账单金额大于余额时,显示账户余额不足,否则正常扣款
    def withdraw (amount: Double) {
        // 这里直接调用了ConsoleLogger特质中的log方法来实现
        if (amount > balance) log("Insufficient funds")
        else
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值