天天看點

Scala學習筆記(五)1. 抽象類2. 類中的apply()3. 類中的update()總結

1. 抽象類

Scala 的抽象類跟Java的一樣,不能被執行個體化。

1.1抽象字段

抽象類中,變量不使用就無需初始化,可以等到子類繼承時再進行初始化。

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更符合标準
     | }
defined class Bull2           

複制

1.2抽象方法

在抽象類中,抽象方法無需使用(也不能)用abstract進行修飾。

一個方法隻要是沒有它的實作(沒有等号或沒有方法體),它就是抽象的,在子類中覆寫或者覆寫接口中的非抽象方法(方法有具體實作)要使用override關鍵字。

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() 可以看作是一個文法糖,它分為兩種方式:object和class中的用法。

2.1 常見的 apply() 用法

借用一個經典的例子。

scala> class Foo{}
defined class Foo

scala> object FooMaker {
     |   def apply() = new Foo
     | }
defined object FooMaker

scala> val newFoo = FooMaker()
newFoo: Foo = Foo@39ba5a14           

複制

在調用 FooMaker() 時,觸發了apply(),是以生成了一個新的Foo對象。

再來看一個例子。

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           

複制

這次是在調用bar()時,觸發了apply(),列印了this is bar

由此,可以總結:

  • object類是單例,不能進行new的執行個體化。在調用

    類名()

    時,便會觸發調用該object中的apply()。如果object類中沒有apply(),這樣調用會報錯。
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()
                               ^           

複制

  • 在類中,建立 val bar = new Bar 之後,調用 bar() 便會觸發該類的apply()。同樣,class中沒有定義apply(),這樣調用也是會報錯的。
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 伴生類和伴生對象中的apply()

把剛才的内容結合起來,順便回憶一下上一篇中的伴生類和伴生對象。

/**
  * 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()使用
  }
}           

複制

調用的結果如下:

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(),因為在 Scala 中函數即對象,後面的筆記會進行總結。

3. 類中的update()

update() 也可以看作是 Scala 的文法糖。

使用 update() 時,等号右邊的值會作為 update 方法的最後一個參數。

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" 這兩句話是等價的。前一種方法比較中規中矩,後一種方法更加簡潔。

總結

本篇筆記仍然是整理類相關的内容,主要是抽象類、類中的apply()和update()。apply()和update()都是文法糖,加以合适的應用,能得到可讀性極強的代碼。

下一篇筆記會整理 Scala 的模式比對。

先前的文章:

Scala學習筆記(四) 類的初步

Scala學習筆記(三)

Scala學習筆記(二)

Scala學習筆記(一)