1. 抽象類
Scala 的抽象類跟Java的一樣侦镇,不能被實(shí)例化资锰。
1.1抽象字段
抽象類中谆棱,變量不使用就無需初始化,可以等到子類繼承時(shí)再進(jìn)行初始化拯田。
scala> abstract class Animal {
| val name:String // 抽象字段历造,沒有帶初始值
| }
defined class Animal
scala> class Bull extends Animal {
| val name = "bull"
| }
defined class Bull
scala> class Bull2 extends Animal {
| override val name = "bull2" // 加上override更符合標(biāo)準(zhǔn)
| }
defined class Bull2
1.2抽象方法
在抽象類中,抽象方法無需使用(也不能)用abstract進(jìn)行修飾船庇。
一個(gè)方法只要是沒有它的實(shí)現(xiàn)(沒有等號(hào)或沒有方法體)吭产,它就是抽象的,在子類中覆寫或者覆寫接口中的非抽象方法(方法有具體實(shí)現(xiàn))要使用override關(guān)鍵字鸭轮。
scala> abstract class Teacher{
| var name:String
| var age:String
| def teach
| }
defined class Teacher
scala> class TeacherForMath extends Teacher {
| var name = "Tony"
| var age = "30"
| override def teach = println("teaching Math")
| }
defined class TeacherForMath
scala> val teacher = new TeacherForMath()
teacher: TeacherForMath = TeacherForMath@27ddd392
scala> teacher.teach
teaching Math
1.3抽象類型
Scala 中的類型成員也可以是抽象的臣淤。
比如,在Trait中窃爷,你可以讓類型成員保持抽象邑蒋。
scala> trait Foo {
| type T;
| val x:T;
| def getX:T = x
| }
defined trait Foo
scala> (new Foo{type T = Int; val x = 123}).getX
res0: Int = 123
scala> (new Foo{type T = String;val x = "hello tony"}).getX
res1: String = hello tony
2. 類中的apply()
在 Scala 的類中,apply() 可以看作是一個(gè)語法糖按厘,它分為兩種方式:object和class中的用法医吊。
2.1 常見的 apply() 用法
借用一個(gè)經(jīng)典的例子。
scala> class Foo{}
defined class Foo
scala> object FooMaker {
| def apply() = new Foo
| }
defined object FooMaker
scala> val newFoo = FooMaker()
newFoo: Foo = Foo@39ba5a14
在調(diào)用 FooMaker() 時(shí)逮京,觸發(fā)了apply()卿堂,所以生成了一個(gè)新的Foo對(duì)象。
再來看一個(gè)例子。
scala> class Bar {
| def apply() = println("this is bar")
| }
defined class Bar
scala> val bar = new Bar
bar: Bar = Bar@59e84876
scala> println(bar())
this is bar
()
scala> bar()
this is bar
這次是在調(diào)用bar()時(shí)草描,觸發(fā)了apply()览绿,打印了this is bar
由此,可以總結(jié):
- object類是單例穗慕,不能進(jìn)行new的實(shí)例化饿敲。在調(diào)用
類名()
時(shí),便會(huì)觸發(fā)調(diào)用該object中的apply()逛绵。如果object類中沒有apply()诀蓉,這樣調(diào)用會(huì)報(bào)錯(cuò)。
scala> object FooMarker2 {
| def apply2() = new Foo
| }
defined object FooMarker2
scala> val newFoo2 = FooMarker2()
<console>:13: error: FooMarker2.type does not take parameters
val newFoo2 = FooMarker2()
^
- 在類中暑脆,創(chuàng)建 val bar = new Bar 之后,調(diào)用 bar() 便會(huì)觸發(fā)該類的apply()狐肢。同樣添吗,class中沒有定義apply(),這樣調(diào)用也是會(huì)報(bào)錯(cuò)的份名。
scala> class Bar2 {
| def apply2() = println("this is bar2")
| }
defined class Bar2
scala> val bar2 = new Bar2
bar2: Bar2 = Bar2@7f416310
scala> bar2()
<console>:14: error: Bar2 does not take parameters
bar2()
^
2.2 伴生類和伴生對(duì)象中的apply()
把剛才的內(nèi)容結(jié)合起來碟联,順便回憶一下上一篇中的伴生類和伴生對(duì)象。
/**
* Created by tony on 2017/2/28.
*/
class ApplyTest {
def apply() = println("This is called by class!")
def haveATry: Unit = {
println("have a try on apply")
}
}
object ApplyTest {
def apply() = {
println("This is called by companion object")
new ApplyTest
}
}
object ApplyOperation {
def main(args: Array[String]) {
val a1 = ApplyTest() //object 的 apply() 使用
a1.haveATry
a1() // class 中 apply()使用
println("------------------")
val a2 = new ApplyTest
a2.haveATry
a2() // class 中 apply()使用
}
}
調(diào)用的結(jié)果如下:
This is called by companion object
have a try on apply
This is called by class!
------------------
have a try on apply
This is called by class!
Process finished with exit code 0
最后僵腺,除了在類中可以使用apply()鲤孵,在function中也可以使用apply(),因?yàn)樵?Scala 中函數(shù)即對(duì)象辰如,后面的筆記會(huì)進(jìn)行總結(jié)普监。
3. 類中的update()
update() 也可以看作是 Scala 的語法糖。
使用 update() 時(shí)琉兜,等號(hào)右邊的值會(huì)作為 update 方法的最后一個(gè)參數(shù)凯正。
scala> class User(var name:String,var password:String) {
| def update(name:String,password:String) = {
| println(s"changing use of $name and $password")
| this.name = name
| this.password = password
| }
| }
defined class User
scala> val tony = new User("tony","123456")
tony: User = User@6d868997
scala> tony.password
res17: String = 123456
scala> tony.update("tony","abcdefg")
changing use of tony and abcdefg
scala> tony.password
res19: String = abcdefg
scala> tony("tony") = "abcdefg"
changing use of tony and abcdefg
scala> tony.password
res21: String = abcdefg
在這里,tony.update("tony","abcdefg") 和 tony("tony") = "abcdefg" 這兩句話是等價(jià)的豌蟋。前一種方法比較中規(guī)中矩廊散,后一種方法更加簡(jiǎn)潔。
總結(jié)
本篇筆記仍然是整理類相關(guān)的內(nèi)容梧疲,主要是抽象類允睹、類中的apply()和update()。apply()和update()都是語法糖幌氮,加以合適的應(yīng)用缭受,能得到可讀性極強(qiáng)的代碼。
下一篇筆記會(huì)整理 Scala 的模式匹配浩销。
先前的文章:
Scala學(xué)習(xí)筆記(四) 類的初步
Scala學(xué)習(xí)筆記(三)
Scala學(xué)習(xí)筆記(二)
Scala學(xué)習(xí)筆記(一)