天天看點

​第2課 Scala面向對象徹底精通及Spark源碼SparkContext,RDD閱讀總結

本期内容:

1 scala中的類、object實戰詳解

2 scala中的抽象類、接口實戰詳解

3 綜合案例及spark源碼解析

一:定義類

class hiscala{

private var name = "spark"

def sayname(){

println(name)

}

def getname = name

scala中,變量與類中的方法是同等級的,可以直接互相指派。與java不同的是類中的屬性必須初始化,例如name屬性不初始化,就會報錯。

scala中的get與set:

在scala中,如果程式中給變量或方法前面定義了private,那麼scala解釋器會給這個變量或方法自動生成private的get和set方 

法,如果程式中沒有給變量或方法前面定義了private,那麼scala會給這個變量或方法自動生成public的get和set方法。這樣可以直接在類的外部直接通路成員變量,但是運作上成員已經被scala私有,我們實際通路的是你們的set和get方法

建立類的對象 

val scal = new hiscala

scal.sayname()

scal.sayname//如果不傳參時,等同上面

scal.getname

var name="spark" //如果不加private,預設會生成一個public的get和set方法,外部可以調

private[this] 對類對象較深層次的通路控制,對象私有屬性,隻能目前對象通路,這個屬性是不能被類的其它對象通路的。如下:

person{

private[this]var name =”spark”

def sayname() {println(name)}

def sayhello(person1:person){

 println(“holle ” +person1.name )

}}

var person1 =new person()

var person2 =new person()

person1.sayhello(person2)    //這個scala時會報錯的,因為name屬性是對象私有的

類的構造器

注意:所有重載的構造器,都必須首先調用預設的構造器,或者說調用其它重載的構造器

類的構造器:重載

def this(name:string)

{

this() //調用預設的構造器

this.name=name

def this(name:string,age:int){

this(name) //調用其它重載的構造器

this.age=age

這裡的重載構造器,如果不調用預設構造器就會報錯,在類的構造時,除了方法以外,類的其它語句都會被執行,一般可以用于類的初始化。如果不想讓使用者使用預設構造器:如下

class person private(name: string){

var name:string="spart"

def this(name:string){

this.name=name}

伴生對象 object:

scala程式中,定義完類之後,一般會定義一個同名的object,它用于存放靜态的成員或者方法,當我們第一次調 

用這個伴生對象時,它會執行object的構造方法,隻是這個構造方法是不接受參數的,而且這個構造方法隻會調用一次,以後不會 

在調用。

如果有個類和object類名相同,則稱這個object類是同名類的伴生對象,同名類是該object類的伴生類;

定義:object person{

println("scala")

val salary=0.0

def getsalary=salary

伴生對象的apply方法:它就是目前類的對象的工廠方法,它可以控制對象的生成。大多數情況下,類是有其伴生對象的apply的方法實作的

scala不支援繼承多個抽象類,關鍵字extends,但是可以繼承多個接口,用with關鍵字

trait:工具方法的一個容器,通用功能都放這個裡面,相當于utils

sparkcontext類源碼解析:

 sparkcontex位于項目的源碼路徑\spark-master\core\src\main\scala\org\apache\spark\sparkcontext.scala中,源檔案包含sparkcontextclasss聲明和其伴生對象sparkcontextobject

  class sparkcontext extends了logging。logging是一個trait,它是用于存放工具方法的一個容器,trait封裝方法和字段。把trait混入到類中,就可以重用它們。一個類,可以繼承任意多個trait,多個trait繼承采用with來實作,可以将trait視為java的接口interface,跟interface非常相似。唯一的差别在于,interface聲明函數,但不實作它們,trait可以實作函數。

trait跟class的差别在于,trait沒有任何類參數,trait調用的方法是動态綁定的。

class sparkcontext類中有多個重載的構造方法:

如下:

def this(master: string, appname: string, conf: sparkconf) =

this(sparkcontext.updatedconf(conf, master, appname))

@deprecated("passing in preferred locations has no effect at all, see spark-10921", "1.6.0")

def this(

master: string,

appname: string,

sparkhome: string = null,

jars: seq[string] = nil,

environment: map[string, string] = map(),

preferrednodelocationdata: map[string, set[splitinfo]] = map()) =

this(sparkcontext.updatedconf(new sparkconf(), master, appname, sparkhome, jars, environment))

if (preferrednodelocationdata.nonempty) {

logwarning("passing in preferred locations has no effect at all, see spark-8949")

val starttime = system.currenttimemillis()

starttime沒有加上private,scala編譯時,starttime這個變量是私有的,但會自動的生成它的public的get和set方法,供外部對象調用。

private[spark] val stopped: atomicboolean = new atomicboolean(false)

private[class_name] 指定可以通路該字段的類,通路的級别較嚴,在編譯時,會自動的生成get和set方法,class_name必須是目前定義的類或類的外部類。

private def assertnotstopped(): unit = {}

這個方法它是一個過程,因為傳回值是unit,沒有結果傳回。

rdd類源碼解析:

class rdd它是個抽象類,

private[spark] def conf = sc.conf

class rdd類中有很多加了final修飾符的方法,表示:此方法或屬性,子類繼承此類時不可被覆寫,如下:

final def dependencies: seq[dependency[_]] = {

checkpointrdd.map(r => list(new onetoonedependency(r))).getorelse {

if (dependencies_ == null) {

dependencies_ = getdependencies

dependencies_

final def partitions: array[partition] = {

checkpointrdd.map(_.partitions).getorelse {

if (partitions_ == null) {

partitions_ = getpartitions

partitions_

final def getnumpartitions: int = partitions.length