Scala面向物件徹底精通及Spark原始碼閱讀?

Scala面向物件徹底精通及Spark原始碼閱讀

方法/步驟

一、Scala中的類實戰詳解類

跟Java一樣,Scala也是用關鍵字class來定義類。示例如下:

scala> class HiScala{

private var name = "Spark"

def sayName(){println(name)}

def getName = name

}

defined class HiScala

以上程式碼,定義了一個名稱為HiScala的類,預設情況下是public級別,所以public關鍵字可以不寫。

ü 定義了一個屬性name,為可變變數,訪問級別為private,在類的外面不能被訪問!

ü 定義一個函式:sayName

ü 定義一個函式:getName

在Scala中,變數與類中的方法是同等級的,可以直接相互賦值。

二、建立類例項

scala> val scal = new HiScala

scal: HiScala = [email protected]

//此時,scal就是HiScala類的一個例項。但是,在Scala中我們一邊不會用new來建立類的例項,而是用apply工廠方法模式來建立。

//呼叫scal的sayName方法,用於打印出name成員的值。

scala> scal.sayName()

Spark

//由於sayName沒有傳引數,所以可以把括號去掉,這樣更簡潔。

scala> scal.sayName

Spark

//呼叫getName方法,訪問name成員的值

scala> scal.getName

res2: String = Spark

//此時確實返回了name的值。

//該示例中name是私有的,所以不能直接訪問scal例項的name,如下訪問就出錯了。

scala> scal.name

:10: error: variable name inclass HiScala cannot be accessed in HiScala

scal.name

^

三、get與set

Scala的get和set跟Java的get和set有很大的差異。在Scala中,如果給變數前定義了private,那麼Scala直譯器會給這個變數自動生成private的get和set方 法;如果變數前沒有定義了private,那麼直譯器會給這個變數自動生成public的get和set方法,這樣就可以直接訪問該類的例項物件的成員變數,實際訪問的是它的set和get方法。

//我們重新改造上面的類,把屬性name前面的private訪問級別去掉。

scala> class HiScala{

var name ="Spark" //去掉了private關鍵字

defsayName(){println(name)}

def getName = name

}

defined class HiScala

scala> val scal = new HiScala

scal: HiScala = [email protected]

//訪問name屬性, 值為Spark

scala> scal.name

res4: String = Spark

//此時雖然是訪問屬性name,但其實不是直接訪問var指定的變數name,而是Scala直譯器自動給name生成public級別的get和set方法。

//修改name屬性

scala> scal.name="Scala"

scal.name: String = Scala

//再次訪問name屬性, 值已經變為Scala

scala> scal.name

res5: String = Scala

四、自定義的get和set

scala> class Person {

private var myName ="Flink"

def name = this.myName //自定義get方法

def name_=(newName : String){ //自定義set方法,注意下劃線和等號之間沒有空格!

myName = newName

println("Hi " + myName)

}

}

defined class Person

// luck為Person 類的例項

scala> val luck = new Person

luck: Person = [email protected]

//通過自定義的get方法,訪問到了myName屬性

scala> luck.name

res0: String = Flink

//呼叫自定義的set方法,修改了myName屬性

scala> luck.name = "Spark"

Hi Spark

luck.name: String = Spark

//再次訪問myName屬性,發現屬性值已經變成Spark

scala> luck.name

res2: String = Spark

//修改上面的示例,僅僅暴露屬性的get方法,沒有為其複寫set方法。但是提供一個名為update的方法用來修改該屬性的值。

scala> class Person {

private var myName ="Flink"

def name = this.myName //get方法

def update(newName :String){

myName = newName

println("Hi "+ myName)

}

}

defined class Person

// luck為Person 類的例項

scala> val luck = new Person

luck: Person = [email protected]

//通過自定義的get方法,訪問myName屬性值,初始值為Flink

scala> luck.name

res4: String = Flink

//想直接通過set方法來修改myName,會提示出錯,因為沒有複寫set方法。

scala> luck.name="Hadoop"

:9: error: value name_= is not a member of Person

luck.name="Hadoop"

^

//通過額外提供的update方法來修改屬性

scala> luck.update("Hadoop")

Hi Hadoop

//再次檢視myName屬性值,發現已經變成了Hadoop

scala> luck.name

res6: String = Hadoop

四、private[this]

private[this]至關重要的,在Spark原始碼中隨處可見。代表屬性或方法為物件私有!在類私有的基礎上更強一層的控制。

//定義一個類:Person

scala> class Person {

private var myName ="Flink"

def name = this.myName

def update(newName :String){

myName = newName

println("Hi "+ myName)

}

def talk(p:Person) = {

println("hello:"+p.name)

}

}

defined class Person

//定義 p1為Person物件

scala> val p1=new Person

p1: Person = [email protected]

//定義 p2為Person物件

scala> val p2=new Person

p2: Person = [email protected]

//把p1的myName 屬性值改為p1

scala> p1.update("p1")

Hi p1

//把p2的myName 屬性值改為p2

scala> p2.update("p2")

Hi p2

//檢視p1的myName 屬性值,此時已經改為p1

scala> p1.name

res14: String = p1

//檢視p2的myName 屬性值,此時已經改為p2

scala> p2.name

res15: String = p2

//呼叫p1的talk方法,傳入p2物件,打印出p2的myName 屬性值

scala> p1.talk(p2)

hello:p2

//修改一下程式碼,看看下面程式碼:

scala>class Person {

private[this]var name = "Flink"

def update(newName : String){

name = newName

println("Hi " + name)

}

def talk(p:Person) = {

println("hello:"+p.name)

}

}

:15:error: valuename is not a member of Person

println("hello:"+p.name)

^

//此時,在定義類時就報錯!因為talk方法中p引數是Person類的物件,而name屬性被限制為private[this],所以只能在Person類內部使用,Person類的物件無權使用。也就是說在Person類中,update方法中可以使用name,但是talk方法訪問物件p的name是不允許的!

// private[this]改成private之後,下面的寫法就能正常定義,程式碼如下:

scala>class Person {

private varname = "Flink"

def update(newName : String){

name = newName

println("Hi " + name)

}

def talk(p:Person) = {

println("hello:"+p.name)

}

}

defined class Person

scala>

構造器的過載

scala> class Person {

private[this] var name ="Flink"

private[this] var age = 10

def update(newName :String){

name = newName

println("Hi "+ name)

}

//過載的構造器,首先呼叫預設的構造器

def this(name:String){

this()

this.name=name

}

//過載的構造器,呼叫上面已經存在的構造器

def this(name:String, age:Int){

this(name)

this.age=age

}

}

defined class Person

原始碼, 屬性, 面向物件,
相關問題答案