[scala-spark]6. 继承与特质trait
1. 繼承
- 定義抽象類
抽象類的方法沒有實現(xiàn),抽象類的類本身必須被abstract修飾。而方法只要沒有實現(xiàn),它就是抽象的,不需要加abstract。
- 定義無參方法
無參數(shù)方法在Scala里十分常見。相對的如果帶有空括號的方法,比如def height():Int ,被稱為空括號方法。推薦使用的方式是:只要方法中沒有參數(shù)且方法僅能夠通過讀取所包含對象的屬性去訪問可變狀態(tài)(特指方法不能改變可變狀態(tài)),就使用無參數(shù)方法。這個慣例支持統(tǒng)一訪問原則。簡單來說,就是說客戶代碼不應(yīng)該由屬性是通過字段實現(xiàn)還是方法實現(xiàn)而受到影響。例如我們可以把上述代碼中的def 換成 val,這種轉(zhuǎn)換會使運行更快。在Scala中調(diào)用空括號方法,省略括號是合法的,在無參數(shù)方法和空括號方法之間有著極大的自由程度。
abstract class Element{def contents:Array[String]val height:Int = contents.lenghtval width:Int = if(height==0) 0 else contents(0).length }總之,Scala鼓勵定義將不帶參數(shù)且沒有副作用的方法定義成為無參數(shù)方法的風(fēng)格。
- 定義子類
ArrayElement類用extends 繼承Elements,ArrayElement獲得了Elements的所有非私有屬性成員,ArrayElement是Elements的子類,Elements是ArrayElement的超類。如果一個類沒有extends,編譯器會將該類隱式地繼承scala.AnyRef,如同Java的Object類一樣。?
Scala中,子類可以重寫父類屬性,可以實現(xiàn)父類抽象屬性,繼承父類非私有屬性。這幾點都和Java相同。
- 重寫方法和屬性
Scala中的字段和方法屬于相同的命名空間,這讓字段可以重寫無參數(shù)方法。比如下面:
class ArrayElement(conts:Array[String]) extends Elements{//實現(xiàn)父類的無參數(shù)方法(def contents:Array[String])val contents:Array[String] = conts }- 調(diào)用超類構(gòu)造器和override關(guān)鍵詞
由于LineElement擴展了ArrayElement。并且ArrayElement的構(gòu)造器帶了一個參數(shù)Array[String],因此LineElement需要傳給超類的主構(gòu)造器一個參數(shù)。調(diào)用父類構(gòu)造器,只要簡單地把參數(shù)放在超類后面的括號里即可。
Scala要求,若子類成員重寫了父類的具體成員則必須帶有這個修飾符。但若子類實現(xiàn)的是父類的抽象成員時,則該修飾符也可以省略。若子類并未重寫或?qū)崿F(xiàn)其他基類的成員則禁用這個修飾符。
Scala中的多態(tài)和Java中的相同。
- 定義final成員
- 定義工廠方法
定義一個工廠方法來生產(chǎn)Element的各個子類實例,隱藏了實現(xiàn)細(xì)節(jié)。
object Element {/*** 私有的類,隱藏實現(xiàn)細(xì)節(jié)** @param cons*/private class ArrayElment(cons: Array[String]) extends Elment {val contents = cons}private class UniformElement(ch: Char, override val height: Int, override val width: Int) extends Elment {private val line = ch.toString * widthdef contents = new Array[String](3);}private class LineElment(s: String) extends ArrayElment(Array(s)) {override val height: Int = 1override val width: Int = s.length}/*** 通過公有的方法,提供私有類的實例** @param contents* @return*/def elem(contents: Array[String]): Elment = new ArrayElment(contents)def elem(chr: Char, width: Int, height: Int): Elment = new UniformElement(chr, width, height)def elem(line: String): Elment = new LineElment(line) }2. 特質(zhì)trait
特質(zhì)是Scala中代碼復(fù)用的基本單元。特質(zhì)中封裝了方法和字段的定義。特質(zhì)功能非常強大。類可以混入任意多個特質(zhì),其主要的運用方式是:拓寬瘦接口為胖接口和實現(xiàn)可堆疊的改變。
trait A{val tyl : Stringdef method : Int {...} }trait C{def method : Int {...} }class D {... }class B with A {override def toString = "B with A" }class B extends D with A with C{... }一旦特質(zhì)被定義,就可以用extends或with關(guān)鍵字,把它混入類中。特質(zhì)就像帶有具體方法的Java接口,它可以有正常的變量、方法,即類可以做到的事情,特質(zhì)都可以除了沒有構(gòu)造器。還有一點類的super調(diào)用是靜態(tài)綁定的,而特質(zhì)則是動態(tài)綁定的,這也決定了特質(zhì)可以實現(xiàn)堆疊式改變。
- 拓寬瘦接口為胖接口
瘦接口和胖接口的對陣體現(xiàn)了面向?qū)ο笤O(shè)計常會面臨的實現(xiàn)者和接口用戶之間的權(quán)衡。胖接口有更多方法,對于調(diào)用者來說更為方便,客戶可以選擇一個完全符合他們功能需要的方法。瘦接口有較少的方法,對于實現(xiàn)者來說簡單,但是調(diào)用者卻要為此寫更多的代碼,由于沒有更多可選的方法,他們或許不得不選一個不太完美匹配的或是重寫額外代碼。 Java中的接口常常是過瘦而非過胖。Java中的CharSequence接口定義了4個方法。如果CharSequence包含全部的String接口,那實現(xiàn)者將為CharSequence定義一堆可能自己不需要定義的方法。 試想一下,一個特質(zhì)擁有幾個抽象方法,剩余的是大量具有具體方法的方法。接口用戶只需要混入該特質(zhì),簡單地實現(xiàn)抽象方法,就可以擁有所有的具體方法。這是Java中不能做到的。
總結(jié)
以上是生活随笔為你收集整理的[scala-spark]6. 继承与特质trait的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [scala-spark]5. 伴生类和
- 下一篇: [scala-spark]7. list