1、繼承java
一、extendses6
Scala中,讓子類繼承父類,與Java同樣,也是使用extends關鍵字 繼承就表明,子類能夠從父類繼承父類的field和method;而後子類能夠在本身內部放入父類所沒有, 子類特有的field和method;使用繼承能夠有效複用代碼 子類能夠覆蓋父類的field和method;可是若是父類用final修飾,field和method用final修飾,則該類是沒法被繼承的, field和method是沒法被覆蓋的; ### scala> :paste // Entering paste mode (ctrl-D to finish) class Person { private var name = "leo" def getName = name } class Student extends Person { private var score = "A" def getScore = score } // Exiting paste mode, now interpreting. defined class Person defined class Student warning: previously defined object Person is not a companion to class Person. Companions must be defined together; you may wish to use :paste mode for this. scala> val s = new Student s: Student = Student@985696 scala> s.getName res11: String = leo scala> s.getScore res12: String = A scala> s.getName res13: String = leo scala> s.name <console>:14: error: value name is not a member of Student s.name ^
二、override和superide
//Scala中,若是子類要覆蓋一個父類中的非抽象方法,則必須使用override關鍵字;
//override關鍵字能夠幫助咱們儘早地發現代碼裏的錯誤,好比:override修飾的父類方法的方法名咱們拼寫錯了;好比要覆蓋的父類方法的參數咱們寫錯了;等等
//此外,在子類覆蓋父類方法以後,若是咱們在子類中就是要調用父類的被覆蓋的方法呢?
那就可使用super關鍵字,顯式地指定要調用父類的方法
###
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Person {
private var name = "leo"
def getName = name
}
class Student extends Person {
private var score = "A"
def getScore = score
override def getName = "Hi, I'm a student, my name is " + super.getName
}
// Exiting paste mode, now interpreting.
defined class Person
defined class Student
warning: previously defined object Person is not a companion to class Person.
Companions must be defined together; you may wish to use :paste mode for this.
scala> val s = new Student
s: Student = Student@618ad2aa
scala> s.getName
res15: String = Hi, I'm a student, my name is leo
三、override field函數
// Scala中,子類能夠覆蓋父類的val field,並且子類的val field還能夠覆蓋父類的val field的getter方法;只要在子類中使用override關鍵字便可
###
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Person {
val name: String = "Person"
def age: Int = 0
}
class Student extends Person {
override val name: String = "leo"
override val age: Int = 30
}
// Exiting paste mode, now interpreting.
defined class Person
defined class Student
warning: previously defined object Person is not a companion to class Person.
Companions must be defined together; you may wish to use :paste mode for this.
scala> val p = new Person
p: Person = Person@71d9cb05
scala> p.name
res16: String = Person
scala> p.age
res17: Int = 0
scala> val s = new Student
s: Student = Student@1ac4ccad
scala> s.name
res18: String = leo
scala> s.age
res19: Int = 30
四、isInstanceOf和asInstanceOfthis
// 若是咱們建立了子類的對象,可是又將其賦予了父類類型的變量。則在後續的程序中,咱們又須要將父類類型的變量轉換爲子類類型的變量,應該如何作?
// 首先,須要使用isInstanceOf判斷對象是不是指定類的對象,若是是的話,則可使用asInstanceOf將對象轉換爲指定類型
// 注意,若是對象是null,則isInstanceOf必定返回false,asInstanceOf必定返回null
// 注意,若是沒有用isInstanceOf先判斷對象是否爲指定類的實例,就直接用asInstanceOf轉換,則可能會拋出異常
###
scala> class Person
defined class Person
warning: previously defined object Person is not a companion to class Person.
Companions must be defined together; you may wish to use :paste mode for this.
scala> class Student extends Person
defined class Student
scala> val p: Person = new Student
p: Person = Student@f324455
scala> var s: Student = null
s: Student = null
scala> if (p.isInstanceOf[Student]) s = p.asInstanceOf[Student]
五、getClass和classOfspa
// isInstanceOf只能判斷出對象是不是指定類以及其子類的對象,而不能精確判斷出,對象就是指定類的對象
// 若是要求精確地判斷對象就是指定類的對象,那麼就只能使用getClass和classOf了
// 對象.getClass能夠精確獲取對象的類,classOf[類]能夠精確獲取類,而後使用==操做符便可判斷
###
scala> class Person
defined class Person
scala> class Student extends Person
defined class Student
scala> val p: Person = new Student
p: Person = Student@77468bd9
scala> p.isInstanceOf[Person]
res0: Boolean = true
scala> p.getClass == classOf[Person]
res1: Boolean = false
scala> p.getClass == classOf[Student]
res2: Boolean = true
六、使用模式匹配進行類型判斷scala
// 可是在實際開發中,好比spark的源碼中,大量的地方都是使用了模式匹配的方式來進行類型的判斷,這種方式更加地簡潔明瞭,
並且代碼得可維護性和可擴展性也很是的高
// 使用模式匹配,功能性上來講,與isInstanceOf同樣,也是判斷主要是該類以及該類的子類的對象便可,不是精準判斷的
###
scala> class Person
defined class Person
scala> class Student extends Person
defined class Student
scala> val p: Person = new Student
p: Person = Student@192d3247
scala> p match {
| case per: Person => println("it's Person's object")
| case _ => println("unknown type")
| }
it's Person's object
七、protectedcode
// 跟java同樣,scala中一樣可使用protected關鍵字來修飾field和method,這樣在子類中就不須要super關鍵字,直接就能夠訪問field和method // 還可使用protected[this],則只能在當前子類對象中訪問父類的field和method,沒法經過其餘子類對象訪問父類的field和method ### scala> :paste // Entering paste mode (ctrl-D to finish) class Person { protected var name: String = "leo" } class Student extends Person { def makeFriends(s: Student) { println("Hi, my name is " + name + ", your name is " + s.name) } } // Exiting paste mode, now interpreting. defined class Person defined class Student scala> val s1 = new Student s1: Student = Student@63355449 scala> val s2 = new Student s2: Student = Student@1ab3a8c8 scala> s1.makeFriends(s2) Hi, my name is leo, your name is leo scala> :paste // Entering paste mode (ctrl-D to finish) class Person { protected[this] val name: String = "leo" } class Student extends Person { def makeFriends(s: Student) { println("my name is " + name + ", your name is " + s.name) } } // Exiting paste mode, now interpreting. <console>:22: error: value name is not a member of Student println("my name is " + name + ", your name is " + s.name) ^
八、調用父類的constructor對象
// Scala中,每一個類能夠有一個主constructor和任意多個輔助constructor,而每一個輔助constructor的第一行都必須是調用其餘輔助constructor或者是主constructor;
所以子類的輔助constructor是必定不可能直接調用父類的constructor的
// 只能在子類的主constructor中調用父類的constructor,如下這種語法,就是經過子類的主構造函數來調用父類的構造函數
// 注意!若是是父類中接收的參數,好比name和age,子類中接收時,就不要用任何val或var來修飾了,不然會認爲是子類要覆蓋父類的field
###
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Person(val name: String, val age: Int)
class Student(name: String, age: Int, var score: Double) extends Person(name, age) {
def this(name: String) {
this(name, 0, 0.0)
}
def this(age: Int) {
this("leo", age, 0)
}
}
// Exiting paste mode, now interpreting.
defined class Person
defined class Student
scala> val s = new Student("leo", 30, 100)
s: Student = Student@783a467b
scala> s.name
res6: String = leo
scala> s.age
res7: Int = 30
scala> s.score
res8: Double = 100.0
scala> val s2 = new Student("leo")
s2: Student = Student@6f204a1a
scala> s2.name
res9: String = leo
scala> s2.age
res10: Int = 0
scala> val s3 = new Student(30)
s3: Student = Student@3224a577
scala> s3.name
res11: String = leo
scala> s3.age
res12: Int = 30
scala> s3.score
res13: Double = 0.0
九、匿名子類blog
// 在Scala中,匿名子類是很是常見,並且很是強大的。Spark的源碼中也大量使用了這種匿名子類。
// 匿名子類,也就是說,能夠定義一個類的沒有名稱的子類,並直接建立其對象,而後將對象的引用賦予一個變量。以後甚至能夠將該匿名子類的對象傳遞給其餘函數。
###
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Person(protected val name: String) {
def sayHello = "Hello, I'm " + name
}
val p = new Person("leo") {
override def sayHello = "Hi, I'm " + name
}
def greeting(p: Person {def sayHello: String}) {
println(p.sayHello)
}
// Exiting paste mode, now interpreting.
defined class Person
p: Person = $anon$1@3f270e0a
greeting: (p: Person{def sayHello: String})Unit
scala> greeting(p)
Hi, I'm leo
十、抽象類
// 若是在父類中,有某些方法沒法當即實現,而須要依賴不一樣的子來來覆蓋,重寫實現本身不一樣的方法實現。此時能夠將父類中的這些方法不給出具體的實現, 只有方法簽名,這種方法就是抽象方法。 // 而一個類中若是有一個抽象方法,那麼類就必須用abstract來聲明爲抽象類,此時抽象類是不能夠實例化的 // 在子類中覆蓋抽象類的抽象方法時,不須要使用override關鍵字 ### scala> :paste // Entering paste mode (ctrl-D to finish) abstract class Person(val name: String) { def sayHello: Unit } class Student(name: String) extends Person(name) { def sayHello: Unit = println("Hello, " + name) } // Exiting paste mode, now interpreting. defined class Person defined class Student scala> val p = new Person <console>:11: error: class Person is abstract; cannot be instantiated val p = new Person ^ scala> val s = new Student("leo") s: Student = Student@368239c8 scala> s.sayHello Hello, leo
十一、抽象field
// 若是在父類中,定義了field,可是沒有給出初始值,則此field爲抽象field
// 抽象field意味着,scala會根據本身的規則,爲var或val類型的field生成對應的getter和setter方法,可是父類中是沒有該field的
// 子類必須覆蓋field,以定義本身的具體field,而且覆蓋抽象field,不須要使用override關鍵字
###
scala> :paste
// Entering paste mode (ctrl-D to finish)
abstract class Person {
val name: String
}
class Student extends Person {
val name: String = "leo"
}
// Exiting paste mode, now interpreting.
defined class Person
defined class Student
scala> val s = new Student
s: Student = Student@1794d431
scala> s.name
res1: String = leo