将trait作为接口使用

 1 // Scala中的Triat是一种特殊的概念2 // 首先我们可以将Trait作为接口来使用,此时的Triat就与Java中的接口非常类似3 // 在triat中可以定义抽象方法,就与抽象类中的抽象方法一样,只要不给出方法的具体实现即可4 // 类可以使用extends关键字继承trait,注意,这里不是implement,而是extends,在scala中没有implement的概念,无论继承类还是trait,统一都是extends5 // 类继承trait后,必须实现其中的抽象方法,实现时不需要使用override关键字6 // scala不支持对类进行多继承,但是支持多重继承trait,使用with关键字即可7 8 trait HelloTrait {9   def sayHello(name: String)
10 }
11 trait MakeFriendsTrait {
12   def makeFriends(p: Person)
13 }
14 class Person(val name: String) extends HelloTrait with MakeFriendsTrait with Cloneable with Serializable {
15   def sayHello(name: String) = println("Hello, " + name)
16   def makeFriends(p: Person) = println("Hello, my name is " + name + ", your name is " + p.name)
17 }

在Trait中定义具体方法

 1 // Scala中的Triat可以不是只定义抽象方法,还可以定义具体方法,此时trait更像是包含了通用工具方法的东西// 有一个专有的名词来形容这种情况,就是说trait的功能混入了类2 // 举例来说,trait中可以包含一些很多类都通用的功能方法,比如打印日志等等,spark中就使用了trait来定义了通用的日志打印方法3 4 trait Logger {5   def log(message: String) = println(message)6 }7 8 class Person(val name: String) extends Logger {9   def makeFriends(p: Person) {
10     println("Hi, I'm " + name + ", I'm glad to make friends with you, " + p.name)
11     log("makeFriends methdo is invoked with parameter Person[name=" + p.name + "]")
12   }
13 }

在Trait中定义具体字段

 1 // Scala中的Triat可以定义具体field,此时继承trait的类就自动获得了trait中定义的field2 // 但是这种获取field的方式与继承class是不同的:如果是继承class获取的field,实际是定义在父类中的;而继承trait获取的field,就直接被添加到了类中3 4 trait Person {5   val eyeNum: Int = 26 }7 8 class Student(val name: String) extends Person {9   def sayHello = println("Hi, I'm " + name + ", I have " + eyeNum + " eyes.")
10 }

在Trait中定义抽象字段

// Scala中的Triat可以定义抽象field,而trait中的具体方法则可以基于抽象field来编写
// 但是继承trait的类,则必须覆盖抽象field,提供具体的值trait SayHello {val msg: Stringdef sayHello(name: String) = println(msg + ", " + name)
}class Person(val name: String) extends SayHello {val msg: String = "hello"def makeFriends(p: Person) {sayHello(p.name)println("I'm " + name + ", I want to make friends with you!")}
}

为实例混入trait

 1 // 有时我们可以在创建类的对象时,指定该对象混入某个trait,这样,就只有这个对象混入该trait的方法,而类的其他对象则没有2 3 trait Logged {4   def log(msg: String) {}5 }6 trait MyLogger extends Logged {7   override def log(msg: String) { println("log: " + msg) }8 }  9 class Person(val name: String) extends Logged {
10     def sayHello { println("Hi, I'm " + name); log("sayHello is invoked!") }
11 }
12
13 val p1 = new Person("leo")
14 p1.sayHello
15 val p2 = new Person("jack") with MyLogger
16 p2.sayHello

trait调用链

 1 // Scala中支持让类继承多个trait后,依次调用多个trait中的同一个方法,只要让多个trait的同一个方法中,在最后都执行super.方法即可2 // 类中调用多个trait中都有的这个方法时,首先会从最右边的trait的方法开始执行,然后依次往左执行,形成一个调用链条3 // 这种特性非常强大,其实就相当于设计模式中的责任链模式的一种具体实现依赖4 trait Handler {5   def handle(data: String) {}6 }7 trait DataValidHandler extends Handler {8   override def handle(data: String) {9     println("check data: " + data)
10     super.handle(data)
11   }
12 }
13 trait SignatureValidHandler extends Handler {
14   override def handle(data: String) {
15     println("check signature: " + data)
16     super.handle(data)
17   }
18 }
19 class Person(val name: String) extends SignatureValidHandler with DataValidHandler {
20   def sayHello = { println("Hello, " + name); handle(name) }
21 }
22 

在trait中覆盖抽象方法

 1 // 在trait中,是可以覆盖父trait的抽象方法的2 // 但是覆盖时,如果使用了super.方法的代码,则无法通过编译。因为super.方法就会去掉用父trait的抽象方法,此时子trait的该方法还是会被认为是抽象的3 // 此时如果要通过编译,就得给子trait的方法加上abstract override修饰4 5 trait Logger {6   def log(msg: String)7 }8 9 trait MyLogger extends Logger {
10   abstract override def log(msg: String) { super.log(msg) }
11 }
12
13
14 

混合使用trait的具体方法和抽象方法

 1 // 在trait中,可以混合使用具体方法和抽象方法2 // 可以让具体方法依赖于抽象方法,而抽象方法则放到继承trait的类中去实现3 // 这种trait其实就是设计模式中的模板设计模式的体现4 5 trait Valid {6   def getName: String7   def valid: Boolean = {8     getName == "leo"    9   }
10 }
11 class Person(val name: String) extends Valid {
12   println(valid)
13   def getName = name
14 }
15
16
17
18 

trait的构造机制

 1 // 在Scala中,trait也是有构造代码的,也就是trait中的,不包含在任何方法中的代码2 // 而继承了trait的类的构造机制如下:1、父类的构造函数执行;2、trait的构造代码执行,多个trait从左到右依次执行;3、构造trait时会先构造父trait,如果多个trait继承同一个父trait,则父trait只会构造一次;4、所有trait构造完毕之后,子类的构造函数执行3 4 class Person { println("Person's constructor!") }5 trait Logger { println("Logger's constructor!") }6 trait MyLogger extends Logger { println("MyLogger's constructor!") }7 trait TimeLogger extends Logger { println("TimeLogger's constructor!") }8 class Student extends Person with MyLogger with TimeLogger {9   println("Student's constructor!")
10 }
11
12
13
14
15
16 

trait field的初始化

 1 // 在Scala中,trait是没有接收参数的构造函数的,这是trait与class的唯一区别,但是如果需求就是要trait能够对field进行初始化,该怎么办呢?只能使用Scala中非常特殊的一种高级特性——提前定义2 trait SayHello {3   val msg: String4   println(msg.toString)5 }6 7 class Person8 val p = new {9   val msg: String = "init"
10 } with Person with SayHello
11
12 class Person extends {
13   val msg: String = "init"
14 } with SayHello {}
15
16 // 另外一种方式就是使用lazy value
17 trait SayHello {
18   lazy val msg: String = null
19   println(msg.toString)
20 }
21 class Person extends SayHello {
22   override lazy val msg: String = "init"
23 }
24
25
26
27 

trait继承class

 1 // 在Scala中,trait也可以继承自class,此时这个class就会成为所有继承该trait的类的父类2 3 class MyUtil {4   def printMessage(msg: String) = println(msg)5 }6 7 trait Logger extends MyUtil {8   def log(msg: String) = printMessage("log: " + msg)9 }
10
11 class Person(val name: String) extends Logger {
12   def sayHello {
13     log("Hi, I'm " + name)
14     printMessage("Hi, I'm " + name)
15   }
16 }

转载于:https://www.cnblogs.com/cxhfuujust/p/9908949.html

scala学习笔记-面向对象编程之Trait相关推荐

  1. Spark基础-scala学习(三、Trait)

    面向对象编程之Trait trait基础知识 将trait作为接口使用 在trait中定义具体方法 在trait中定义具体字段 在trait中定义抽象字段 trait高级知识 为实例对象混入trait ...

  2. Scala 学习笔记

    Scala 学习笔记 1 object func_exp { 2 println("Welcome to the Scala worksheet") //> Welcome ...

  3. Scala学习笔记04:内建控制结构

    Scala学习笔记04:内建控制结构 scala提供的控制结构并不算多,因为在函数式编程中,可以自己开发出各种功能的控制结构,所以scala提供的原生控制结构仅仅够用为止. 1.if - 判断 if是 ...

  4. Scala学习笔记03:操作符

    Scala学习笔记03:操作符 一.scala中操作符与方法的等价性 scala中操作符即方法.方法即操作符.scala中操作符其实是普通方法调用的另一种表现形式,运算符的使用其实就是隐含地调用对应的 ...

  5. Scala学习笔记02:数据类型、常量与变量

    Scala学习笔记02:数据类型.常量与变量 一.数据类型 1.基本数据类型 Byte 字节型 Short 短整型 Int 整型 Long 长整型 Char 字符型 String 字符串 Float ...

  6. Scala学习笔记(三)

    Scala学习笔记(三) 一.模式匹配 1. 简单模式匹配 2. 匹配类型 3. 守卫 4. 匹配样例类 5. 匹配数组 6. 匹配列表 7. 匹配元组 8. 变量声明中的模式匹配 8.1 获取数组中 ...

  7. Scala学习笔记(一)

    Scala学习笔记(一) 一.Scala简介 二.Scala安装与配置 1. 安装JDK 2. 安装Scala SDK 3. 安装IDEA插件 三.Scala解释器 1. 启动Scala解释器 2. ...

  8. Scala学习笔记-环境搭建以及简单语法

    关于环境的搭建,去官网下载JDK8和Scala的IDE就可以了,Scala的IDE是基于Eclipse的. 下面直接上代码: 这是项目目录: A是scala写的: package first impo ...

  9. Scala学习笔记-方便查找使用 为Spark学习打基础

    Scala学习 注意 伊始 为什么是Scala 网课 环境 电脑环境安装 关于版本的声明 我的环境和版本 IDEA插件安装 IDEA关联Scala源码 基础部分1 文档注释和生成 字符串的三种输出 变 ...

最新文章

  1. 算法设计与分析课程的时间空间复杂度
  2. CentOS编译安装PHP 7.0
  3. python / 解决 pyinstaller 打包后运行时提示找不到模块的问题
  4. Springboot@PathVariable注解使用--请求路径占位符
  5. 2020年Deribit成交量达2110亿美元 同比增长82%
  6. C++之实现优先队列
  7. 从Python入门人工智能指南
  8. 《SAP快速入门》视频课程
  9. 倾斜摄影模型(.osgb)中心点位置的确定方法(SuperMap idesktop)
  10. cad批量打印快捷键_批量打印CAD图(无删减版)
  11. 面试官问:如何搭建测试环境?掌握这5种技能和知识就够了
  12. 每天学一个 Linux 命令(115):accton
  13. jbe 可以用来修改Java class的字节码,配合jd-gui 使用
  14. 神经系统疾病题库【1】
  15. 23-Travel旅游-签证
  16. 编译安装redis6.2.6
  17. 历史最全自然语言处理测评基准分享-数据集、基准(预训练)模型、语料库、排行榜
  18. dw在php图片滑动切换效果,超简单的图片左右切换滑动
  19. net mysql反斜杠怎么入库_MySQL中如何插入反斜杠,反斜杠被吃掉,反斜杠转义
  20. Nginx轮训tomcat服务器配置流程

热门文章

  1. python任务队列 http_基于Python开发的分布式任务队列:Celery
  2. html.partial mvc,MVC Html.Partial or Html.Action
  3. android sliding tab,android – 刷新SlidingTabLayout
  4. vs2012html图片,简单几步 实现vs2010对html5的支持
  5. 压缩文件夹_怎样压缩文件夹并发送
  6. mysql性能的介绍少_MySQL性能突然下降怎么回事 MySQL性能突然下降原因介绍
  7. 天体摇摆仪的工作原理
  8. 什么时候用redis_C++传参什么时候用引用, 什么时候用指针?
  9. 无法进入一个空框_win10电脑开机进入不了系统如何解决?
  10. django安装mysql_django+mysql安装和设置