Scala高级语法

131 阅读6分钟

柯里化

柯里化是一个过程
把一个参数列表中的多个参数, 转换为多个参数列表
科里化可以支持隐式转换
[Scala] 纯文本查看 复制代码
?

object Currying {
"正常方法"
def m1(a: Int, b: Int): Int = a + b

"柯里化方法"
def m2(a: Int)(b: Int) = a + b
def m3(a: Int)(b: Int, c: Int) = a + b + c
def m4(a: Int, b: Int)(c: Int, d: Int) = a + b + c + d

def main(args: Array[String]): Unit = {
println("正常方法调用:" + m1(10, 20))
println("柯里化方法调用:" + m2(10)(20))
println("柯里化方法调用:" + m3(10)(20, 30))
println("柯里化方法调用:" + m4(10, 20)(30, 40))
}
}

隐式参数

用 implicit 关键字修饰的参数,就是隐式参数
隐式参数的值从哪儿取
从上下文环境中,最多找到一个和隐式参数类型一致,且用implicit修饰的变量,如果找到多个则报错
如果上下文环境中没有,则使用默认值
如果找不到,也没有默认值,则报错
implicit 只能作用于最后一个参数列表,一个参数列表中只能由一个 implicit 关键字
关键字只能放在最后一个参数列表中,而且修饰该参数列表中的所有参数
[Scala] 纯文本查看 复制代码
?

object ImpDemo {
implicit val defalut1: Int = 20
// implicit val defalut2: Int = 30
implicit val defalut3: Double = 10

def m1(a: Int)(implicit b: Int = 10): Int = {
if (a > b) a else b
}

def m2(a: Int)(implicit b: Int, c: Double): Double = a + b + c

def main(args: Array[String]): Unit = {
println(m1(5))
println(m1(5)(30))
println(m2(10))
}
}

隐式转换

主要指隐式方法和隐式函数
[Scala] 纯文本查看 复制代码
?

object ImpMethod {
implicit def str2int(str: String): Int = Integer.parseInt(str)

def main(args: Array[String]): Unit = {
println(1 to 3)
"这里发生了隐式转换,这里调用了RichInt的方法"
"implicit 修饰的方法,方法参数是Int,返回值是RichInt"
"当Int 类型上调用to方法,Int上没有这个方法,但是RichInt上有,发现有隐式方法从Int->RichRint"
println(1.to(3))
val x: Int = "123"
println(x)
}
}

[Scala] 纯文本查看 复制代码
?

import java.io.File
import scala.io.Source
class RichFile(f: File) {
def read(): String = Source.fromFile(f).getLines().mkString("rn");
}
object RichFile {
// 隐式转换
implicit def file2RichFile(f: File): RichFile = new RichFile(f)
def main(args: Array[String]): Unit = {
val path: String = "C:/Users/unkonw_yu/Desktop/scala/rating.json"
val f = new File(path)
val lines = f.read()
println(lines)
}
}

如果隐式方法和隐式函数都存在,优先使用函数
[Scala] 纯文本查看 复制代码
?

class RichFile(f: File) {
def read(): String = Source.fromFile(f).getLines().mkString("rn");
}
object RichFile {
// 隐式转换
implicit def file2RichFile(f: File): RichFile = new RichFile(f)
implicit val file2RichFile2 = (f: File) => {
println("调用函数")
new RichFile(f)
}
def main(args: Array[String]): Unit = {
val path: String = "C:/Users/unkonw_yu/Desktop/scala/rating.json"
val f = new File(path)
val lines = f.read()
println(lines)
}
}

可以导入外部的隐式转换 ,类和object导入方式不一样
[Scala] 纯文本查看 复制代码
?
import java.io.File
class MyImpl {
implicit def file2RichFile(f: File): RichFile = new RichFile(f)
}
object MyImpl {
implicit def file2RichFile(f: File): RichFile = new RichFile(f)
}

[Scala] 纯文本查看 复制代码
?
class RichFile(f: File) {
def read(): String = Source.fromFile(f).getLines().mkString("rn");
}
object RichFile {
"引入 object 的隐式方法"
import MyImpl.file2RichFile

"引入 class 的隐式方法"
private val imp = new MyImpl
import imp.file2RichFile

def main(args: Array[String]): Unit = {
val path: String = "C:/Users/unkonw_yu/Desktop/scala/rating.json"
val f = new File(path)
val lines = f.read()
println(lines)
}
}

泛型

[Scala] 纯文本查看 复制代码
?

abstract class MessageT {
def getMsg(): T = msg
}
class IntMsg(msg: Int) extends Message(msg)
class StrMsg(msg: String) extends Message(msg)

object TestMsg {
def main(args: Array[String]): Unit = {
val msg1 = new IntMsg(123)
println(msg1.getMsg())
val msg2 = new StrMsg("hello")
println(msg2.getMsg())
}
}

[Scala] 纯文本查看 复制代码
?
class ClothesColorTypes

"枚举"
object ColorTypes extends Enumeration {
type CT = Value
val RED = Value(0)
val BLACK = Value(1)
val GREEN = Value(2)
}

object TestMsg {
def main(args: Array[String]): Unit = {
val colthes1 = new ClothesColorTypes.Value
val colthes2 = new ClothesCT
println(colthes1.color)
println(colthes2.color)
}
}

比较器

Java 中的比较器
Comparable
Comparator
scala中的比较器
Ordered --> Comparable
Ordering --> Comparator
[Scala] 纯文本查看 复制代码
?
import java.util
import java.util.Collections

class Student(val name: String, val age: Int, val fv: Int) extends Ordered[Student] {
override def compare(that: Student): Int = this.fv - that.fv
override def toString: String = s"

{age},${fv}"
}

object Student {
def main(args: Array[String]): Unit = {
val sList = new util.ArrayList[Student]()

val s1 = new Student("zs",23,999)
val s2 = new Student("li",24,998)
val s3 = new Student("ww",25,997)

sList.add(s1)
sList.add(s2)
sList.add(s3)

Collections.sort(sList)
println(sList)

Collections.sort(sList,new Ordering[Student]{
override def compare(x: Student, y: Student): Int = y.fv - x.fv
})
println(sList)
}
}

泛型约束上界

Java
<T extends P>
<? extends P>
Scala
T <: P
[Scala] 纯文本查看 复制代码
?
任意类型比较"
class ComparTestT {
def myEquals() = t1 == t2
}
"Comparable 的子类"
class ComparaTest2[T <: Ordered[T]](t1: T, t2: T) {
def myEquals() = t1 compareTo t2
}
object ComparTest {
def main(args: Array[String]): Unit = {
val s1 = new Student("zs", 23, 999)
val s2 = new Student("li", 24, 998)

val comp1 = new ComparTestStudent
println(comp1.myEquals())
val comp2 = new ComparTestInt
println(comp2.myEquals())

"报错,Int没有混入Ordered特质"
val comp3 = new ComparaTest2Int
println(comp3.myEquals())

"正常运行"
val comp4 = new ComparaTest2Student
println(comp4.myEquals())
}
}

下界

[Scala] 纯文本查看 复制代码
?
object LowerBounds {
val f1 = (x: Int, y: Int) => x + y
val f2 = (a: AnyVal, b: AnyVal) => a.asInstanceOf[Int] + b.asInstanceOf[Int]
val f3 = (a: Any, b: Any) => a
val f4 = (a: Any, b: AnyRef) => a
val f5 = (a: AnyRef, b: AnyRef) => a

def main(args: Array[String]): Unit = {
val arr = Array(1, 3, 5, 7, 9)
// def reduce[A1 >: A]
val res1 = arr.reduce(_ + _)
val res2 = arr.reduce(f1)
// AnyVal 是 Int 的父类,可以传递
val res3 = arr.reduce(f2)
// Any 是 Int 的顶级父类,可以传递
val res4 = arr.reduce(f3)

// AnyRef 不是 Int 的父类,调用失败
// val res5 = arr.reduce(f4)
// val res6 = arr.reduce(f5)
}
}

协变逆变

[XML] 纯文本查看 复制代码
?
[T] 正常的泛型 不变
[T <: Test] 上界
[T >: Test] 下界
[+T] 协变
[-T] 逆变

[Scala] 纯文本查看 复制代码
?
class Card[T] {}
class Card[+T] {}
class Card[-T] {}

class Metting[T] {
def metting(c: Card[T]): Unit = println("人们代表大会")
}

// 层级关系
class ChangWei

class Leader extends ChangWei

class Flower extends Leader

object Card {
def main(args: Array[String]): Unit = {
val metting = new Metting[ChangWei]()

val changweiCart = new Card[ChangWei]
val leaderCart = new Card[Leader]
val flowerCart = new Card[Flower]

"class Card[T]"
metting.metting(changweiCart)
"下面的会报错"
// metting.metting(leaderCart)
// metting.metting(flowerCart)

"class Cart[+T],都不会报错"
metting.metting(changweiCart)
metting.metting(leaderCart)
metting.metting(flowerCart)

"class Cart[-T]"
val leaderMetting = new Metting[Leader]
leaderMetting.metting(changweiCart)
leaderMetting.metting(leaderCart)
"下面代码会报错"
// leaderMetting.metting(flowerCart)
}
}

CallByName 和 CallByValue

函数调用中的两种形式
CallByName(传名调用)
传递的参数,在调用的时候才会真正的执行
CallByValue(传值调用)
先计算调用的结果,然后再传递
[Scala] 纯文本查看 复制代码柯里化
柯里化是一个过程
把一个参数列表中的多个参数, 转换为多个参数列表
科里化可以支持隐式转换
[Scala] 纯文本查看 复制代码
?
object Currying {
"正常方法"
def m1(a: Int, b: Int): Int = a + b

"柯里化方法"
def m2(a: Int)(b: Int) = a + b
def m3(a: Int)(b: Int, c: Int) = a + b + c
def m4(a: Int, b: Int)(c: Int, d: Int) = a + b + c + d

def main(args: Array[String]): Unit = {
println("正常方法调用:" + m1(10, 20))
println("柯里化方法调用:" + m2(10)(20))
println("柯里化方法调用:" + m3(10)(20, 30))
println("柯里化方法调用:" + m4(10, 20)(30, 40))
}
}

隐式参数
用 implicit 关键字修饰的参数,就是隐式参数
隐式参数的值从哪儿取
从上下文环境中,最多找到一个和隐式参数类型一致,且用implicit修饰的变量,如果找到多个则报错
如果上下文环境中没有,则使用默认值
如果找不到,也没有默认值,则报错
implicit 只能作用于最后一个参数列表,一个参数列表中只能由一个 implicit 关键字
关键字只能放在最后一个参数列表中,而且修饰该参数列表中的所有参数
[Scala] 纯文本查看 复制代码
?

object ImpDemo {
implicit val defalut1: Int = 20
// implicit val defalut2: Int = 30
implicit val defalut3: Double = 10

def m1(a: Int)(implicit b: Int = 10): Int = {
if (a > b) a else b
}

def m2(a: Int)(implicit b: Int, c: Double): Double = a + b + c

def main(args: Array[String]): Unit = {
println(m1(5))
println(m1(5)(30))
println(m2(10))
}
}

隐式转换
主要指隐式方法和隐式函数
[Scala] 纯文本查看 复制代码
?
object ImpMethod {
implicit def str2int(str: String): Int = Integer.parseInt(str)

def main(args: Array[String]): Unit = {
println(1 to 3)
"这里发生了隐式转换,这里调用了RichInt的方法"
"implicit 修饰的方法,方法参数是Int,返回值是RichInt"
"当Int 类型上调用to方法,Int上没有这个方法,但是RichInt上有,发现有隐式方法从Int->RichRint"
println(1.to(3))
val x: Int = "123"
println(x)
}
}

[Scala] 纯文本查看 复制代码
?
import java.io.File
import scala.io.Source
class RichFile(f: File) {
def read(): String = Source.fromFile(f).getLines().mkString("rn");
}
object RichFile {
// 隐式转换
implicit def file2RichFile(f: File): RichFile = new RichFile(f)
def main(args: Array[String]): Unit = {
val path: String = "C:/Users/unkonw_yu/Desktop/scala/rating.json"
val f = new File(path)
val lines = f.read()
println(lines)
}
}

如果隐式方法和隐式函数都存在,优先使用函数
[Scala] 纯文本查看 复制代码
?
class RichFile(f: File) {
def read(): String = Source.fromFile(f).getLines().mkString("rn");
}
object RichFile {
// 隐式转换
implicit def file2RichFile(f: File): RichFile = new RichFile(f)
implicit val file2RichFile2 = (f: File) => {
println("调用函数")
new RichFile(f)
}
def main(args: Array[String]): Unit = {
val path: String = "C:/Users/unkonw_yu/Desktop/scala/rating.json"
val f = new File(path)
val lines = f.read()
println(lines)
}
}

可以导入外部的隐式转换 ,类和object导入方式不一样
[Scala] 纯文本查看 复制代码
?

import java.io.File
class MyImpl {
implicit def file2RichFile(f: File): RichFile = new RichFile(f)
}
object MyImpl {
implicit def file2RichFile(f: File): RichFile = new RichFile(f)
}

[Scala] 纯文本查看 复制代码
?
class RichFile(f: File) {
def read(): String = Source.fromFile(f).getLines().mkString("rn");
}
object RichFile {
"引入 object 的隐式方法"
import MyImpl.file2RichFile

"引入 class 的隐式方法"
private val imp = new MyImpl
import imp.file2RichFile

def main(args: Array[String]): Unit = {
val path: String = "C:/Users/unkonw_yu/Desktop/scala/rating.json"
val f = new File(path)
val lines = f.read()
println(lines)
}
}

泛型
[Scala] 纯文本查看 复制代码
?
abstract class MessageT {
def getMsg(): T = msg
}
class IntMsg(msg: Int) extends Message(msg)
class StrMsg(msg: String) extends Message(msg)

object TestMsg {
def main(args: Array[String]): Unit = {
val msg1 = new IntMsg(123)
println(msg1.getMsg())
val msg2 = new StrMsg("hello")
println(msg2.getMsg())
}
}

[Scala] 纯文本查看 复制代码
?
class ClothesColorTypes

"枚举"
object ColorTypes extends Enumeration {
type CT = Value
val RED = Value(0)
val BLACK = Value(1)
val GREEN = Value(2)
}

object TestMsg {
def main(args: Array[String]): Unit = {
val colthes1 = new ClothesColorTypes.Value
val colthes2 = new ClothesCT
println(colthes1.color)
println(colthes2.color)
}
}

比较器
Java 中的比较器
Comparable
Comparator
scala中的比较器
Ordered --> Comparable
Ordering --> Comparator
[Scala] 纯文本查看 复制代码
?
import java.util
import java.util.Collections

class Student(val name: String, val age: Int, val fv: Int) extends Ordered[Student] {
override def compare(that: Student): Int = this.fv - that.fv
override def toString: String = s"

{age},${fv}"
}

object Student {
def main(args: Array[String]): Unit = {
val sList = new util.ArrayList[Student]()

val s1 = new Student("zs",23,999)
val s2 = new Student("li",24,998)
val s3 = new Student("ww",25,997)

sList.add(s1)
sList.add(s2)
sList.add(s3)

Collections.sort(sList)
println(sList)

Collections.sort(sList,new Ordering[Student]{
override def compare(x: Student, y: Student): Int = y.fv - x.fv
})
println(sList)
}
}

泛型约束上界
Java
<T extends P>
<? extends P>
Scala
T <: P
[Scala] 纯文本查看 复制代码
?
任意类型比较"
class ComparTestT {
def myEquals() = t1 == t2
}
"Comparable 的子类"
class ComparaTest2[T <: Ordered[T]](t1: T, t2: T) {
def myEquals() = t1 compareTo t2
}
object ComparTest {
def main(args: Array[String]): Unit = {
val s1 = new Student("zs", 23, 999)
val s2 = new Student("li", 24, 998)

val comp1 = new ComparTestStudent
println(comp1.myEquals())
val comp2 = new ComparTestInt
println(comp2.myEquals())

"报错,Int没有混入Ordered特质"
val comp3 = new ComparaTest2Int
println(comp3.myEquals())

"正常运行"
val comp4 = new ComparaTest2Student
println(comp4.myEquals())
}
}

下界
[Scala] 纯文本查看 复制代码
?
object LowerBounds {
val f1 = (x: Int, y: Int) => x + y
val f2 = (a: AnyVal, b: AnyVal) => a.asInstanceOf[Int] + b.asInstanceOf[Int]
val f3 = (a: Any, b: Any) => a
val f4 = (a: Any, b: AnyRef) => a
val f5 = (a: AnyRef, b: AnyRef) => a

def main(args: Array[String]): Unit = {
val arr = Array(1, 3, 5, 7, 9)
// def reduce[A1 >: A]
val res1 = arr.reduce(_ + _)
val res2 = arr.reduce(f1)
// AnyVal 是 Int 的父类,可以传递
val res3 = arr.reduce(f2)
// Any 是 Int 的顶级父类,可以传递
val res4 = arr.reduce(f3)

// AnyRef 不是 Int 的父类,调用失败
// val res5 = arr.reduce(f4)
// val res6 = arr.reduce(f5)
}
}

协变逆变
[XML] 纯文本查看 复制代码
?
[T] 正常的泛型 不变
[T <: Test] 上界
[T >: Test] 下界
[+T] 协变
[-T] 逆变

[Scala] 纯文本查看 复制代码
?
class Card[T] {}
class Card[+T] {}
class Card[-T] {}

class Metting[T] {
def metting(c: Card[T]): Unit = println("人们代表大会")
}

// 层级关系
class ChangWei

class Leader extends ChangWei

class Flower extends Leader

object Card {
def main(args: Array[String]): Unit = {
val metting = new Metting[ChangWei]()

val changweiCart = new Card[ChangWei]
val leaderCart = new Card[Leader]
val flowerCart = new Card[Flower]

"class Card[T]"
metting.metting(changweiCart)
"下面的会报错"
// metting.metting(leaderCart)
// metting.metting(flowerCart)

"class Cart[+T],都不会报错"
metting.metting(changweiCart)
metting.metting(leaderCart)
metting.metting(flowerCart)

"class Cart[-T]"
val leaderMetting = new Metting[Leader]
leaderMetting.metting(changweiCart)
leaderMetting.metting(leaderCart)
"下面代码会报错"
// leaderMetting.metting(flowerCart)
}
}

CallByName 和 CallByValue
函数调用中的两种形式
CallByName(传名调用)
传递的参数,在调用的时候才会真正的执行
CallByValue(传值调用)
先计算调用的结果,然后再传递
[Scala] 纯文本查看 复制代码
?
object CallByNameAndValue {
def getCurTime() ={
println("调用 method")
System.currentTimeMillis()
}
def callByValie (time:Long): Long = {
println("call by value")
time
}
def callByName(time: => Long): Long = {
println("call by name")
time
}
def main(args: Array[String]): Unit = {
"先执行getCurTime获取当前时间,然后传递给callByValue方法"
callByValie(getCurTime())
"先执行callByName方法,当需要用到参数的时候,才取计算结果"
callByName(getCurTime())
}
}
?

object CallByNameAndValue {
def getCurTime() ={
println("调用 method")
System.currentTimeMillis()
}
def callByValie (time:Long): Long = {
println("call by value")
time
}
def callByName(time: => Long): Long = {
println("call by name")
time
}
def main(args: Array[String]): Unit = {
"先执行getCurTime获取当前时间,然后传递给callByValue方法"
callByValie(getCurTime())
"先执行callByName方法,当需要用到参数的时候,才取计算结果"
callByName(getCurTime())
}
}