第八章 scala语言–match、PartialFunction、implicit
前言
今天是学习Scala第八天打卡,开始学习match、PartialFunction、implicit。
一、match(模式匹配)
Scala 提供了强大的模式匹配机制,应用也非常广泛。
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。
(1) 简单的整型值模式匹配
object Test {
def main(args: Array[String]) {
println(matchTest(3))
}
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "many"
}
}
执行结果:
---------------------------------------------------------------------------------------------------------------------------
many
- match 对应 Java 里的 switch,但是写在选择器表达式之后。即: 选择器 match {备选项}。
- match 表达式通过以代码编写的先后次序尝试每个模式来完成计算,只要发现有一个匹配的case,剩下的case不会继续匹配。
(2) 不同数据类型的模式匹配
object Test {
def main(args: Array[String]) {
println(matchTest("two"))
println(matchTest("test"))
println(matchTest(1))
println(matchTest(6))
}
def matchTest(x: Any): Any = x match {
case 1 => "one"
case "two" => 2
case y: Int => "scala.Int"
case _ => "many"
}
}
执行结果:
---------------------------------------------------------------------------------------------------------------------------
2
many
one
scala.Int
(3) 使用Iterator遍历并模式匹配
object Lesson06_match {
def main(args: Array[String]): Unit = {
val tup: (Double, Int, String, Boolean, Int) = (1.0,88,"abc",false,44)
val iter: Iterator[Any] = tup.productIterator
val res: Iterator[Unit] = iter.map(
(x) => {
x match {
case 1 => println(s"$x...is 1")
case 88 => println(s"$x ...is 88")
case false => println(s"$x...is false")
case w: Int if w > 50 => println(s"$w...is > 50")
case _ => println("wo ye bu zhi dao sha lei xing ")
}
}
)
while(res.hasNext) println(res.next())
}
}
执行结果:
---------------------------------------------------------------------------------------------------------------------------
1.0...is 1
()
88 ...is 88
()
wo ye bu zhi dao sha lei xing
()
false...is false
()
wo ye bu zhi dao sha lei xing
()
(4) 使用样例类
使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配。
object Test {
def main(args: Array[String]) {
val alice = new Person("Alice", 25)
val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Age: " + age + " year, name: " + name + "?")
}
}
}
// 样例类
case class Person(name: String, age: Int)
}
执行结果:
---------------------------------------------------------------------------------------------------------------------------
Hi Alice!
Hi Bob!
Age: 32 year, name: Charlie?
在声明样例类时,下面的过程自动发生了:
- 构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;
- 在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象;
- 提供unapply方法使模式匹配可以工作;
- 生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义。
二、PartialFunction(偏函数)
object Lesson07_PartialFunction {
def main(args: Array[String]): Unit = {
def xxx:PartialFunction[ Any,String] ={
case "hello" => "val is hello"
case x:Int => s"$x...is int"
case _ => "none"
}
println(xxx(44))
println(xxx("hello"))
println(xxx("hi"))
}
}
执行结果:
---------------------------------------------------------------------------------------------------------------------------
44...is int
val is hello
none
更多:https://cloud.tencent.com/developer/article/1657841
三、implicit
1.JAVA中可以使用forEach()方法对List集合进行遍历,例如:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
list.forEach(e ->{
System.out.println(e);
});
}
执行结果:
---------------------------------------------------------------------------------------------------------------------------
张三
李四
王五
赵六
如果用Scala呢,发现并没有forEach()函数。当然你可以自己定义一个,例如:
val listArray = new util.ArrayList[Int]()
listArray.add(1)
listArray.add(2)
listArray.add(3)
def foreach[T](list:util.ArrayList[T], f:(T)=>Unit): Unit ={
val iter: util.Iterator[T] = list.iterator()
while(iter.hasNext) f(iter.next())
}
foreach(listArray,println)
执行结果:
---------------------------------------------------------------------------------------------------------------------------
1
2
3
或者,你可以这样,例如:
class XXX[T](list:util.LinkedList[T]){
def foreach( f:(T)=>Unit): Unit ={
val iter: util.Iterator[T] = list.iterator()
while(iter.hasNext) f(iter.next())
}
}
val xx = new XXX(listLinked)
xx.foreach(println)
执行结果:
---------------------------------------------------------------------------------------------------------------------------
1
2
3
2.但这样还是不能像list.forEach()直接使用。这里看一下下面的示例:
object Lesson08_implicit {
def main(args: Array[String]): Unit = {
val listArray = new util.ArrayList[Int]()
listArray.add(1)
listArray.add(2)
listArray.add(3)
implicit def demo[T](list:java.util.ArrayList[T]) ={
val iter: util.Iterator[T] = list.iterator()
new Bex(iter)
}
listArray.foreach(println)
}
}
class Bex[T](list:util.Iterator[T]){
def foreach( f:(T)=>Unit): Unit ={
while(list.hasNext) f(list.next())
}
}
执行结果:
---------------------------------------------------------------------------------------------------------------------------
1
2
3
上面的代码,发现竟然实现了,起码形式上是实现了。这里做了什么?
首先这些代码交给scala的编译器去处理。
1,scala编译器编译到 list.foreach(println) ,发现找不到foreach()
2,去寻找有没有implicit关键字定义的方法,且方法的参数正好是list的类型!!!
3,编译器把代码改写为
val xx = new XXX(list)
xx.foreach(println)
。。。
总结
以上就是今天要讲的内容,本文就scala的match、PartialFunction、implicit使用方面列举了一些示例及使用技巧。