Scala入门之面向接口编程

来源:互联网 发布:celtx剧本写作软件 编辑:程序博客网 时间:2024/06/06 03:58

##一、scala中trait的定义
这里的trait字面意思是特质或者特征,这个词翻译成特征比较合适。它的意义和java,c#中接口很类似。但是trait支持部分实现,也就是说可以在scala的trait中可以实现部分方法。
##二、scala中trait的使用
一个类继承不管继承的是抽象类还是接口,都是用extends关键字,而对于多继承时用的是with关键字连接起来,其实背后是这样读的:
extends (类或接口with接口with接口with接口with接口with接口with接口with接口with接口….)
它是把后面做为一个整体来看。
抽象属性可以不赋值,但是得写类型,scala是一门静态语言,如 val name: String
//声明一个 trait
trait TraitBase{
def add(x:Int,y:Int): Int ={
return x+y
}
}
//TraitTest 继承自 TraitBase
class TraitTest extends TraitBase{
//重写父类的方法
override def add(x:Int,y:Int): Int ={
return x+y*10
}
}

//如果需要调用父类的方法,使用super访问父类
class TraitTest extends TraitBase{
override def add(x:Int,y:Int): Int ={
return super.add(x,y)*10
}
}

//使用
val test = new TraitTest
println(test.add(4,5))

//对于多重继承,使用 with 关键字
trait A{
def FA(): Unit ={
println(“FA”)
}
}
trait B{
def FB(): Unit ={
println(“FB”)
}
}
class C{
val content=null
}
//多重继承
class D extends C with A with B{
//这里不需要必须实现trait中的方法,因为已经实现了
}

*//混入:混入trait的数量可以是任意的。用关键字with可以混入更多的trait。如果类已经继承了类,就可以
//使用with混入trait。*
trait Friend {
val name: String
def listen() = println(“You frient ” + name + ” is listening”)
}

class Animal
class Dog(val name: String) extends Animal with Friend{
}
//还可以在实例一级进行混入,这样的话就可以把特定的类的实例当做trait
class Cat(val name: String) extends Animal
val scat = new Cat(“cat”) with Friend
//这样scat就是Friend了
##三、背后实现
对于不存在具体实现的方法及字段的trait,它最终生成的字节码文件反编译后是等同于java中的接口,而对于存在具体实现方法及字段的trait,其字节码文件反编译后得到的java中的抽象类.所以可以理解为trait就是抽象类与interface的结合体。
##四、scala中trait与接口,抽象类的区别:
trait中可以写方法的实现,interface不可以(java8开始支持接口中允许写方法实现代码了),这样看起来trait又很像抽象类(abstract)。
trait很强大,抽象类能做的事情,trait都可以做。它的长处在于可以多继承。trait和抽象类的区别在于抽象类是对一个继承链的,类和类之前确实有父子类的继承关系,而trait则如其名字,表示一种特征,可以多继承。
##五、DTSpark课堂讲解内容
a.trait中的方法都实现了的话一般情况下那就相当于一个工具方法的集合。
b.继承类或者接口开始都是用extends关键字,多继承时用with(scala继承语法结构第一个必需是extends)
c.scala中的接口支持多种继承,但是类还有抽象类不支持多种继承。(即父类只能有一个)
d.scala中的类的实例对象也可以混入接口,以扩展当前对象的实例的功能
e.继承多重接口时,实现的顺序是从右到左,如果 trait里都有一个方法,那就会从右到左形成一个调用链条
=============================代码=========================================
package com.dt.spark.scala.bascis

trait Logger{
def log(message:String){
println(“Logger: “+ message)
}
}

trait aLogger extends Logger{
println(“a Logger: ” )
override def log(message:String){
println(“a Logger: “+ message)
}
}

trait bLogger extends Logger{
println(“b Logger: ” )
override def log(message:String){
println(“b Logger: “+ message)
}
}

trait cLogger extends Logger{
println(“c Logger: ” )
override def log(message:String){
println(“c Logger: “+ message)
}
}

trait dLogger extends Logger{
println(“d Logger: ” )
override def log(message:String){
println(“d Logger: “+ message)
}
}

trait eLogger extends Logger{
println(“e Logger: ” )
override def log(message:String){
println(“e Logger: “+ message)
}
}

trait RichLogger extends Logger{
override def log(message:String){
println(“RichLogger: “+ message)
}
}

//具体方法依赖于抽象方法
trait information{
def getInformation:String
def checkIn:Boolean={
getInformation.equals(“Spark”)
}
println (“getInformation.equals Spark ” +checkIn)
}

class Passenger (val name: String){
def getInformation=name
println(“getInformation: ” +getInformation )
}

class Loggin (val name:String) extends Logger{
def loggin{
println(“Loggin name: “+ name)
log(name)
}

}

object HelloTrait {
def main(args: Array[String]): Unit = {

new Loggin("DTspark").loggin

//在此展示的是上面说的d点,scala中的类的实例对象也可以混入接口,以扩展当前对象的实例的功能
val personLoggin = new Loggin(“Hello scala”) with RichLogger
//RichLogger 继承了Logger,重写了log方法,所以调用的时候输出的是RichLogger 的方法内容。而这就是扩展功能,
//这在本来有默认方法,而某些时候并不是都需要默认的,这时用混入特质的方式可以在不改变原有默认
//的情况下达到要示
personLoggin.loggin
val abcdeLoggin = new Loggin(“abcde”) with aLogger with bLogger with cLogger with dLogger with eLogger
abcdeLoggin.loggin

*new Passenger("Spark").getInformationval passenger= new Passenger("Sparkjava") with informationpassenger.checkIn*

}
}

=============================代码=========================================

运行结果

Loggin name: DTspark
Logger: DTspark
Loggin name: Hello scala
RichLogger: Hello scala
a Logger:
b Logger:
c Logger:
d Logger:
e Logger:
Loggin name: abcde
e Logger: abcde
getInformation: Spark
getInformation: Sparkjava
getInformation.equals Spark false

========================================================================
##六、Spark源码
看了一下SparkContext源码,它继承了两个trait:logging和ExecutorAllocationClient ,trait里trait:logging实现了,而ExecutorAllocationClient 没实现。
trait Logging {
// Make the log field transient so that objects with Logging can
// be serialized and used on another machine
@transient private var log_ : Logger = null
protected def logDebug(msg: => String) {
if (log.isDebugEnabled) log.debug(msg)
}
protected def logTrace(msg: => String) {
if (log.isTraceEnabled) log.trace(msg)
}

private[spark] trait ExecutorAllocationClient {
/**
* Request an additional number of executors from the cluster manager.
* @return whether the request is acknowledged by the cluster manager.
*/
def requestExecutors(numAdditionalExecutors: Int): Boolean

/**
* Request that the cluster manager kill the specified executors.
* @return whether the request is acknowledged by the cluster manager.
*/
def killExecutors(executorIds: Seq[String]): Boolean

class SparkContext(config: SparkConf) extends Logging with ExecutorAllocationClient
..

以上内容部分来自[DT大数据梦工厂]首席专家Spark专家王家林老师的课程分享。感谢王老师的分享,更多精彩内容请扫描关注[DT大数据梦工厂]微信公众号DT_Spark

0 0