Scala中面向?qū)ο缶幊淘趺从?/h1>

這篇文章主要講解了“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)用合理。

2 面向?qū)ο缶幊?/h3>

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的類允許嵌套定義

類的方法
  1. 方法的調(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

    ?

  2. 方法的返回值

    方法有聲明返回值類型,那么返回值是方法體中最后一條執(zhí)行語(yǔ)句的值;

    方法沒(méi)有聲明返回值類型,那么scala編譯器會(huì)根據(jù)方法體中最后一條執(zhí)行語(yǔ)句的值來(lái)推斷返回值類型。

    此時(shí)如果省略了等號(hào),使用大括號(hào),scala編譯器會(huì)將返回值推斷為Unit。

  3. 方法參數(shù)

    • Scala中,方法的參數(shù)都是不可變的,隱式使用了 val 進(jìn)行聲明,所以既不可以在聲明參數(shù)時(shí)使用var 或val ,也不可以在方法體中重新給參數(shù)賦值。

    • 在scala中調(diào)用方法時(shí)可以顯式地命名參數(shù)列表。

  4. scala中允許方法重載

  5. scala中允許方法的嵌套定義

類成員的可見(jiàn)性

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ì)顯得更加直觀。

構(gòu)造器

在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)樗遣豢勺兊?,只可以讀不可以寫。

對(duì)象

單例對(duì)象

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í)行。

apply方法

之前的介紹中曾經(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è)鍵的值。

    ?

unapply方法

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的類層級(jí)結(jié)構(gòu)

Scala中面向?qū)ο缶幊淘趺从?></p><table><tbody><trl><th>類型</th><th>描述</th></tr></tbody><tbody><tr><td>Null</td><td>所有<strong>引用類型</strong>的子類。值為null,表示一個(gè)空對(duì)象。</td></tr><tr><td>Nothing</td><td>Nothing類型在Scala的類層級(jí)的最底端;它是任何其他類型的子類型。</td></tr><tr><td>Any</td><td>Any是所有其他類的超類</td></tr><tr><td>AnyRef</td><td>AnyRef類是Scala里所有引用類(reference class)的基類</td></tr></tbody></table><ul><li><p>Nothing主要用于異常處理函數(shù)的返回值類型,這樣異常拋出后不會(huì)返回任何對(duì)象,所以異常處理函數(shù)可以更為方便地使用。</p></li></ul><h5>Option類</h5><p>scala采用Option類來(lái)統(tǒng)一表示對(duì)象有值和無(wú)值的情況,Option是一個(gè)抽象類,有一個(gè)具體的類Some和一個(gè)對(duì)象Node。Some表示有值,None表示無(wú)值。</p><h4>參數(shù)化類型</h4><p>scala中的參數(shù)化類型相當(dāng)于java中的泛型,與之不同的是scala中使用方括號(hào)[] 來(lái)定義參數(shù)化類型。</p><h4>特質(zhì) Trait</h4><p>scala中的特質(zhì)Trait 相當(dāng)于java中的接口。一個(gè)特質(zhì)被子類實(shí)現(xiàn)以后,就可以看做這個(gè)類的父類,但與繼承不同的是,特質(zhì)允許多重實(shí)現(xiàn),也就是一個(gè)子類可以混入多個(gè)特質(zhì)。</p><p>特質(zhì)可以同時(shí)用擁有具體方法和抽象方法,這就跟抽象類很相似。</p><p>注:</p><ul><li><p>如果特質(zhì)沒(méi)有顯式地說(shuō)明繼承關(guān)系,那么這個(gè)特質(zhì)就默認(rèn)繼承自AnyRef。</p></li><li><p>如果特質(zhì)繼承自某個(gè)父類,那么它無(wú)法向該父類構(gòu)造器傳遞參數(shù),這就要求特質(zhì)所繼承的父類必須有一個(gè)無(wú)參構(gòu)造器。</p></li><li><p>若要混入多個(gè)特質(zhì),可以使用with關(guān)鍵字(可以連續(xù)使用):</p><pre>class Man extends Person with Boy{     //字段與方法實(shí)現(xiàn)}</pre><p></p></li><li><p>特質(zhì)不能實(shí)例化</p></li></ul><h4>模式匹配</h4><ol><li><p>match 語(yǔ)句</p><p>scala中最常見(jiàn)的模式匹配是match語(yǔ)句,類似于其它語(yǔ)言中的switch語(yǔ)句。</p><pre>val grade = 90grade match {     case 'A' => println("85-100")case 'B' => println("70-84")case 'C' => println("60-69")case _ => println("unqualified!")}</pre><p></p><p>最后一個(gè)case使用了下劃線"_"代表其它情況,相當(dāng)于java中的default分支。</p></li></ol><ol><li><p>case 類</p><p>定義一個(gè)類時(shí),如果在class關(guān)鍵字前加上case修飾,則該類為case類。scala為case類重載了許多實(shí)用的方法,包括tiString,equals和hashcode方法。更重要的是,scala為每一個(gè)case類自動(dòng)生成一個(gè)伴生對(duì)象。</p></li></ol><h4>包</h4><p>為了解決程序中的命名沖突,scala也和java一樣使用包來(lái)層次化、模塊化地組織程序。</p><p>將代碼放在指定包中的兩種方法:</p><ul><li><p>在代碼文件的頂端使用package關(guān)鍵字聲明</p></li><li><p>在package子句中加一對(duì)大括號(hào),將類和對(duì)象放在大括號(hào)里</p></li></ul><p>感謝各位的閱讀,以上就是“Scala中面向?qū)ο缶幊淘趺从谩钡膬?nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Scala中面向?qū)ο缶幊淘趺从眠@一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!</p>            <p>
                網(wǎng)頁(yè)名稱:<a href=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)