Step into Scala - 15 - 特质
来源:互联网 发布:sql select 两个字段 编辑:程序博客网 时间:2024/06/05 16:10
目录
- 特质
- 概念
- 定义一个特质
- 实现特质
- 继承特质
- 带有特质的对象
- 特质的构造顺序
- 叠加在一起的特质
- 什么时候应该使用特质而不是抽象类
- 特质
摘要
特质概念,定义特质,抽象方法,抽象属性,实现多个特质,继承特质,带有特质的对象,特质构造顺序,特质与抽象类
特质
概念
- 特质是一些字段和行为的集合
- 特质可以同时拥有抽象方法和具体方法
- 一个类可以实现多个特质
- 特质不能有带参数的构造函数。
定义一个特质
trait Logger { //字段 val brand: String val minLength: Int //行为 //抽象方法 def log(msg: String) //带有具体实现 def echo(msg: String) { println(msg) } //依赖抽象方法 def info(msg: String) = log("INFO" + msg)}
- 特质使用关键字 trait 声明
- 特质中可以有抽象方法和抽象属性,且复写时无需使用关键字
override
- 特质中的方法可以互相依赖,即使是依赖抽象方法
实现特质
实现特质使用关键字 extends
,之后如果需要实现多个特质时,则使用关键字 with
class ConsoleLogger extends Logger with Cloneable with Serializable { //实现抽象方法 def log(msg: String): Unit = println(msg) //实现抽象属性 val minLength: Int = 1}
以上代码实际内部是将 Logger with Cloneable with Serializable
看作了一个整体类进行了继承。
继承特质
trait Logger { def show(msg: String) {} def log(msg: String)}trait OutputLogger extends Logger{ override def show(msg: String): Unit = println(msg) //重写抽象方法 abstract override def log(msg: String): Unit = { super.log(msg) }}
- 特质也可以继承特质
- 如果需要在重写的抽象方法中调用父类特质的抽象方法,必须将方法本身声明为抽象的,即
abstract
。
带有特质的对象
可以为单个对象添加特质
trait Logger { def show(msg: String) {}}trait OutputLogger extends Logger{ override def show(msg: String): Unit = println(msg)}class LoggerExample extends Logger {}val logger1 = new LoggerExamplelogger1.say("hello")//为单个对象添加特质val logger2 = new LoggerExample with OutputLoggerlogger2.say("hello world") //hello world
特质的构造顺序
特质构造顺序遵循以下原则
- 首先调用超类的构造器
- 特质构造器在超类构造器之后,类构造器之前执行
- 特质由左至右被构造
- 每个特质中,父特质先被构造
- 如果多个特质有同一个父特质,且父特质已被构造了,则不会被再次构造
- 所有特质构造完毕,子类才被构造
例
有如下类
class SavingAccount extends Account with FileLogger with ShortLogger
则构造顺序为
- Account
- Logger
- FileLogger
- ShortLogger
- SavingAccount
在 ShortLogger 中调用 super 会执行 FileLogger 的方法
叠加在一起的特质
一般情况下,特质总是从最后一个开始向前执行
trait Logger { def show(msg: String) {}}trait TimeStampLogger extends Logger { override def show(msg: String): Unit = { super.show(new Date() + " " + msg) }}trait ShortLogger extends Logger { val maxLength = 15 override def show(msg: String): Unit = { super.show( if (msg.length <= maxLength) msg else msg.substring(0, maxLength - 3) + "..." ) }}class LoggerExample extends Logger {}val logger3 = new LoggerExample with OutputLogger with TimeStampLogger with ShortLoggerlogger3.show("hello world logger3") //Mon Feb 16 11:46:06 CST 2015 hello world ...val logger4 = new LoggerExample with OutputLogger with ShortLogger with TimeStampLoggerlogger4.show("hello world logger4") //Mon Feb 16 1...
什么时候应该使用特质而不是抽象类?
如果你想定义一个类似接口的类型,你可能会在特质和抽象类之间难以取舍。这两种形式都可以让你定义一个类型的一些行为,并要求继承者定义一些其他行为。一些经验法则:
- 优先使用特质。一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。
- 如果你需要构造函数参数,使用抽象类。因为抽象类可以定义带参数的构造函数,而特质不行。
- 如果需要类从 Java类继承,使用抽象类。
- 如果需要考虑效率问题,使用抽象类。Java的动态绑定机制决定了直接方法要快于接口方法。而特质最终是被编译成接口。
0 0
- Step into Scala - 15 - 特质
- Step into Scala - 02 - 数据类型
- Step into Scala - 07 - 异常
- Step into Scala - 08 - 数组
- Step into Scala - 09 - 集合
- Step into Scala - 11 - 类
- Step into Scala - 14 - 继承
- Step into Scala - 17 - 泛型
- Step into Scala - 18 - Function
- Step into Scala - 22 - Xml
- Step into Scala - 24 - Option
- Step into Scala - 25 - Actor
- Step into Scala - 32 - Test
- Step into Scala - 01 - 安装与运行
- Step into Scala - 04 - 操作符
- Step into Scala - 05 - 块与函数
- Step into Scala - 06 - 流程控制
- Step into Scala - 12 - 对象与枚举
- RaspberryPi+SAE+Wechat打造智能家居篇(一)
- Android Studio 使用Support.v7和support.v4包遇到的各种问题
- wince6.0 编译报错:"error C2220: warning treated as error - no 'object' file generated"的解决办法
- Step into MongoDB - 16 - 账号管理
- 数字证书
- Step into Scala - 15 - 特质
- office2007每次打开都要配置文件,怎么取消配置
- jsp页面获取数据方法
- 第九周项目3(2)-分数类中的运算符重载(续)
- JavaScript 函数回调
- mysql数据库下hibernate无法自动建表
- Scala字符串处理常用函数
- hdu5215(判环总结)
- csu 1605: Target Sudoku(Dancing Links)