Scala--第七天

yunfenglee 2020-02-12

一、内部类

定义:实现一个抽象类 或者 Trait 时 可以通过内部类的方式完成

abstract class Cmx {
    def func: Unit

  }

  def main(args: Array[String]): Unit = {
    var cmx = new Cmx {
      override def func: Unit = {
        println("我是内部类")
      }
    }
    cmx.func
    //我是内部类
  }

二、特质 Trait

  定义:类似于其它语言的接口

  格式:trait 名称{

      //抽象成员方法或属性

      //普通成员方法或属性

      }

  注意:Trait中的抽象成员 必须全部实现 ,不然程序报错,如果实现不完整 只能称这个类为抽象类 需要加上abstract字段

trait cmx {
    //抽象属性和普通属性
    var name: String
    var age = 10

    //抽象方法和普通方法
    def func(): Unit

    def func1(): Unit = {
      println("我是特质的普通方法")
    }
  }

  class cmx01 extends cmx {
    override var name = "cmx01"

    override def func(): Unit = {
      println("必须重写")
    }
  }

  def main(args: Array[String]): Unit = {
    var a = new cmx01
    a.func()
    println(a.name)
    //必须重写
    //cmx01
  }

  Trait与abstract的区别

  1.  abstract是单根继承体系,只能继承一个父类

       Trait是多继承体系,可以被继承多个父类,使用关键字with
  2.  在实战中,抽象类 表达的是 抽象的概念 名词

           trait 表达的是 抽象的行为 动词

区别一
  class Person

  trait Cmx

  trait Cmx01

  class User extends Person with Cmx with Cmx01 {
    print("---------")
  }

  def main(args: Array[String]): Unit = {
    var a = new User
    //主构造器的返回结果
    //---------
  }
区别二
//打印日志是实际的动作,是个动词
  trait Logger {
    def log(msg: String)
  }

  class ConsoleLogger extends Logger {
    override def log(msg: String): Unit = println(s"---控制台打印日志${msg}---")
  }

  class DBLogger extends Logger {
    override def log(msg: String): Unit = println("----数据库存储日志----")
  }


  def main(args: Array[String]): Unit = {
    var logger = new ConsoleLogger
    logger.log("ok")
    //---控制台打印日志ok---
  }

object 继承trait

trait cmx {
    def func(): Unit
  }

  object A extends cmx {
    override def func(): Unit = {
      println("单例对象继承特质类")
    }
  }

  def main(args: Array[String]): Unit = {
    A.func()
    //单例对象继承特质类
  }

  trait 可以和父类共存,但是注意父类一定要在前面,trait在后面,因为之后trait才能用with关键字

  以下案例,将演示以上的案例,同时演示继承的构造顺序

class Person {
    println("执行Person构造器")
  }

  trait Cmx {
    println("执行Cmx构造器")
  }

  trait Cmx01 extends Cmx {
    println("执行cmx01构造器")
  }

  trait Cmx02 extends Cmx {
    println("执行cmx02构造器")
  }

  class User extends Person with Cmx01 with Cmx02  {
    print("执行User构造器")
  }

  def main(args: Array[String]): Unit = {
    var a = new User
    //执行Person构造器
    //执行Cmx构造器
    //执行cmx01构造器
    //执行cmx02构造器
    //执行User构造器
  }

对象混入trait

class Cmx() {
    def func(): Unit = {
      println("我是一个普通的类")
    }
  }

  trait Cmx01 {
    def func1(): Unit = {
      println("我是一个特质的类")
    }
  }

  def main(args: Array[String]): Unit = {
    var a = new Cmx with Cmx01
    a.func()
    a.func1()
    //我是一个普通的类
    //我是一个特质的类
  }

trait 也可以继承class

class Cmx() {
    def func(): Unit = {
      println("我是一个普通的类")
    }
  }

  trait Cmx01 extends Cmx {
    def func1(): Unit
  }

  class Test extends Cmx01 {
    override def func1(): Unit = {
      println("我是一个特质的实现")
    }
  }

  def main(args: Array[String]): Unit = {
    var a = new Test
    a.func()
    a.func1()
    //我是一个普通的类
    //我是一个特质的实现
  }

三、样例类

  定义:一种特殊的类,用来快速定义一个保存数据的类,类似与Java的实体,在后续spark,flink中及其重要

  回顾已经学过的类:类,单例对象,半生对象,抽象类,Trait类,样例类

  语法: case class 类名(属性名:属性类型...){...}        ##这种写法,属性值的修饰符 是 val  ,属性值不可变

      case class 类名(var 属性名:属性类型...){...}   ##这种写法 的属性值可以改变

  注意:样例类使用来存储数据用的,所以没有方法

case class Cmx(var name: String) {

  }

  def main(args: Array[String]): Unit = {
    var a = Cmx("cmx")
    println(a.name)
    //cmx
    a.name = "cmx01"
    println(a.name)
    //cmx01
  }

  样例类的隐含方法

  1.apply:快速创建对象,省去new关键字的书写

  2.toString:将对象的内容,自动转换成字符串显示;而普通的类默认输出的是这个对象的地址(包.单利对象$类名@16进制hash码)

//普通类,改写默认方法
  class Cmx(name: String) {
    override def toString: String = {
      return s"name= ${name}"
    }
  }

  //普通类,为改写默认方法
  class Cmx01(name: String) {}

  def main(args: Array[String]): Unit = {
    var a = new Cmx("cmx")
    var b = new Cmx01("cmx01")
    println(a.toString)
    //name= cmx
    println(b.toString)
    //   #@符号后的是十六进制的哈希码
    println(b.hashCode())
    //13648335   #这个方法返回的是十进制的哈希码
    println(Integer.toHexString(b.hashCode()))
    //d041cf    #结果和前面的一样
  }

  3.equals方法:可以进行样例类,内容的比较

    判断引用的方法eq()

    判断内容的方法 equals(),==

case class Cmx(name: String) {}

  def main(args: Array[String]): Unit = {
    var a = Cmx("cmx")
    var b = Cmx("cmx")
    println(a.equals(b))
    //true
    println(a.eq(b))
    //false
  }

  4.hascode方法:获取对象的哈希码,用于进行哈希操作,进行去重操作

    注意:每个对象都有哈希码,但是哈希码不能代表对象的唯一标识

       同一个对象的哈希码一定是相同的,不同对象的哈希码有可能是相同的

case class Cmx(name: String) {

  }

  def main(args: Array[String]): Unit = {

    var a = Cmx("cmx")
    var b = Cmx("cmx")
    println(a.hashCode())
    println(b.hashCode())
    println(a.eq(b))
    //结果验证样例类的哈希码和内容保持一致,说明样例类修改了原来类的hashCode()
    //-351660709
    //-351660709
    //false
  }

  5.copy方法:快速实现一个相同的对象(指的是数据内容相同)

case class Person(name: String, age: Int)

  def main(args: Array[String]): Unit = {
    var a = Person("cmx", 11)
    var b = a.copy("cmx01")
    print(b.toString)
    //Person(cmx01,11)
  }

四、样例对象

  语法: case object 对象名字

  定义枚举 : 一个类型 有有限的对象 (Sex Season ),在scala中通过 trait 和 样例对象 可以配合定义枚举类型

//性别 特质类
  trait Sex

  //样例对象 继承性别类
  case object Male extends Sex

  case object Female extends Sex

  //样例类 参数性别的类型是Sex
  case class Person(name: String, sex: Sex)


  def main(args: Array[String]): Unit = {
    var p = Person("suns", Male)
    var p1 = Person("liwj", Female)
  }

五、模式匹配

  1.基本匹配

  2.类型匹配

  3.if条件判断匹配 守卫

  4.样例类匹配

  5.集合匹配

//基本匹配
    var a = StdIn.readLine()
    a match {
      case "cmx" => println("cmx")
      case "cmx01" => println("cmx01")
      case _ => println("都不是")
    }
    //cmx
//类型匹配
    var a: Any = 10
    //模式匹配是可以有返回值的
    //可以用一个参数代表a的值, 借以使用
    var b = a match {
      case x: String => s"String${x}"
      case x: Int => s"Int${x.toString}"
    }
    //println(b)
    //Int10
//if 条件判断 守卫
    var a = 7
    a match {
      case _ if a >= 0 && a <= 3 => println("0---3")
      case _ if a >= 4 && a <= 8 => println("4---8")
      case _ => println("为匹配")
    }
    //4---8
//样例类匹配
    case class Cmx(name: String)
    case class Cmx01(age: Int)
    var m: Any = Cmx("cmx")
    var p: Any = Cmx01(20)
    p match {
      case Cmx(name) => println("cmx类")
      case Cmx01(age) => println("cmx01类")
    }
    //cmx01类
//集合匹配
    //三种形式
    /*
      List(1,_*):以1开头的列表
      List(1):只有1一个元素的列表
      List(1,x,y):以1 开头只有三个元素的列表
      */
    var a = List(1, 2, 3, 4)
    a match {
      case List(1, _*) => println("该列表是1以开头的")
      case List(1, x, y, z) => println("该列表共有4个元素")
      case List(1) => println("该列表只有1 一个元素")
    }
    //该列表是1以开头的

相关推荐