一、Trait基础

1、将trait作为接口使用

// Scala中的Triat是一种特殊的概念
// 首先我们可以将Trait作为接口来使用,此时的Triat就与Java中的接口非常类似
// 在triat中可以定义抽象方法,就与抽象类中的抽象方法一样,只要不给出方法的具体实现即可
// 类可以使用extends关键字继承trait,注意,这里不是implement,而是extends,在scala中没有implement的概念,无论继承类还是trait,统一都是extends
// 类继承trait后,必须实现其中的抽象方法,实现时不需要使用override关键字
// scala不支持对类进行多继承,但是支持多重继承trait,使用with关键字即可 ###
scala> :paste
// Entering paste mode (ctrl-D to finish) trait SayHello {
def sayHello(name: String)
} trait MakeFriends {
def makeFriends(p: Person)
} class Person(val name: String) extends SayHello with MakeFriends {
def sayHello(otherName: String) = println("Hello, " + otherName + ", I'm " + name)
def makeFriends(p: Person) = println("Hello " + p.name + ", I'm " + name + ", I want to make friends with you.")
} // Exiting paste mode, now interpreting. defined trait SayHello
defined trait MakeFriends
defined class Person scala> val p = new Person("leo")
p: Person = Person@223f3642 scala> val p2 = new Person("jack")
p2: Person = Person@48fa0f47 scala> p.sayHello("jack")
Hello, jack, I'm leo scala> p.makeFriends(p2)
Hello jack, I'm leo, I want to make friends with you.

2、在Trait中定义具体方法

// Scala中的Triat可以不是只定义抽象方法,还可以定义具体方法,此时trait更像是包含了通用工具方法的东西// 有一个专有的名词来形容这种情况,
就是说trait的功能混入了类
// 举例来说,trait中可以包含一些很多类都通用的功能方法,比如打印日志等等,spark中就使用了trait来定义了通用的日志打印方法 ###
scala> :paste
// Entering paste mode (ctrl-D to finish) trait Logger {
def log(msg: String) = println("log: " + msg)
} class Person(val name: String) extends Logger {
def sayHello {
println("Hello, I'm " + name); log("sayHello is invoked")
}
} // Exiting paste mode, now interpreting. defined trait Logger
defined class Person scala> val p = new Person("leo")
p: Person = Person@2898ac89 scala> p.sayHello
Hello, I'm leo
log: sayHello is invoked

3、在Trait中定义具体字段

// Scala中的Triat可以定义具体field,此时继承trait的类就自动获得了trait中定义的field
// 但是这种获取field的方式与继承class是不同的:如果是继承class获取的field,实际是定义在父类中的;而继承trait获取的field,就直接被添加到了类中 ###
scala> :paste
// Entering paste mode (ctrl-D to finish) trait Person {
val eyeNum: Int = 2
} class Student(val name: String) extends Person {
def sayHello = println("Hi, I'm " + name + ", I have " + eyeNum + "eyes.")
} // Exiting paste mode, now interpreting. defined trait Person
defined class Student scala> val s = new Student("leo")
s: Student = Student@4b0d79fc scala> s.sayHello
Hi, I'm leo, I have 2eyes.

4、在Trait中定义抽象字段

// Scala中的Triat可以定义抽象field,而trait中的具体方法则可以基于抽象field来编写
// 但是继承trait的类,则必须覆盖抽象field,提供具体的值 ###
scala> :paste
// Entering paste mode (ctrl-D to finish) trait SayHello {
val msg: String
def 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 friend with you.")
}
} // Exiting paste mode, now interpreting. defined trait SayHello
defined class Person scala> val p1 = new Person("leo")
p1: Person = Person@62656be4 scala> val p2 = new Person("jack")
p2: Person = Person@56dc1551 scala> p1.makeFriends(p2)
hello, jack
I;m leo, I want to make friend with you.

二、trait高级

1、为实例混入trait

// 有时我们可以在创建类的对象时,指定该对象混入某个trait,这样,就只有这个对象混入该trait的方法,而类的其他对象则没有

###
scala> :paste
// Entering paste mode (ctrl-D to finish) trait Logged {
def log(msg: String) {}
} trait MyLogger extends Logged {
override def log(msg: String) {println("log: " + msg)}
} class Person(val name: String) extends Logged {
def sayHello {println("Hi, I'm " + name); log("sayHello is invoked!")}
} // Exiting paste mode, now interpreting. defined trait Logged
defined trait MyLogger
defined class Person scala> val p1 = new Person("leo")
p1: Person = Person@35d08e6c scala> p1.sayHello
Hi, I'm leo scala> val p2 = new Person("jack") with MyLogger
p2: Person with MyLogger = $anon$1@1bb564e2 scala> p2.sayHello
Hi, I'm jack
log: sayHello is invoked!

2、trait调用链

// Scala中支持让类继承多个trait后,依次调用多个trait中的同一个方法,只要让多个trait的同一个方法中,在最后都执行super.方法即可
// 类中调用多个trait中都有的这个方法时,首先会从最右边的trait的方法开始执行,然后依次往左执行,形成一个调用链条
// 这种特性非常强大,其实就相当于设计模式中的责任链模式的一种具体实现 ###
scala> :paste
// Entering paste mode (ctrl-D to finish) trait Handler {
def handle(data: String) {}
} trait DataVailHandler extends Handler {
override def handle(data: String) {
println("check data: " + data)
super.handle(data)
}
} trait SignatureVaildHandler extends Handler {
override def handle(data: String) {
println("check signature: " + data)
}
} class Person(val name: String) extends SignatureVaildHandler with DataVailHandler {
def sayHello = {println("Hello," + name); handle(name)}
} // Exiting paste mode, now interpreting. defined trait Handler
defined trait DataVailHandler
defined trait SignatureVaildHandler
defined class Person scala> val p = new Person("leo")
p: Person = Person@545de5a4 scala> p.sayHello
Hello,leo
check data: leo
check signature: leo

3、在trait中覆盖抽象方法

// 在trait中,是可以覆盖父trait的抽象方法的
// 但是覆盖时,如果使用了super.方法的代码,则无法通过编译。因为super.方法就会去掉用父trait的抽象方法,此时子trait的该方法还是会被认为是抽象的
// 此时如果要通过编译,就得给子trait的方法加上abstract override修饰 ###
scala> :paste
// Entering paste mode (ctrl-D to finish) trait Logger {
def log(msg: String)
} trait Mylogger extends Logger {
abstract override def log(msg: String) {super.log(msg)}
} // Exiting paste mode, now interpreting. defined trait Logger
defined trait Mylogger

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

// 在trait中,可以混合使用具体方法和抽象方法
// 可以让具体方法依赖于抽象方法,而抽象方法则放到继承trait的类中去实现
// 这种trait其实就是设计模式中的模板设计模式的体现 ###
scala> :paste
// Entering paste mode (ctrl-D to finish) trait Valid {
def getName: String
def valid: Boolean = {
getName == "leo"
}
} class Person(val name: String) extends Valid {
println(valid)
def getName = name
} // Exiting paste mode, now interpreting. defined trait Valid
defined class Person scala> val p = new Person("leo")
true
p: Person = Person@3f093abe

5、trait的构造机制

// 在Scala中,trait也是有构造代码的,也就是trait中的,不包含在任何方法中的代码
// 而继承了trait的类的构造机制如下:1、父类的构造函数执行;2、trait的构造代码执行,多个trait从左到右依次执行;
3、构造trait时会先构造父trait,如果多个trait继承同一个父trait,则父trait只会构造一次;4、所有trait构造完毕之后,子类的构造函数执行 ###
scala> :paste
// Entering paste mode (ctrl-D to finish) class Person {
println("Persons's constructor!")
} trait Logger {
println("Logger's constructor!")
} trait MyLogger extends Logger {
println("MyLogger's constructor!")
} trait TimeLogger extends Logger {
println("TimeLogger's constructor!")
} class Student extends Person with MyLogger with TimeLogger {
println("Student's constructor!")
} // Exiting paste mode, now interpreting. defined class Person
defined trait Logger
defined trait MyLogger
defined trait TimeLogger
defined class Student scala> val s = new Student
Persons's constructor!
Logger's constructor!
MyLogger's constructor!
TimeLogger's constructor!
Student's constructor!
s: Student = Student@158d255c

6、trait field的初始化

// 在Scala中,trait是没有接收参数的构造函数的,这是trait与class的唯一区别,但是如果需求就是要trait能够对field进行初始化,该怎么办呢?
只能使用Scala中非常特殊的一种高级特性 - 提前定义 ###
scala> trait sayHello {
| val msg: String
| println(msg.toString)
| }
defined trait sayHello scala> class Person
defined class Person scala> val p = new {
| val msg: String = "init"
| } with Person with sayHello
init
p: Person with sayHello = $anon$1@1af7f54a

7、trait继承class

// 在Scala中,trait也可以继承自class,此时这个class就会成为所有继承该trait的类的父类

###
scala> :paste
// Entering paste mode (ctrl-D to finish) class MyUtil {
def printMessage(msg: String) = println(msg)
} trait Logger extends MyUtil {
def log(msg: String) = printMessage("log: " + msg)
} class Person(val name: String) extends Logger {
def sayHello {
log("Hi, I'm " + name)
printMessage("Hi, I'm" + name)
}
} // Exiting paste mode, now interpreting. defined class MyUtil
defined trait Logger
defined class Person scala> val p = new Person("leo")
p: Person = Person@6650813a scala> p.sayHello
log: Hi, I'm leo
Hi, I'mleo

8、scala面向对象编程之Trait的更多相关文章

  1. 10、scala面向对象编程之Trait

    1.  将trait作为接口使用 2.trait中定义具体方法 3.trait定义具体字段 4.trait中定义抽象字段 5.为实例对象混入trait 6.trait调用链 7.在trait中覆盖抽象 ...

  2. Scala 面向对象编程之Trait

    将trait作为接口使用 // Scala中的Triat是一种特殊的概念 // 首先我们可以将Trait作为接口来使用,此时的Triat就与Java中的接口非常类似 // 在triat中可以定义抽象方 ...

  3. Scala编程入门---面向对象编程之Trait高级知识

    trait调用链 Scala中支持让类继承多个Trait后,依次调用多个Trait中的同一个方法,只要让多个trait的同一个方法中,在最后都执行super.方法即可 类中调用多个trait中都有这个 ...

  4. scala学习笔记-面向对象编程之Trait

    将trait作为接口使用 1 // Scala中的Triat是一种特殊的概念 2 // 首先我们可以将Trait作为接口来使用,此时的Triat就与Java中的接口非常类似 3 // 在triat中可 ...

  5. Scala编程入门---面向对象编程之Trait

    Scala中Trait是一种特殊概念 首先我们可以将Triat做为接口来使用,此时的Triat就与java中的接口非常相似 在Triat中可以定义抽象方法,就与抽象类中的抽象方法一样,只要不给出具体的 ...

  6. 8、scala面向对象编程之对象

    1.  Object 2.伴生对象 3.让object继承抽象类 4.apply方法 5.main方法 6.用object实现枚举功能 1.  Object Object,相当于class的单个实例, ...

  7. Scala 面向对象编程之对象

    此对象非彼java bean对象 是scala object的对象 Object // object,相当于class的单个实例,通常在里面放一些静态的field或者method // 第一次调用ob ...

  8. 9、scala面向对象编程之继承

    1.  extends 2.override 和super 3.override field 4.isInstanceOf和asInstanceOf 5.getClass和classOf 6.使用模式 ...

  9. Scala 面向对象编程之继承

    extends关键字 // Scala中,让子类继承父类,与Java一样,也是使用extends关键字 // 继承就代表,子类可以从父类继承父类的field和method:然后子类可以在自己内部放入父 ...

随机推荐

  1. 【Flask】filter 常用查询条件

    1. equal    2. not equal  3. like, ilike  4.in  5. not in 6. is null  7. is not null  8. and  9. or ...

  2. Android系统定制之SystemUI修改:下拉通知栏尺寸【转】

    本文转载自:https://blog.csdn.net/huil0925/article/details/67632358 最近项目需要修改下拉通知栏面板的宽度,完成后,写个Blog做个总结,也提供给 ...

  3. 剑指offer之 整数中1出现的次数

    public class Solution { public int NumberOf1Between1AndN_Solution(int n) { int count=0; for(int i=1; ...

  4. 是否可以重定向到 WEB-INFO 下的页面?

    redirect的路径一定不能在WEB-INF路径下,因为redirect是相当于用户直接访问了路径,而用户不能访问WEB-INF目录下的文件,只有程序内部转发的时候才能转发到WEB-INF下的JSP ...

  5. Hibernate映射--基本类映射和对象关系映射(转)

    原文地址:http://blog.csdn.net/lovesummerforever/article/details/20901011   尊重原创,请访问原网址 回想一些我们在没有学习ssh的时候 ...

  6. codeforces 86D D. Powerful array(莫队算法)

    题目链接: D. Powerful array time limit per test 5 seconds memory limit per test 256 megabytes input stan ...

  7. hdu-5584 LCM Walk(数论)

    题目链接:LCM Walk Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others)To ...

  8. RTP Payload Format for Opus Speech and Audio Codec

    [Docs] [txt|pdf] [Tracker] [WG] [Email] [Diff1] [Diff2] [Nits] Versions: (draft-spittka-payload-rtp- ...

  9. 【队列】最大值减去最小值小于等于num的子数组数量

    摘自<程序员代码面试指南> 题目: 给定数组 arr 和整数 num, 共返回有多少个⼦数组满⾜如下情况:max(arr[i...j]) - min(arr[i...j]) <= n ...

  10. 洛谷【P1175】表达式的转换

    浅谈栈:https://www.cnblogs.com/AKMer/p/10278222.html 题目传送门:https://www.luogu.org/problemnew/show/P1175 ...