美文网首页scala程序员
Scala学习笔记(五) 抽象类以及类中的一些语法糖

Scala学习笔记(五) 抽象类以及类中的一些语法糖

作者: fengzhizi715 | 来源:发表于2017-02-28 19:02 被阅读0次

    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学习笔记(一)

    相关文章

      网友评论

        本文标题:Scala学习笔记(五) 抽象类以及类中的一些语法糖

        本文链接:https://www.haomeiwen.com/subject/kzcuwttx.html