2021-05-02

@Scala

day04

静态工厂

  1. 伴生类和伴生对象可以互相访问对方的私有成员!!!
  2. 编译成字节码之后, 伴生对象中的成员就是java中的静态成员, 伴生类中的成员, 就是java中的普通成员
    */

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

package com.syf.scala1015day04
/**
  * Author Amily
  * Date 2021/5/2
  */
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"
}

trait

/*
java:

静态 (伴生对象中的)
抽象类
内部类
接口(1.7 常量和抽象方法)
1.8 默认方法
scala:
trait
scala没有提供接口, 但是提供了一个更加强大的: trait 特质
将来一定会有接口,

1. 抽象类中有的东西, trait都可以有.
        抽象类是类, 所以只能单继承
        trait 可以多继承

2. 当类继承类和trail, 对前面用extends, 后面的统一用with(混入)

*/

package com.syf.scala1015day04
/**
* Author Amily
* Date 2021/4/25
**/
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在抛异常")
}

  1. 如果一个类混入的特质中有相同的实现好的方法, 则会产生成员冲突
  2. 可以使用菱形的继承结构解决冲突问题, 冲突解决之后, 方法谁最后混入的那个
  3. super[A] super具体指代
  4. 动态混入(叠加)
package com.syf.scala1015day04
/**
* Author Amily
* Date 2021/4/25
**/
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 My


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 ...")
  }
}

如果要成功, 则My要么是Exception, 要么是Exception的子类

  1. class Sub extends My with F

  2. 对trait使用另外一种更加优雅的语法, 来替换掉让trait继承类
    自身类型. 类型实现了java的依赖注入的功能

package com.syf.scala1015day04
/**
* Author Amily
* Date 2021/4/25
**/
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

类型转换

类型转换:
java:
判断 obj instanceof 类型
类型转换 (类型)obj

scala:
   判断 bb.isInstanceOf[BB]

   类型转换   bb.asInstanceOf[AA]


实际开发的时候, 一般不用这么low的方式, 将来会有更好的: 模式匹配

枚举类的几种实现

<> : 给xml, scala语言级别的支持xml   <user> </user>

[]:给了泛型
(index): 访问指定索引的元素

  1. scala没有自己定义数组, 底层就是java的数组
    定长数组

  2. 创建数组;

    1. 直接通过给数组初始化元素的方式创建数组

:+ 一般用于给不可变的集合添加单个元素在末尾 (+)
+: 一般用于给不可变的结集合加单个元素到头部 (+)
++ 合并连个集合

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

package com.syf.scala1015day04
/**
* Author Amily
* Date 2021/4/25
**/

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(", "))
  }
}

隐式

隐式转换函数的基本使用

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

    将来可以给已有的类增加功能!
package com.syf.scala1015day04
/**
* Author Amily
* Date 2021/4/25
**/
object Implicit1 {
  implicit def double2Int(d: Double) = d.toInt
  def main(args: Array[String]): Unit = {

    val a: Int = 10.1
    val b : Int = 20.2
    println(a)
    println(b)
  }
}

扩展现有类

package com.syf.scala1015day04
import java.io.File
/**
* Author Amily
* Date 2021/4/25
**/
import scala.io.Source
object Implicit2 {
  def main(args: Array[String]): Unit = {
    implicit def file2RichFile(file: File): RichFile = new RichFile(file)

    val content: String = new File("C:\\Users\\lzc\\Desktop\\class_code\\2019_10_15\\01_scala\\scala1015\\src\\main\\scala\\com\\atguigu\\scalal1015\\day04\\implicitdemo\\Implicit2.scala")
      .readContent
    println(content)
  }
}

class RichFile(file: File) {
  def readContent: String = {
    Source.fromFile(file, "utf-8").mkString
  }
}

隐式类

package com.syf.scala1015day04
/**
* Author Amily
* Date 2021/4/25
**/
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.syf.scala1015day04

import java.io.File

import scala.io.Source

/**
* Author Amily
* Date 2021/4/25
**/
object Implicit4 {
  def main(args: Array[String]): Unit = {

    val content: String = new File("C:\\Users\\lzc\\Desktop\\class_code\\2019_10_15\\01_scala\\scala1015\\src\\main\\scala\\com\\atguigu\\scalal1015\\day04\\implicitdemo\\Implicit4.scala")
      .readContent
    println(content)
  }

  // 隐式类必须是内部类
  implicit class RichFile(file: File) {
    def readContent: String = {
      Source.fromFile(file, "utf-8").mkString
    }

  }
}

隐式参数和隐式值,隐式值和默认值的区别

隐式转换

 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.syf.scala1015day04
/**
* Author Amily
* Date 2021/4/25
**/
object Implicit5 {
  implicit val aa = 100
  //    implicit val bb: Double = 200

  def main(args: Array[String]): Unit = {
    //        foo(10, 100)
    //        foo

    //        foo(2)

    foo  /// 先隐式值, 没有了再去默认值
    foo()  // 默认值
  }

  def foo(implicit a: Int = 10) = {
    println(a)
  }


  /*def foo(a: Int)(implicit b: Int, c: Double) = {
      println(a + b + c)
  }*/

  /*// a就是隐式参数
  def foo(implicit a: Int, b: Double) = {
      println(a)
  }*/
}

/*

隐式实体的查找路径

隐式查找的路径问题:

  1. 先在当前作用域
  2. 再去相关类型(包含泛型的伴生对象)的伴生对象中去找
package com.syf.scala1015day04
/**
* Author Amily
* Date 2021/4/25
**/
object A{
  /* implicit def b2a(b: B) = {
       println("A 的伴生对象")
       new A
   }*/
}
class A

object B{
  implicit def b2a(b: B) ={
    println("B 的伴生对象")
    new A
  }
}
class B

object Implicit6 {
  /*implicit def b2a(b: B) = {
      println("当前作用域")
      new A
  }*/
  def main(args: Array[String]): Unit = {
    //        val a: A = new B()

  }
}


从冥界召唤隐式值、

package com.syf.scala1015day04
/**
* Author Amily
* Date 2021/4/25
**/
object Implicit7 {
  implicit val a: Int = 10

  def main(args: Array[String]): Unit = {
    /*val b: Int = implicitly[Int]
    println(b)*/
    foo
    foo(implicitly[Int])
  }

  def foo(implicit a:Int ) = println(a)
}

定长数组

<> : 给xml, scala语言级别的支持xml
[]:给了泛型
(index): 访问指定索引的元素

  1. scala没有自己定义数组, 底层就是java的数组
    定长数组

  2. 创建数组;

    1. 直接通过给数组初始化元素的方式创建数组

:+ 一般用于给不可变的集合添加单个元素在末尾 (+)
+: 一般用于给不可变的结集合加单个元素到头部 (+)
++ 合并连个集合

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

package com.syf.scala1015day04

/**
* Author Amily
* Date 2021/4/25
**/
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(", "))
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值