• Scala学习笔记(三)类层级和特质


    无参方法

    功能:将方法的定义转换为属性字段的定义;

    作用范围:方法中没有参数,并且方法仅能通过读取所包含的对象属性去访问可变状态,而不改变可变状态,就可使用无参方法;

    例子:

    abstract class Element{
        def texts:String
    }

    class Sub1Element(text:String) extends Element{
        val texts:String = text
    }

    object RunApplication{
        def main(args:Array[String]){
            var node:Element = new Sub1Element("Hello World 1");
            println(node.texts);
        }
    }

    说明:

    Scala中仅有两个命名空间:
    1、值(字段、方法、包还有单例对象)
    2、类型(类和特质名)
    正因为字段和方法在同一个命名空间,所以val可重写无参方法;

     

    超类构造器的调用

    例子:

    class Element(text:String){
        println(text);
        def texts:String = text
    }

    class Sub1Element(text:String) extends Element("Hello World 2"){
        override val texts:String = text
    }

    object RunApplication{
        def main(args:Array[String]){
            var node:Element = new Sub1Element("Hello World 1");
            println(node.texts);
        }
    }

     

    override修饰符
    1、若子类成员所有重写了父类成员则必须带有该修饰符;
    2、若成员实现的是同名的抽象成员时,则该修饰符是可选的;
    3、若成员并未重写或实现其它基类里的成员则禁用这个修饰符;

     

    final
    作用:当某个类的成员不需要被子类重写时,可通过final修饰对应的成员来实现;

     

    zip

    作用:将两个数组或集合等取出相应的元素生成二元对数组;

    例子:

    scala> val a = Array[String]("world","world")
    a: Array[String] = Array(world, world)

    scala> val b = Array[Int](1,2,3,4,5)
    b: Array[Int] = Array(1, 2, 3, 4, 5)

    scala> val c = a zip b
    c: Array[(String, Int)] = Array((world,1), (world,2))

    scala> for ((p1,p2) <- c){
         | println(p1+p2)}


    world1
    world2

    说明:

    当两个数组中测长度不一致时,zip将舍弃多余的元素;

     

    Scala类层级

    1、scala中每个类都继承自Any的超类,即所有类都是Any的子类;

    2、Nothing是所有其它类的子类;

    层级图:

     t

     

     

    ==、!=、equals、eq、ne

    1、Any类中的等号和不等号方法(==和!=)被声明为final,因此它们不能被子类重写,而实际上==总是与equals相同,!=总是与equals相反,所以子类可以通过重写equals方法来改变==和!=的意义;【适合值类型比较】

    2、scala中对值的比较使用==或equals,而对引用的比较使用eq和ne,eq为判别引用是否相等,nq作用与eq相反;【适合引用类型比较】

     

    Any有两个子类:AnyVal和AnyRef
    1、AnyVal是Scala里每个内建值类(Byte、Short、Char、Int、Long、Float、Double、Boolean、Unit)的父类;
    2、值类都被定义为即是抽象的又是final的;
    3、AnyRef是scala里所有引用类的基类,在Java平台中对用java.lang.Object的别名,因此Java里面写的类和scala里面写的类都继承自AnyRef;
    4、scala类与Java类的不同在于,scala中的类还继承自ScalaObject的特别的记号特质,有提高执行效率的作用,ScalaObject只包含一个方法,名为$tag,在内部使用加速模式匹配;

     

    scala.Null

    每个引用类的子类(继承自AnyRef),Null不兼容值类型,如:不能把null赋值给整型变量;

    例子:

    scala> val a:Int = null
    <console>:7: error: an expression of type Null is ineligible for implicit conver
    sion
           val a:Int = null
                       ^


    scala.Nothing

    scala的类层级的最低端,它是任何其它类型的的子类;

    作用:标明不正常的终止

    scala> def error(message:String):Nothing=

         throw new RuntimeException(message)

    scala>  def divide(x:Int,y:Int):Int=
         | if (y!=0) x / y else
         | error("can't divide by zero")
    warning: there were 1 deprecation warning(s); re-run with -deprecation for detai
    ls
    divide: (x: Int, y: Int)Int

    scala> val b = divide(2,0)
    java.lang.RuntimeException: can't divide by zero
      at scala.sys.package$.error(package.scala:27)
      at scala.Predef$.error(Predef.scala:139)
      at .divide(<console>:9)

     

    特质
    定义:带有具体方法的Java接口

    例子:

    trait trafunction{
         def showTrait(){println("trafunction")}
    }
    功能:特质可以声明字段和维护状态值,可以用特质的定义做任何用类定义做的事情;
    与类的区别:
    1、特质不能有任何参数(构造器的参数);
    2、特质的调用是动态绑定的;

    extends混入特质
    格式:class 类名 extends 特质

    特质混入扩展超类的类里
    class 类名 extends 基类 with 特质1 with 特质2 ...

    例子:

    // 特质定义

    trait Line{
        def left:Int
        def leftvalue=left+5
        def showLine = println("showTraitLine")
        def showLeft = println("Left is "+left);
    }

    // 工具类

    class Graph(val left:Int) extends Line{
        def showGraph = println(leftvalue)
    }

    // 程序入口

    object TestTrait{
        def main(args:Array[String]){
            val a = new Graph(5);
            a.showLine
            a.showLeft
            a.showGraph
        }
    }

    说明:

    1、在特质Line中定义了left和leftLine两个无参方法,即可将这样的方法看做属性字段处理;

    2、类Graph混入特质Line后,根据构造器传入的参数left自动为特质中的无参数方法left赋值(参数化字段),需要注意的是构造器中的参数名,与特质中定义的无参方法名必须同名;

    3、特质Line中的left若定义为var运行将出错;

     

    Ordered特质

    功能:简话类对比较操作的实现;

    例子:

    class Unit(n:Int) extends Ordered[Unit]{
        def num = n
        def compare(that:Unit) = {
            this.num - this.num
        }
    }

    //程序入口

    object TestUnit{
        def main(args:Array[String]){
            val a = new Unit(5)
            val b = new Unit(9)
            println(a>b)
        }
    }

    说明:

    1、用compare方法替换了所有的比较方法,本质上是Ordered特质利用这个方定义了>、<、>=、<=,所以只需要实现compare那么所有的比较方法就都实现了;

    2、compare返回值说明:相等返回0,this小于that返回负数,this大于that返回正数;

     

    特质的堆叠

    功能:改变类方法的实现,构造所需改造的新类;

    例子:

    import scala.collection.mutable.ArrayBuffer

    abstract class IntQueue{
        def get():Int
        def put(x:Int)
    }
    class BaseQueue extends IntQueue{
        private val buf = new ArrayBuffer[Int]
        def get() = buf.remove(0)
        def put(x:Int){buf += x}
    }
    // 特质的定义改变原有方法的实现
    trait Doubling extends IntQueue{
        abstract override def put(x:Int){
            super.put(2*x)
        }
    }
    // 程序入口
    object TestApplication{
        def main(args:Array[String]){
            val a = new BaseQueue with Doubling
            a.put(10)
            println(a.get())
        }
    }

    说明:

    1、Doubling特质定义了超类IntQueue,这意味着它只能混入扩展了IntQueue的类中;

    2、特质在声明为抽象的方法中有一个super调用,特质里的super调用是动态绑定的,特质Doubling的super调用将直到被混入另一个特质或类之后,有了具体的方法定义才工作;

    3、实现堆叠改动的方法必须使用abstract override 标识修饰;

    4、在有多个特质混入的情况下,越靠近右侧的特质越先起作用,当调用带混入的类的方法时,最有侧特质的方法首先被调用。若果该方法调用了super,它将调用其左侧特质的方法,以此类推;

  • 相关阅读:
    每天OnLineJudge 之 “蛇形矩阵 ”
    Hello World 发生了什么?
    软件开发人员真的了解SQL索引吗(索引使用原则)
    软件开发人员真的了解SQL索引吗(聚集索引)
    项目经验总结(一)如何约定接口的定义
    min的个人网站终于创建起来了
    WCF单例服务,如何实现并发
    如何规范.net中的js开发(2)原理篇(更新版)
    网站架构之缓存应用(3)实现篇
    网站架构之缓存应用(1)概念篇
  • 原文地址:https://www.cnblogs.com/jianyuan/p/4310302.html
Copyright © 2020-2023  润新知