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