Spark基础-scala学习(三)

面向对象编程之Trait

trait基础知识

  1. 将trait作为接口使用
  2. 在trait中定义具体方法
  3. 在trait中定义具体字段
  4. 在trait中定义抽象字段

trait高级知识

  1. 为实例对象混入trait
  2. trait调用链
  3. 在trait中覆盖抽象方法
  4. 混合使用trait的具体方法和抽象方法
  5. trait的构造机制
  6. trati字段的初始化
  7. 让trait继承类

将trait作为接口使用

  1. trait作为接口,和java中的接口非常类似
  2. 在triat中可以定义抽象方法,就与抽象类中的抽象方法一样,只要不给出方法的具体实现即可
  3. 类可以使用extends关键字继承trait,注意,这里不是implement,而是extends,在scala中没有implement的概念,无论继承类还是trait,统一都是extends
  4. 类继承trait后,必须实现其中的抽象方法,实现时不需要使用override关键字
  5. scala不支持对类进行多继承,而是支持多重继承trait,使用with关键字即可
scala> :paste
// Entering paste mode (ctrl-D to finish)

trait HelloTrait{
 def sayHello(name:String)
}
trait MakeFriendsTrait{
 def makeFriend(p:Person)
}
class Person(val name:String) extends HelloTrait with MakeFriendsTrait with Cloneable with Serializable
{
 def sayHello(name:String) = println("Hello," + name)
 def makeFriend(p:Person) = println("Hello,my name is "+name +",your name is "+p.name)
}

// Exiting paste mode, now interpreting.

defined trait HelloTrait
defined trait MakeFriendsTrait
defined class Person

scala> val p = new Person("Tom")
p: Person = [email protected]

scala> p.makeFriend(p)
Hello,my name is Tom,your name is Tom

scala> p.sayHello("jike")
Hello,jike

在Trait中定义具体的方法

  1. scala中的Triat可以不是只定义抽象方法,还可以定义具体方法,此时trait更像是包含了通用工具方法的东西
  2. 就想trait的功能混入了类
  3. 举例来说,trait中可以包含一些很多类都通用的功能方法,比如打印日志等等,spark中就使用了trait来定义了通用的日志打印方法
scala> :paste
// Entering paste mode (ctrl-D to finish)

trait Logger{
 def log(message :String) = println(message)
}
class Person(val name:String) extends Logger{
 def makeFriends(p:Person){
  println("Hi,I‘m "+name+",I‘m glad to make friends with you," + p.name)
  log("makeFriends method is invoked with parameter Person[name="+p.name+"]")
 }
}

// Exiting paste mode, now interpreting.

defined trait Logger
defined class Person

scala> val p = new Person("Tom")
p: Person = [email protected]

scala> p.makeFriends(p)
Hi,I‘m Tom,I‘m glad to make friends with you,Tom
makeFriends method is invoked with parameter Person[name=Tom]

在trait中定义具体字段

  1. scala中trait可以定义具体field,此时继承trait的类就可以自动获得trait中定义的field
  2. 但是这种获取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("Tom")
s: Student = [email protected]

scala> s.sayHello
Hi,I‘m Tom,I have 2 eyes

在Trait中定义抽象字段

  1. scala中的Trait可以定义抽象field,而trait中的具体方法则可以基于抽象field来编写
  2. 但是继承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)
  print("I‘m "+name+",I want to make friends with you!")
 }
}

// Exiting paste mode, now interpreting.

defined trait SayHello
defined class Person

scala> val p = new Person("Tom")
p: Person = [email protected]

scala> p.msg
res4: String = hello

scala> p.makeFriends(p)
hello,Tom
I‘m Tom,I want to make friends with you!

为实例混入trait

  1. 有时候我们可以在创建类的对象时,指定该对象混入某个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 = [email protected]

scala> p1.sayHello
Hi,I‘m leo

scala> val p2 = new Person("jack") with MyLogger
p2: Person with MyLogger = [email protected]

scala> p2.sayHello
Hi,I‘m jack
log:sayHello is invoked!

trait调用链

  1. scala中支持多个trait,一次调用多个trait中的同一个方法,只要让多个trait的同一个方法中,在最后都执行super.方法即可
scala> :paste
// Entering paste mode (ctrl-D to finish)

trait Handler{
 def handle(data:String){}
}
trait DataValidHandler extends Handler{
 override def handle(data:String){
  println("check data:" +data)
  super.handle(data)
 }
}
trait SignatureValidHandler extends Handler {
 override def handle(data:String){
  println("check signature: "+data)
  super.handle(data)
 }
}
class Person(val name:String) extends SignatureValidHandler with DataValidHandler{
 def sayHello = { println("Hello, " + name);handle(name)}
}

// Exiting paste mode, now interpreting.

defined trait Handler
defined trait DataValidHandler
defined trait SignatureValidHandler
defined class Person

scala> val p1 = new Person("Tom")
p1: Person = [email protected]

scala> p1.sayHello
Hello, Tom
check data:Tom
check signature: Tom

在trait中覆盖抽象方法

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

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

  1. 在trait中,可以混合使用具体方法和抽象方法
  2. 可以让具体方法依赖于抽象方法,而抽象方法则放到继承trait的类中去实现
  3. 这种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 = [email protected]

scala> p.getName
res10: String = leo

scala> val p2 = new Person("Tom")
false
p2: Person = [email protected]

scala> p2.getName
res11: String = Tom

trait的构造机制

  1. 在scala中,trait也是有构造代码的,也就是trait中,不包含在任何方法中的代码
  2. 而继承了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("Person constructor")}
trait Logger{println("Logger constructor")}
trait MyLogger extends Logger{println("MyLogger constructor")}
trait TimeLogger extends Logger{println("TimeLogger constructor")}
class Student extends Person with MyLogger with TimeLogger{
 println("Student 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
Person constructor
Logger constructor
MyLogger constructor
TimeLogger constructor
Student constructor
s: Student = [email protected]

trait field的初始化

  1. 在scala中,trait是没有接受参数的构造函数的,这是trait与clas的唯一区别,但是如果需求就是要trait能够对field进行初始化,我们可以使用scala中非常特殊的一种高级特性--提前定义
scala> :paste
// Entering paste mode (ctrl-D to finish)

trait SayHello{
 val msg:String
 println(msg:String)
}
class Person
val p = new {
 val msg:String = "init"
} with Person with SayHello

// Exiting paste mode, now interpreting.

init
defined trait SayHello
defined class Person
p: Person with SayHello = [email protected]
scala> :paste
// Entering paste mode (ctrl-D to finish)

class Person extends{
 val msg:String = "init"
} with SayHello{}

// Exiting paste mode, now interpreting.

defined class Person

scala> val p2 = new Person
init
p2: Person = [email protected]
scala> :paste
// Entering paste mode (ctrl-D to finish)

trait SayHello{
 lazy val msg:String = null
 println(msg.toString)
}
class Person extends SayHello{
 override lazy val msg:String = "init"
}

// Exiting paste mode, now interpreting.

defined trait SayHello
defined class Person

scala> val p3 = new Person
init
p3: Person = [email protected]

trait继承class

  1. 在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("Jike")
p: Person = [email protected]

scala> p.sayHello
log: Hi,I‘m Jike
Hi,I‘m Jike

原文地址:https://www.cnblogs.com/sky-chen/p/10099716.html

时间: 2024-10-14 09:04:50

Spark基础-scala学习(三)的相关文章

Spark基础-scala学习(一)

Scala解析器的使用 REPL:Read(取值)-> Evaluation(求值)-> Print(打印)->Loop(循环).scala解析器也被称为REPL,会快速编译scala代码为字节码,然后交给JVM执行 val result = 1 设置变量不可变 var result = 2 可变的变量 val name: String = null 声明变量类型 val name: Any = "leo" val name1,name2:String = null

Spark基础-scala学习(四)

函数式编程 将函数赋值给变量 匿名函数 高阶函数 高级函数的类型推断 scala的常用高阶函数 闭包 sam转换 currying函数 return 将函数赋值给变量 scala中的函数是一等公民,可以独立定义,独立存在,而且可以直接将函数作为值赋值给变量 scala> def sayHello(name:String){println("Hello, "+name)} sayHello: (name: String)Unit scala> sayHello("t

Spark基础-scala学习(五、集合)

集合 scala的集合体系结构 List LinkedList Set 集合的函数式编程 函数式编程综合案例:统计多个文本内的单词总数 scala的集合体系结构 scala中的集合体系主要包括:Iterable.Seq.Set.Map.其中Iterable是所有集合trait的根trait.这个结构与java的集合体系非常相似 scala中的集合是分成可变和不可变两类集合的,其中可变集合就是说,集合的元素可以动态修改,而不可变集合的元素在初始化之后,就无法修改了.分别对应scala.collec

Spark基础-scala学习(七、类型参数)

类型参数是什么 类似于java泛型,泛型类 泛型函数 上边界Bounds 下边界 View Bounds Context Bounds Manifest Context Bounds 协变和逆变 Existential Type 泛型类 scala> :paste // Entering paste mode (ctrl-D to finish) class Student[T](val localId:T){ def getSchoolId(hukouId:T) = "S-"+

Spark之Scala学习

1. Scala集合学习: http://blog.csdn.net/lyrebing/article/details/20362227 2. scala实现kmeans算法 http://www.thinksaas.cn/group/topic/93852/ 3. Spark之Scala学习网站 http://spark.apache.org/docs/latest/mllib-decision-tree.html 4. Spark wordcount开发并提交到集群运行: http://ww

scala学习三---文件里读取文本行

学习了scala的基本知识后,发现了scala是集函数式和指令式结合为一体的一种语言,代码更加简洁,但是对于用习惯了java的人来说,还真的不是一件易事~~ 今天学习scala脚本读取文本文件 列子如下: import scala.io.Source if(args.length>0){ for(line <- Source.fromFile(args(0)).getLines) print(line.length+" "+line) }else{ Console.err.

Scala学习(三)----数组相关操作

数组相关操作 摘要: 本篇主要学习如何在Scala中操作数组.Java和C++程序员通常会选用数组或近似的结构(比如数组列表或向量)来收集一组元素.在Scala中,我们的选择更多,不过现在我们先假定不关心其他选择,而只是想马上开始用数组.本篇的要点包括: 1. 若长度固定则使用Array,若长度可能有变化则使用ArrayBuffer 2. 提供初始值时不要使用new 3. 用()来访问元素 4. 用for (elem<-arr)来遍历元素 5. 用for (elem<-arr if…)…yie

Scala学习(三)练习

Scala数组相关操作&练习 1. 1. 编写一段代码,将a设置为一个包含n个随机整数的数组,要求随机数介于0(包含)和n(不包含)之间 def main (args: Array[String]) { createArr(10).foreach(println)}def createArr(n:Int):Array[Int]={ val arr=new Array[Int](n) val rand=new Random() for(ele <- arr) yield rand.nextIn

【Scala学习之一】 Scala基础语法

环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark-1.6 Scala是一种混合功能编程语言,类似java,运行于JVM,集成面向对象编程和函数式编程的各种特性.(1)Scala可以与Java互操作:它用scalac这个编译器把源文件编译成Java的class文件,从Scala中调用所有的Java类库,也同样可以从Java应用程序中调用Scala的