@Scala
day04
静态工厂
- 伴生类和伴生对象可以互相访问对方的私有成员!!!
- 编译成字节码之后, 伴生对象中的成员就是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在抛异常")
}
- 如果一个类混入的特质中有相同的实现好的方法, 则会产生成员冲突
- 可以使用菱形的继承结构解决冲突问题, 冲突解决之后, 方法谁最后混入的那个
- super[A] super具体指代
- 动态混入(叠加)
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的子类
-
class Sub extends My with F
-
对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): 访问指定索引的元素
-
scala没有自己定义数组, 底层就是java的数组
定长数组 -
创建数组;
- 直接通过给数组初始化元素的方式创建数组
:+ 一般用于给不可变的集合添加单个元素在末尾 (+)
+: 一般用于给不可变的结集合加单个元素到头部 (+)
++ 合并连个集合
运算符的结合性:
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)
}*/
}
/*
隐式实体的查找路径
隐式查找的路径问题:
- 先在当前作用域
- 再去相关类型(包含泛型的伴生对象)的伴生对象中去找
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): 访问指定索引的元素
-
scala没有自己定义数组, 底层就是java的数组
定长数组 -
创建数组;
- 直接通过给数组初始化元素的方式创建数组
:+ 一般用于给不可变的集合添加单个元素在末尾 (+)
+: 一般用于给不可变的结集合加单个元素到头部 (+)
++ 合并连个集合
运算符的结合性:
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(", "))
}
}