這篇文章主要講解了“Scala中面向?qū)ο缶幊淘趺从谩保闹械闹v解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Scala中面向?qū)ο缶幊淘趺从谩卑桑?/p>
在沙坡頭等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)、做網(wǎng)站 網(wǎng)站設(shè)計(jì)制作按需求定制制作,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,成都全網(wǎng)營(yíng)銷推廣,外貿(mào)網(wǎng)站建設(shè),沙坡頭網(wǎng)站建設(shè)費(fèi)用合理。
scala在數(shù)據(jù)的處理上使用的是函數(shù)式編程思想,但在上層的架構(gòu)組織中仍使用面向?qū)ο?/strong>的模型,對(duì)于大型應(yīng)用程序尤其重要。
?
類的聲明使用關(guān)鍵字 class:
class Counter{ //這里定義類的字段和方法}
Scala中建議類名首字母大寫。
要定義類的字段,使用var/val,和變量的定義一樣。
要定義類的方法,使用def 關(guān)鍵字。
下面來(lái)定義一個(gè)完整的類:
class Woman{ //定義類的字段val sex = "female"//定義類的方法def usedToBeGirl():Unit = { println("A Woman used to be a girl.")}}
方法usedToBeGirl()
的返回值類型為Unit
,代表它沒(méi)有返回任何結(jié)果,是一個(gè)空值,表示為()
。
scala的類允許嵌套定義
方法的調(diào)用
方法若沒(méi)有參數(shù),在定義時(shí)可以省略括號(hào)。
方法定義時(shí)若省略了括號(hào),那么調(diào)用時(shí)也不能帶括號(hào);若沒(méi)有省略括號(hào),則調(diào)用時(shí)帶不帶括號(hào)都可以。
比如:
class MyFather{ //定義類的字段val age = 40val sex = "male"//定義類的方法def getAge():Int = agedef getSex:String = sex}
這里getAge
方法的調(diào)用:
//先創(chuàng)建一個(gè)實(shí)例val f = new MyFather//以下這兩種調(diào)用方法都可以f.getAge f.getAge()//getSex方法聲明時(shí)沒(méi)有括號(hào),調(diào)用時(shí)也不能有括號(hào)f.getSex
?
方法的返回值
方法有聲明返回值類型,那么返回值是方法體中最后一條執(zhí)行語(yǔ)句的值;
方法沒(méi)有聲明返回值類型,那么scala編譯器會(huì)根據(jù)方法體中最后一條執(zhí)行語(yǔ)句的值來(lái)推斷返回值類型。
此時(shí)如果省略了等號(hào),使用大括號(hào),scala編譯器會(huì)將返回值推斷為Unit。
方法參數(shù)
Scala中,方法的參數(shù)都是不可變的,隱式使用了 val 進(jìn)行聲明,所以既不可以在聲明參數(shù)時(shí)使用var 或val ,也不可以在方法體中重新給參數(shù)賦值。
在scala中調(diào)用方法時(shí)可以顯式地命名參數(shù)列表。
scala中允許方法重載
scala中允許方法的嵌套定義
scala類中,所有成員的默認(rèn)可見(jiàn)性都是公有的,且不需要使用 public 關(guān)鍵字進(jìn)行限定。
除了public之外,scala也具有和java同樣的可見(jiàn)性選項(xiàng):private和protected。
private:對(duì)本類和嵌套類可見(jiàn)
protected:對(duì)本類和子類可見(jiàn)
scala是不推薦將所有成員設(shè)置為公有屬性的,而建議將其設(shè)置為private,這樣外部成員就無(wú)法直接訪問(wèn)私有字段。因此,像java類中使用的getter和setter方法一樣,scala也提供對(duì)private 字段進(jìn)行訪問(wèn)和修改的方法。
class Counter{ //定義一個(gè)private字段private var privateValue = 0//提供訪問(wèn)和修改privateValue的方法def value = privateValuedef value_ = (newValue:Int){ if (newValue > 0) privateValue = newValue} }
其中,value 和value_ 這兩個(gè)方法是成對(duì)的。
訪問(wèn)privateValue字段:
//先實(shí)例化一個(gè)對(duì)象val counter = new Counter//訪問(wèn)privateValuecouner.value//修改privateValuecounter.value_(3)
上面對(duì)私有字段進(jìn)行修改的方法也可以省略下劃線_(scala語(yǔ)法規(guī)定):
counter.value(3)
這樣會(huì)顯得更加直觀。
在scala中,整個(gè)類的定義主體就是類的構(gòu)造器,稱為主構(gòu)造器,所有位于類方法以外的語(yǔ)句都將在構(gòu)造過(guò)程中被執(zhí)行。
那么如何向構(gòu)造器傳入?yún)?shù)呢?
scala規(guī)定在類名之后使用圓括號(hào)列出主構(gòu)造器的參數(shù)列表:
class Counter(name:String){ private val value = 0}
除了主構(gòu)造器,scala類還可以擁有零個(gè)或多個(gè)輔助構(gòu)造器。
每個(gè)輔助構(gòu)造器的第一條語(yǔ)句必須是對(duì)主構(gòu)造器或者此前已經(jīng)定義的輔助構(gòu)造器的調(diào)用。
輔助構(gòu)造器使用this進(jìn)行定義,調(diào)用形式為:this(參數(shù)列表)
。
與普通方法的定義不同,構(gòu)造器的參數(shù)可以使用val 或var進(jìn)行定義。scala將自動(dòng)為這些參數(shù)創(chuàng)建私有字段。
使用val 定義的參數(shù),只會(huì)為其生成讀方法,因?yàn)樗遣豢勺兊?,只可以讀不可以寫。
scala中的單例對(duì)象相當(dāng)于java中的靜態(tài)成員。
單例對(duì)象的定義使用object關(guān)鍵字:
object Person{ private var lastId = 0{ lastId += 1 lastId }}
單例對(duì)象在第一次被訪問(wèn)的時(shí)候初始化。
單例對(duì)象包括兩種:伴生對(duì)象和孤立對(duì)象。
當(dāng)一個(gè)單例對(duì)象具有同名類,則這個(gè)單例對(duì)象就稱為這個(gè)同名類的伴生對(duì)象。相應(yīng)的,這個(gè)同名類就稱為這個(gè)單例對(duì)象的伴生類。它們之間可以互相訪問(wèn)對(duì)方的私有成員。
反之,沒(méi)有同名類的單例對(duì)象,就稱為孤立對(duì)象。比如scala程序的入口main方法就定義在一個(gè)孤立對(duì)象里:
object HelloWorld{ //HelloWorld是一個(gè)孤立對(duì)象def main(args[]:Array[String]){ println("Hello World!")}}
對(duì)于包含了伴生類和伴生對(duì)象定義的代碼文件,不能直接在REPL中使用":load"命令來(lái)執(zhí)行,需要先對(duì)其進(jìn)行編譯,再用scala命令來(lái)執(zhí)行。
之前的介紹中曾經(jīng)使用過(guò)apply方法:
val strArr = Array("hadoop","spark","flink")
可以看到這里實(shí)例化了一個(gè)數(shù)組對(duì)象strArr,但是并沒(méi)有使用new關(guān)鍵字進(jìn)行創(chuàng)建,這里實(shí)際上就是隱式調(diào)用了apply方法。整個(gè)過(guò)程就是,scala自動(dòng)調(diào)用了Array類的伴生對(duì)象Array中一個(gè)apply方法,創(chuàng)建了一個(gè)Array對(duì)象。
apply方法也可以定義在類中,比如說(shuō)定義如下類TestApply:
class TestApply{ def apply(param:String):Unit = { println("apply method called " + param)}}
在REPL模式下執(zhí)行程序:
先創(chuàng)建一個(gè)TestApply對(duì)象,名為myObject。然后執(zhí)行myObject("Hello Apply")
,傳遞了一個(gè)參數(shù),執(zhí)行的結(jié)果就是類中的apply方法被自動(dòng)調(diào)用了。
scala> val myObject = new TestApply val myObject: TestApply = TestApply@3caf5c96scala> myObject("Hello Apply")apply method called Hello Apply
然而我的學(xué)識(shí)尚淺,有一個(gè)疑惑,把a(bǔ)pply方法名改成別的還會(huì)自動(dòng)調(diào)用該方法嗎?
經(jīng)過(guò)我的實(shí)驗(yàn)可以證明,答案是:不會(huì)。
將TestApply類中的apply方法改名為helloApply,然后重新執(zhí)行程序:
scala> :load /usr/local/scala/mycode/testApply.scalaval args: Array[String] = Array()Loading /usr/local/scala/mycode/testApply.scala...class TestApply scala> val myObject = new TestApplyval myObject: TestApply = TestApply@53da2aecscala> myObject("Hello Apply") ^ error: TestApply does not take parameters scala> myObject.helloApply("Hello Apply")apply method called Hello Apply只有顯式調(diào)用helloApply方法才行。
apply方法定義在類的伴生對(duì)象中(更通常的用法)
將類的構(gòu)造方法以apply方法的形式定義在類的伴生對(duì)象中,類的伴生對(duì)象就成為了一個(gè)“工廠”,專門生產(chǎn)類的實(shí)例,apply方法就稱為工廠方法。
實(shí)際上,apply方法設(shè)計(jì)的初衷就是為了保持對(duì)象和函數(shù)之間使用的一致性,數(shù)學(xué)中函數(shù)的使用形式是函數(shù)(參數(shù))
,在scala中函數(shù)也是對(duì)象,因此scala的方法調(diào)用可以省去對(duì)方法的調(diào)用,像使用函數(shù)一樣使用方法。
函數(shù)(參數(shù))函數(shù).方法(參數(shù))
在scala中,apply的調(diào)用規(guī)則是:用括號(hào)傳遞給類實(shí)例或?qū)ο竺粋€(gè)或多個(gè)參數(shù)時(shí),scala會(huì)在相應(yīng)的類或?qū)ο笾胁檎颐麨閍pply的方法,且要求參數(shù)列表與傳入?yún)?shù)一致,然后調(diào)用該apply方法。
update 方法
update跟apply方法遵循同樣的調(diào)用規(guī)則,update方法用于對(duì)象的重新賦值,比如可變Map類的伴生對(duì)象中就有update方法,可以修改某個(gè)鍵的值。
?
unupply方法用于對(duì)對(duì)象進(jìn)行解構(gòu)操作,它也會(huì)被自動(dòng)調(diào)用。
unapply方法可以看做apply方法的反向操作,它從某個(gè)類的構(gòu)造函數(shù)中解構(gòu)出該函數(shù)的傳入?yún)?shù)。
若一個(gè)類包含沒(méi)有實(shí)現(xiàn)的成員(字段或方法),那么它就是抽象類,要使用abstract 關(guān)鍵詞對(duì)該類進(jìn)行修飾。
abstract class Person{ val name:Stringval age:Intdef getAge()def greeting(){ println("hello")}}
抽象類中的抽象字段必須聲明類型。抽象類不能實(shí)例化,只能作為父類被其它類繼承。
與java不同的是,scala抽象類中的抽象方法不需要加abstract修飾。
scala中的繼承與java一樣,只支持單一繼承,即一個(gè)子類只能有一個(gè)父類。繼承父類使用關(guān)鍵字使用extends關(guān)鍵字表示。
定義子類時(shí),需要注意以下幾點(diǎn):
重載父類的抽象成員時(shí),override關(guān)鍵字是可選的;重載父類的非抽象成員時(shí),override關(guān)鍵字是必選的。
建議重載父類的抽象成員也使用關(guān)鍵字override,若在后續(xù)的業(yè)務(wù)中父類的抽象成員被實(shí)現(xiàn)了,此時(shí)該成員就是非抽象成員。因?yàn)橹剌d非抽象成員時(shí)override關(guān)鍵字是必選的,如果子類沒(méi)有使用override關(guān)鍵字,就會(huì)出現(xiàn)編譯錯(cuò)誤,此時(shí)用戶會(huì)及時(shí)發(fā)現(xiàn)父類的改變。
子類在重載時(shí)只能重載val修飾的字段,var本身就是可變的,重載并沒(méi)有意義。
子類的主構(gòu)造器必須調(diào)用父類的主構(gòu)造器或輔助構(gòu)造器。
若父類構(gòu)造器中有val或var修飾的參數(shù),它就相當(dāng)于類的字段,因此如果子類的構(gòu)造器參數(shù)中包含與父類構(gòu)造器中同名的參數(shù),那么子類構(gòu)造器相當(dāng)于重載了父類字段,需要使用override對(duì)該構(gòu)造器參數(shù)進(jìn)行修飾。
Scala中面向?qū)ο缶幊淘趺从?/a>
網(wǎng)頁(yè)網(wǎng)址:http://muchs.cn/article46/iejohg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、微信小程序、做網(wǎng)站、網(wǎng)站建設(shè)、、服務(wù)器托管
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)