2021-05-08

Scala day04

伴生类和伴生对象的用法:静态工厂

package com.gc.scala1015day04
/**
  * Author guochao
  * Date 2021/5/8
  */
object Factory1 {
  def main(args: Array[String]): Unit = {
    println(Human.getHuman("黑色"))
    println(Human.getHuman("黑色"))



  }
}

object Human{

  val map = mutable.Map[String, Human](
    "黑色" -> new Human("黑色")
  )

  def getHuman(color: String) = map.getOrElseUpdate(color, new Human(color))
}

class Human private (color: String){

  println(s"$color.....")

  override def toString: String = s"人种: $color"
}
/*
1.伴生类和伴生对象可以互相访问对方的私有成员
2.编译成字节码之后, 伴生对象中的成员就是java中的静态成员, 伴生类中的成员, 就是java中的普通成员

*/

特质(trait)

特质声明

trait 特质名 {
trait体
}

特质基本语法

一个类具有某种特质(特征),就意味着这个类满足了这个特质(特征)的所有要素,所以在使用时,也采用了extends关键字,如果有多个特质或存在父类,那么需要采用with关键字连接。

  1. 基本语法:
    没有父类:class 类名 extends 特质1 with 特质2 with 特质3 …
    有父类:class 类名 extends 父类 with 特质1 with 特质2 with 特质3…
  2. 说明
    (1)类和特质的关系:使用继承的关系。
    (2)当一个类去继承特质时,第一个连接词是extends,后面是with。
    (3)如果一个类在继承特质和父类时,应当把父类写在extends后。
  3. (1)类和特质的关系:使用继承的关系。
    (2)当一个类去继承特质时,第一个连接词是extends,后面是with。
    (3)如果一个类在继承特质和父类时,应当把父类写在extends后。
  4. 案例实操
    (1)特质可以同时拥有抽象方法和具体方法
    (2)一个类可以混入(mixin)多个特质
    (3)所有的Java接口都可以当做Scala特质使用
    (4)动态混入:可灵活的扩展类的功能
    (4.1)动态混入:创建对象时混入trait,而无需使类混入该trait
    (4.2)如果混入的trait中有未实现的方法,则需要实现
trait PersonTrait {

  //(1)特质可以同时拥有抽象方法和具体方法
  // 声明属性
  var name: String = _

  // 抽象属性
  var age: Int

  // 声明方法
  def eat(): Unit = {
    println("eat")
  }

  // 抽象方法
  def say(): Unit
}

trait SexTrait {
  var sex: String
}

//(2)一个类可以实现/继承多个特质
//(3)所有的Java接口都可以当做Scala特质使用
class Teacher extends PersonTrait with java.io.Serializable {

  override def say(): Unit = {
    println("say")
  }

  override var age: Int = _
}


object TestTrait {

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

    val teacher = new Teacher

    teacher.say()
    teacher.eat()

    //(4)动态混入:可灵活的扩展类的功能
    val t2 = new Teacher with SexTrait {
      override var sex: String = "男"
    }

    //调用混入trait的属性
    println(t2.sex)
  }
}
package com.gc.scala1015day04
/**
* Author guochao
* Date 2021/5/8
*/
object Trait1 {
  def main(args: Array[String]): Unit = {
    val usb: Logger = new HuaweiUsb
    usb.insert
    usb.work
    usb.print()

  }
}

class Logger{
  println("logger 类的构造器")
  def print() = {
    println("开始打印日志...")
  }
}

trait Usb{
  println("USB的构造器 第一个混入的")
  // 抽象字段
  val name: String
  def insert: Unit
  def work: Unit
  def pop: Unit

  def init()= {
    println(s" $name 开始初始化...")
  }
}
trait MyException{
  println("MyException 的构造器  第二个混入的")
  def thowExec: Exception// 抽象字段
}
class HuaweiUsb extends Logger with MyException with Usb {
  println("HuaweiUSB类的构造器  子类")
  override val name: String = "huawei"

  override def insert: Unit = {
    println("华为 usb开始插入...")
    init()
  }

  override def work: Unit =
    println("华为 usb开始工作...")

  override def pop: Unit =
    println("华为 usb退出工作...")

  override def thowExec: Exception = new RuntimeException("华为的usb在抛异常")
}
package com.gc.scala1015day04
/**
* Author guochao
* Date 2021/5/8
*/
object Trait2 {
  def main(args: Array[String]): Unit = {
    /*val abc = new ABC
    abc.foo()*/
    val my:A = new My with A with B with C
    my.foo()
  }
}

class ABC extends A with B with C{
  override def foo() = {
    super.foo()  //
    println("ABC ...")
  }
}
trait A{
  def foo() = {
    println("A ...")
  }
}
trait B extends A{
  override def foo() = {
    println("B ...")
  }
}
trait C extends A{
  override def foo() = {
    super[A].foo()
    println("C ...")
  }
}
/*
1.如果一个类混入的特质中有相同的实现好的方法, 则会产生成员冲突
2.可以使用菱形的继承结构解决冲突问题, 冲突解决之后, 方法谁最后混入的那个
3.super[A] super具体指代
4.动态混入(叠加)

*/
package com.gc.scala1015day04
/**
* Author guochao
* Date 2021/5/8
*/
object Trait3 {
  def main(args: Array[String]): Unit = {
    val sub = new Sub
    sub.f()
    sub.foo()
  }
}

class Father {
  def f() = println("father... f")
}

class My1 extends Father

//trait F extends Exception
trait F {
  // 自身类型 self 是一个变量名, 可以通过这个名字取调用father中方法
  self: Father => // trait F extends Father
  def foo() = {
    //        self.f()
    this.f()
  }
}

//如果要成功, 则My要么是Exception, 要么是Exception的子类
class Sub extends My1 with F

扩展

类型转换
  1. 说明
    (1)obj.isInstanceOf[T]:判断obj是不是T类型。
    (2)obj.asInstanceOf[T]:将obj强转成T类型。
    (3)classOf获取对象的类名。

  2. 案例实操

class Person{

}

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

        val person = new Person

        //(1)判断对象是否为某个类型的实例
        val bool: Boolean = person.isInstanceOf[Person]

        if ( bool ) {
            //(2)将对象转换为某个类型的实例
            val p1: Person = person.asInstanceOf[Person]
            println(p1)
        }

        //(3)获取类的信息
        val pClass: Class[Person] = classOf[Person]
        println(pClass)
    }
}
枚举类和应用类
  1. 说明
    枚举类:需要继承Enumeration
    应用类:需要继承App

  2. 案例实操

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

        println(Color.RED)
    }
}

// 枚举类
object Color extends Enumeration {
    val RED = Value(1, "red")
    val YELLOW = Value(2, "yellow")
    val BLUE = Value(3, "blue")
}

// 应用类
object Test20 extends App {
    println("xxxxxxxxxxx");
}

隐式

  1. 隐式转换函数
    implicit def double2Int(d: Double) = d.toInt
    不看函数名, 只看参数和返回值类型

    将来可以给已有的类增加功能!

  2. 隐式类
    implicit class RichFile(file: File) {
    def readContent: String = {
    Source.fromFile(file, “utf-8”).mkString
    }
    }

    1. 不能顶级
    2. 柱构造必须有参数

    2.10新增的, 是对隐式转换函数的一个封装. 简化隐式转换函数的使用.
    spark里面, 其实还是隐式转换函数用的比较多

    可以把隐式当做一个普通的类使用!!!

  3. 隐式参数和隐式值
    隐式参数是指的给函数的参数添加隐式关键字

    implicit val aa = 100

    def foo(implicit a: Int)

    当调用函数的时候, 如果不传参数, 并且省略括号, 就会找隐式值!(只看类型,不看名字)

    如果定义了隐式参数, 则整个参数列表中所有的参数都是隐式参数

package com.gc.scala1015day04
/**
* Author guochao
* Date 2021/5/8
*/
import java.time.LocalDate

object Implicit3 {
  def main(args: Array[String]): Unit = {
    implicit def int2RichDate(day: Int) = new RichDate(day)

    //  2 days ago  计算2天前是哪一天
    val ago = "ago"
    val later = "later"
    //        val r = 2 days ago
    val r = 100.days(later)
    println(r)   // 2020-03-04
    // 4 days later 计算4天后是哪一天
  }
}

class RichDate(day: Int) {
  def days(when: String) = {
    if("ago"==when)
      LocalDate.now().plusDays(-day).toString
      LocalDate.now().minusDays(day)
    else{
      LocalDate.now().plusDays(day).toString
    }
  }
}

定长数组

package com.gc.scala1015day04
/**
* Author guochao
* Date 2021/5/8
*/
object Array1 {
  def main(args: Array[String]): Unit = {
     val arr: Array[Int] = Array[Int](1, 2, 3, 4)
    println(arr(0))
    arr(0) = 100
    println(arr.mkString(", "))
    // 遍历数组 for while
       val arr1: Array[Int] = arr :+ 100  // arr.:+(100)
       val arr1 = 100 +: arr  // ====  arr.+:(100)
       val arr1 = arr.+:(100)


     println(arr1.mkString(", "))

      val arr1 = Array(30, 50, 70, 60, 10, 20)
      val arr2 = Array(3, 5, 7, 6, 1, 2)
      val arr3: Array[Int] = arr1 ++ arr2   // === arr1.++(arr2)
      myPrint(arr3)
      val arr1 = Array(30, 50, 70, 60, 10, 20)

  }
  def myPrint(any: Traversable[_]): Unit = {
    println(any.mkString(", "))
  }
}
/*
<> : 给xml, scala语言级别的支持xml
[]:给了泛型
(index): 访问指定索引的元素

scala没有自己定义数组, 底层就是java的数组
定长数组
创建数组;

直接通过给数组初始化元素的方式创建数组
:+ 一般用于给不可变的集合添加单个元素在末尾 (+)
+: 一般用于给不可变的集合加单个元素到头部 (+)
++ 合并连个集合

运算符的结合性:
1 + 2 左结合
+2 右集合
a = 3 右集合
只要运算符是以: 结尾就是右结合运算符

*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值