博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Scala的sealed关键字
阅读量:6934 次
发布时间:2019-06-27

本文共 3961 字,大约阅读时间需要 13 分钟。

hot3.png

今天在学习Akka的监控策咯过程中看到了下面一段代码:

def supervisorStrategy(): SupervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 10 seconds) {    case _: ArithmeticException => Resume    case _: IllegalArgumentException => Restart    case _: NullPointerException => Stop    case _: Exception => Escalate  }

当时有点好奇,就想去看看ResumeRestart等的实现,于是就看到了下面的代码:

object SupervisorStrategy extends SupervisorStrategyLowPriorityImplicits {

sealed trait Directive

/** * Resumes message processing for the failed Actor */case object Resume extends Directive/** * Discards the old Actor instance and replaces it with a new, * then resumes message processing. */case object Restart extends Directive/** * Stops the Actor */case object Stop extends Directive/** * Escalates the failure to the supervisor of the supervisor, * by rethrowing the cause of the failure. */case object Escalate extends Directive  // ....}

刚刚Scala不久,不太清楚这里的sealed关键字的作用,本文下面就详细的描述一下这个关键字的作用吧。

模式匹配

模式匹配pattern matching在scala里面是一个重量级的功能,依赖于模式匹配可以优雅地实现很多功能。大致格式如下:

selector match {  pattern1 => 
pattern2 =>
...}

pattern总结起来大约以下几类:

  • Wildcard patterns // _ 统配
  • Constant patterns // 常量
  • Variable patterns // 变量
  • Constructor patterns // 构造函数
  • Sequence patterns // 比如List(,). 如果需要匹配剩余的话使用List(0,_*)
  • Tuple patterns // (a,b,c)
  • Typed patterns // 使用类型匹配 case a:Map[,]
  • asInstanceOf[]
  • isInstanceOf[]
  • note(dirlt):这里需要注意容器类型擦除.Array例外因为这个是java内置类型

实际上我们还能够使用pattern完成下面事情:

  • Patterns in variable definitions // val (a,b) = ("123","345");
  • Case sequences as partial functions
    • 直接使用pattern来构造函数.以参数为match对象,在body里面直接编写case.
    • Each case is an entry point to the function, and the parameters are specified with the pattern. The body of each entry point is the right-hand side of the case.
  • Patterns in for expressions // for ((country, city) <- capitals)

    // case sequences as partial function. val foo : Option[String] => String = {  case Some(e) => e  case None => "???"}val a = Option[String]("hello")println(foo(a))val b = Noneprintln(foo(b))

pattern matching过程中还有下面几个问题需要注意:

  • Patterns are tried in the order in which they are written.
  • Variable binding // 有时候我们希望匹配的变量包含外层结构
    • A(1,B(x)) => handle(B(x))
    • A(1, p @ B(_)) => handle(p) # p绑定了B(x)这个匹配
    • A(1, p @ B()) => handle(p) # B是可以包含unapply从type(p) => Boolean的类,做条件判断
  • Pattern guards // 有时候我们希望对pattern做一些限制性条件
    • A(1,e,e) 比如希望后面两个元素相等,但是这个在pm里面没有办法表达
    • A(1,x,y) if x == y => // 通过guard来完成

scala为了方便扩展模式匹配对象的case, 提供case class这个概念。case class和普通class大致相同,不过有以下三个区别,定义上只需要在class之前加上case即可:

  • 提供factory method来方便构造object
  • class parameter隐含val prefix
  • 自带toString,hashCode,equals实现

    case class A(x:Int) {} // implicit val x:Int  val a = A(1); // factory method.println(a.x); println(a); // toString = A(1)

case class最大就是可以很方便地用来做pattern matching.

如果我们能够知道某个selector所有可能的pattern的话,那么就能够在编译期做一些安全性检查。但是selector这个过于宽泛,如果将selector限制在类层次上的话,那么还是可以实现的。举例如下:

abstract class A; // sealed abstract class Acase class B(a:Int) extends A;case class C(a:Int) extends A;case class D(a:Int) extends A;val a:A = B(1);a match {  case e @ B(_) => println(e)  case e @ C(_) => println(e)}

在match a这个过程中,实际上我们可能存在B,C,D三种子类,但是因为我们这里缺少检查。使用sealed关键字可以完成这个工作。sealed class必须和subclass在同一个文件内。A sealed class cannot have any new subclasses added except the ones in the same file. 如果上面增加sealed的话,那么编译会出现如下警告,说明我们没有枚举所有可能的情况。

/Users/dirlt/scala/Hello.scala:8: warning: match may not be exhaustive.It would fail on the following input: D(_)a match {^one warning found

有三个方式可以解决这个问题,一个是加上对D的处理,一个是使用unchecked annotation, 一个则是在最后用wildcard匹配

(a : @unchecked)  match {      case e @ B(_) => println(e)      case e @ C(_) => println(e)    }        a match {      case e @ B(_) => println(e)      case e @ C(_) => println(e)      case _ => throw new RuntimeException("??");    }

sealed

从上面的描述我们可以知道,sealed 关键字主要有2个作用:

  • 其修饰的trait,class只能在当前文件里面被继承
  • 用sealed修饰这样做的目的是告诉scala编译器在检查模式匹配的时候,让scala知道这些case的所有情况,scala就能够在编译的时候进行检查,看你写的代码是否有没有漏掉什么没case到,减少编程的错误。

转载于:https://my.oschina.net/u/2935389/blog/1377650

你可能感兴趣的文章
apache忽略文件后缀
查看>>
教你如何rEFIt-让你开机免按option!
查看>>
linux 权限管理
查看>>
Windows 2003 标准版_企业版_SP1_SP2_R2的区别
查看>>
AD域管理系列(6)-- 常见处理
查看>>
rpm包安装apache发布多个虚拟主机
查看>>
运维工具
查看>>
喜欢与需要
查看>>
echo命令详解
查看>>
Activity一共有以下四种launchMode
查看>>
空间谱专题09:阵列信号建模方法
查看>>
微软职位内部推荐-SENIOR DEVELOPMENT LEAD
查看>>
k8s系列~mgr的应用
查看>>
并查集 HDOJ 5441 Travel
查看>>
简单几何(推公式) UVA 11646 Athletics Track
查看>>
简单几何(线段相交+最短路) POJ 1556 The Doors
查看>>
INFORMIX-4GL实用手册
查看>>
理解Java动态代理(1)—找我还钱?我出钱要你的命
查看>>
前后端分离?
查看>>
打砖块代码解析
查看>>