@Scala
day07
变量和循环中的模式匹配`
package com.syf.scala1015day07
/**
* Author Amily
* Date 2021/5/18
*/
object Pattern1 {
def main(args: Array[String]): Unit = {
// val (a,b):(Int,String)=foo()
// println(a)
// println(b)
// val Array(a,b,rest@_*)=foo1
// println(a)
// println(b)
// println(rest)
val list:List[(Int,Int)]=List((1,2),(10,20),(100,200))
// for (kv<- list){
// println(kv._1)
// }
for((k,v)<-list){
println(k)
}
}
def foo():(Int,String)=(10,"lisi")
def foo1:Array[Int]=Array(1,2,3,4,5)
}
偏函数
用一对大括号括起来的一个或多个case语句就是偏函数
package com.syf.scala1015day07
/**
* Author Amily
* Date 2021/5/18
*/
object Pattern2 {
def main(args: Array[String]): Unit = {
val list:List[Any]=List(10,20,1,"aa",false)
val f= new PartialFunction[Any,Int] {
//只对返回值是true的那些元素进行处理,是false的跳过
//是true的时候交给apply进行处理
override def isDefinedAt(x: Any): Boolean =x.isInstanceOf[Int]
override def apply(v1: Any): Int =v1.asInstanceOf[Int]
}
//等价于 filter+map
val a:List[Int]=list.collect(f)
println(a)
}
}
偏函数使用注意的地方
偏函数使用的地方很多,但是大部分情况都是把他变成一个普通的函数莱使用,
package com.syf.scala1015day07
/**
* Author Amily
* Date 2021/5/18
*/
object Pattern3 {
def main(args: Array[String]): Unit = {
val list:List[Any]=List(10,20,1,"aa",false)
val list2:List[Int]=list.collect({
case a:Int=>a
})
println(list2)
}
}
如果函数的参数是元组的时候,喜欢使用偏函数
使用的策略
当传递的函数只有一个参数,并且这个参数是元组的时候,才使用偏函数
package com.syf.scala1015day07
/**
* Author Amily
* Date 2021/5/18
*/
object Pattern4 {
def main(args: Array[String]): Unit = {
//val map :Map[String,Int]=Map("a"->97,"b"->98,"c"->99)
// map.foreach(x=>{
// println(x._1)
// println(x._2)
// })
// map.foreach({
// case (k,v)=> println(k)
// })
val list:List[(String,(String,(Int,String)))]=List(
("a",("b",(1,"c"))),
("aa",("bb",(2,"cc"))))
val list2= list.map({
case (a,(b,(c,d)))=> c
})
println(list2)
// val r:Int=foo{
// case (x,y)=>x+y
// }
// println(r)
val r:Int=foo((x,y)=>{
x+y
})
println(r)
}
def foo(f:(Int,Int)=>Int):Int=f(10,20)
}
关于some的模式匹配
package com.syf.scala1015day07
/**
* Author Amily
* Date 2021/5/18
*/
object Pattern5 {
def main(args: Array[String]): Unit = {
val opt:Option[Int]=Some(10)
val v:Int=opt match {
case Some(x)=>
//更加复杂的逻辑
x
case None=>0
}
println(v)
}
}
Scala中的异常处理
在Scala中,不强制要求必须处理异常
如何处理异常
1,抛出异常
2,try
抛出异常对象:
throw new 异常对象
Java:
运行时异常
可以不用提前处理,将来运行的时候可能会抛异常
受检异常
在编译阶段,异常必须被处理
1,try
2,抛出异常类型throws异常类
package com.syf.scala1015day07
import java.io.{FileInputStream, IOException}
import scala.io.StdIn
/**8
* Author Amily
* Date 2021/5/18
*/
object ExecptionDemo1 {
def main(args: Array[String]): Unit = {
val i:Int=StdIn.readInt()
if(i==0){
throw new ArithmeticException("除数不能是0")
}
// Thread.sleep(1000)
try {
var i: Int = 1 / 0
new FileInputStream("aa")
}catch{
case e:ArithmeticException=>
println("发生算术异常")
case e:Exception=>
println("运行时异常")
case _=>
}finally {
//不管有没有异常,都会走这里
println("释放资源")
}
println("aaa")
}
@throws(classOf[RuntimeException])
@throws(classOf[IOException])
def foo()={
println("aaaa")
}
}
泛型类和泛型函数
1.泛型类和泛型方法入手
数据类型参数化
a:泛型类
定义类的时候,定义泛型,这个泛型就可以在类的任何地方使用
当成一个类型来使用
b:泛型方法或者泛型函数
定义函数的时候,定义泛型,这个泛型只能在函数的内部使用
package com.syf.scala1015day07
/**9
* Author Amily
* Date 2021/5/18
*/
object Generic1 {
def main(args: Array[String]): Unit = {
val p1:Point[Int]= new Point[Int](10,20)
val x:Int=p1.x
val p2:Point[Double]=Point(11.1,1.2)
val y:Double=p2.y
val i:Int=p1.dis[Int](10)
}
}
case class Point[T](x:T,y:T){
var z:T=x
def foo():T={
z
}
def dis[A](a:A)=a
}
泛型上限
package com.syf.scala1015day07
/**10
* Author Amily
* Date 2021/5/19
*/
class AA(val age:Int) extends Ordered[AA]{
override def compare(that: AA): Int =age-that.age
}
object Generic2 {
def main(args: Array[String]): Unit = {
// val aa:AA= compare(new AA(10),new AA(20))
// println(aa)
// compare("a","b")
}
def compare[T<:Ordered[T]](x:T,y:T)={
if(x>y) x
y
}
}
泛型的下界
package com.syf.scala1015day07
//ctrl+h打开继承结构
/**11
* Author Amily
* Date 2021/5/19
*/
class Animal {
val name: String = "Animal"
}
class Pet extends Animal {
}
class Dog extends Pet {
override val name: String = "dog"
}
class Cat extends Pet {
override val name: String = "cat"
}
class Lion extends Animal {
override val name: String = "lion"
}
object TestGeneric {
def main(args: Array[String]): Unit = {
val dog: Dog = new Dog()
val cat: Cat = new Cat()
val lion: Lion = new Lion()
print(new Pet())
print(new Animal())
print(new Object())
print(dog)
print(1)
}
def print[P >: Pet](p: P) = {
}
/*def print[P <: Pet](p : P) = {
println(p.name)
}*/
}
视图绑定
视图绑定:
ViewBound
T<%Ordered[T]
表示一定要存在一个隐式转换函数
T=>Ordered[T]
package com.syf.scala1015day07
/**12
* Author Amily
* Date 2021/5/19
*/
object ViewBound {
def main(args: Array[String]): Unit = {
val max1=max(10,20)
println(max1)
}
// def max[T<%Ordered[T]](x:T,y:T)={
def max[T](x:T,y:T)(implicit ev$1:T=>Ordered[T])={
if(x > y) x
else y
}
}
上下文界定及其应用
上下文界定:
[T:Ordering]
表示存在一个隐式值:Ordering[T]
得用召唤的方式把隐式召唤出来
等价于:隐式值+隐式参数
上下文:
环境
package com.syf.scala1015day07
/**13 14
* Author Amily
* Date 2021/5/19
*/
case class People(age:Int,name:String)
object People{
implicit val ord:Ordering[People]=new Ordering[People](){
override def compare(x: People, y: People): Int = x.age-y.age
}
}
object ContextBound {
def main(args: Array[String]): Unit = {
println(max(10, 20))
println(max(People(10,"a"),People(20,"b")))
}
def max[T:Ordering](x:T,y:T)={
//从冥界召唤隐式值
val ord :Ordering[T]= implicitly[Ordering[T]]
if(ord.gt(x,y)) x
else y
}
// def max[T](x:T,y:T)(implicit ord:Ordering[T])={
// //x<y 找一个比较器,去比较x y Ordering[T]
// if(ord.gt(x,y)) x
// else y
// }
}
泛型的型变
泛型的型变:
不变 invariant
[T]
子类型的集合对象不能赋值给父类型的集合引用
默认都是不变
协变 covariant
[+T]
子类型的集合对象可以赋值给父类型的集合引用
逆变 contravariant
[-T]
父类型的集合对象可以赋值给子类型的集合引用
package com.syf.scala1015day07
/**15
* Author Amily
* Date 2021/5/19
*/
//集合
//class MyList[T]
//class MyList[+T](t:T){
//参数位置是逆变点
// def foo(t:T)={}//error
// def foo():T=t//ok
//}
class MyList[-T](t:T){
def foo(t:T)={}//ok
def foo[A <: T](a:A):A=a//error
}
class Father
class Son extends Father
object TypeVariable {
def main(args: Array[String]): Unit = {
val a:Father=new Son//ok
// var fList:MyList[Father]= new MyList[Father]
// var sList:MyList[Son]=new MyList[Son]
// fList=sList//编译不通过//不变
// fList=sList//编译通过//协变
// val sList:MyList[Son]=new MyList[Father]//逆变
}
}
//class MySubList[T]extends MyList[T]
二元一元运算符及其他补充
1 中置运算符
1+2
1 to 100
2.一元运算符
后置:
1 toString
5!
前置:
+5
-10
-5==5.unsary_-
这四种前置运算符:
+ -~ !
3.运算符的结合性
重点理解右结合
=
:结尾
4.apply方法
任意对象都可以定义apply方法
对象(…)===对象.apply(…)
1.伴生对象有apply Person(a)
2.普通的类也可以有apply new Person()(a)
3.调用函数
val f=函数
f()
f.apply()
5.update方法
更新
对象(0)= 值 === 对象.update(参数,值)
6. 总结
1.导入包,通配符
2.元组元素的前缀 t.1
3. 函数的隐式参数(占位符) f(+)
4.方法转函数
def f=…
val f1=f_
5.给类的属性设置默认值
class …
var a:Int=_
6.在一个标识符中隔开字符和运算符
±/*
a_+
7.模式匹配的时候通配符
case_=>
8.部分应用函数
val sqrt =math.pow(,2)
9. 分解集合
foo(1,2,3)
foo(1 to 100:)
def foo(a:Int)
10. 模式匹配集合的时候
Array(rest@_*)
…
7.额外的类
Option[T]
语义:表示值要么存在,要么不存在
Some
None
Either[T,V]
表示值要么正确要么错误
Left:左值
Right :右值
package com.syf.scala1015day07
/**17 18
* Author Amily
* Date 2021/5/19
*/
class User(var age:Int,var name:String){
def apply(i:Int)=i match {
case 0=>age
case 1=>name
case _=>throw new IndexOutOfBoundsException("下标越界")
}
def update[T](i:Int,v:T):Unit= i match {
case 0=>age=v.asInstanceOf[Int]
case 1=>name=v.asInstanceOf[String]
case _=>
}
}
object Extro1 {
def main(args: Array[String]): Unit = {
println(5!)
val a:RichInt=new RichInt(5)
// println(~a)
println(a.unary_~)
val user:User=new User(10,"lisi")
// println(user(0))
// println(user(1))
// println(user(2))
// user(0)==100
// user(1)=="zs"
// println(user.age)
// var f:()=>Unit=foo _
// f()
// f.apply()
// val a+ =10//error
// val a_+ :Int=10//ok
val e:Either[String,Double]=sqrt(10)
// if(e.isRight){
// println(e.right.get)
// }else{
// println(e.left.get)
// }
e match {
case Left(l) => println(l)
case Right(r)=> println(r)
}
val s="syf"
println(s(0))//s.apply(0)
s.apply(0)
}
def sqrt(d:Double):Either[String,Double]= d match {
case d if d>=0 =>Right[String,Double] (math.sqrt(d))
case _=> Left[String,Double]("负数不能→平方根")
}
def foo()={
println("foo...")
}
implicit class RichInt(n:Int){
def ! :Int= {
def loop(n: Int): Int =
if (n == 1) 1
else n * loop(n - 1)
loop(n)
}
//+ - ! ~
def unary_~ :Int = n
}
}