本期内容:
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