Scala学习笔记(七)

1. Sealed Class

1.1 sealed class

先上一段代码,看看sealed是怎么使用的

scala> sealed abstract class Drawing
defined class Drawing

scala> case class Point(x: Int, y: Int) extends Drawing
defined class Point

scala> case class Circle(p: Point, r: Int) extends Drawing
defined class Circle

scala> case class Cylinder(c: Circle, h: Int) extends Drawing
defined class Cylinder

scala> def what(d: Drawing) = d match {
     |   case Point(_,_) => "点"
     |   case Circle(_,_) => "圆"
     | }
<console>:16: warning: match may not be exhaustive.
It would fail on the following input: Cylinder(_, _)
       def what(d: Drawing) = d match {
                              ^
what: (d: Drawing)String

在这里what()方法报错了,主要是因为还缺少了对Cylinder的匹配,只要改成如下的代码就可以正常运行了。

scala> def what(d: Drawing) = d match {
     |   case Point(_,_) => "点"
     |   case Circle(_,_) => "圆"
     |   case Cylinder(_,_) => "柱"
     | }
what: (d: Drawing)String

在使用模式匹配的时候,使用 sealed 修饰某个 class 的目的是让 Scala 知道所有 case 的情况,否则会编译报错。

当然,也有例外的时候,使用 @unchecked 告诉编译器可以不用检查也能编译通过。

scala> def what(d: Drawing) = (d: @unchecked) match {
     |   case Point(_,_) => "点"
     |   case Circle(_,_) => "圆"
     | }
what: (d: Drawing)String

还有一点很重要,当使用 sealed 来修饰某个 class 时,继承该类的其他子类需要跟父类在同一文件中。

1.2 sealed trait

同样,先上一段代码

scala> sealed trait Color
defined trait Color

scala> final case object Red extends Color
defined object Red

scala> final case object Green extends Color
defined object Green

scala> final case object Blue extends Color
defined object Blue

scala> val colors = List(Red,Green,Blue)
colors: List[Product with Serializable with Color] = List(Red, Green, Blue)

可以看到“Product with Serializable with Color”这一句。 case class 会自动继承两个trait:Product 和 Serializable。

Product Trait 让 case class 被扩展为具有Algebraic Data Type,或者说具有产品类型

Serializable Trait 让 case class 可以被视为一个纯粹的数据,能够被序列化。

如果你想避免看到这个实现的细节,可以提前声明Color已经扩展了 Product 和 Serializable 这些 trait。

scala> sealed trait Color extends Product with Serializable
defined trait Color

scala> final case object Red extends Color
defined object Red

scala> final case object Green extends Color
defined object Green

scala> final case object Blue extends Color
defined object Blue

scala> val colors = List(Red, Green, Blue)
colors: List[Color] = List(Red, Green, Blue)

sealed 修饰的 trait 也只能在当前文件里面被继承。

1.3 sealed abstract 和 abstract class 的区别

sealed class的所有子类,无论是否是抽象类,都必须跟 sealed class 在同一个文件中。

而abstract class并没有这样的规定。

2. Enumeration

Scala 中并没有枚举类型,但是在标准库中有scala.Enumeration。可以扩展Enumeration类,调用Value方法来初始化枚举中的可能值。

/**
  * Created by tony on 2017/4/12.
  */
object Source extends Enumeration {

  type Source = Value

  //枚举的定义
  val Net, Memory, Disk = Value
}

import Source._

object Data extends App {

  def loadData(source: Source){
    source match {
      case Net => println ("source type is " + source)
      case Memory => println ("source type is " + source)
      case Disk => println ("source type is " + source)
      case _ => println ("unknown type")
    }
  }

  val net = Source(0) // Calls Enumeration.apply
  println(loadData(net)) // source type is Net

  // 遍历Source枚举
  for (s <- Source.values)
    println(s.id + ":" + s)
}

打印的结果:

source type is Net
()
0:Net
1:Memory
2:Disk

在定义枚举值的时候也可以自定义id和名称,Source2重新定义了几个枚举。

/**
  * Created by tony on 2017/4/12.
  */
object Source2 extends Enumeration {

  type Source = Value

  //枚举的定义
  val Net, Memory, Disk = Value
  val Other = Value(10,"other source")
}

object Data2 extends App {

  // 遍历Source枚举
  for (s <- Source2.values)
    println(s.id + ":" + s)
}

打印的结果:

0:Net
1:Memory
2:Disk
10:other source

最终,我们可以得到:

  • Scala中的枚举使用轻量级Enumeration进行实现
  • Scala中的枚举其实是一个伴随对象
  • Scala中的枚举没有方法重写功能
  • Scala中的枚举其实都是Enumeration.Value这个对象

总结

本篇笔记仍然是为了 Scala 模式匹配所做的铺垫。在模式匹配中会讲到Sealed Class,所以先整理出来。除了Sealed用法之外,还整理了Enumeration的相关用法。

先前的文章: Scala学习笔记(六) Scala的偏函数和偏应用函数 Scala学习笔记(五) 抽象类以及类中的一些语法糖 Scala学习笔记(四) 类的初步 Scala学习笔记(三) Scala学习笔记(二) Scala学习笔记(一)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员互动联盟

【编程基础】聊聊C语言-兵马未动粮草先行(1)

上一篇我们讲的聊聊C语言-我的地盘我做主,相信大家对变量的存储类型和变量的作用域有了一定的了解。现在我们马上公布上期的答案如下: #include<stdio....

3328
来自专栏Jackson0714

PHP内核之旅-3.变量

1444
来自专栏恰童鞋骚年

.NET基础拾遗(1)类型语法基础和内存管理基础

在.NET中所有的内建类型都继承自System.Object类型。在C#中,不需要显示地定义类型继承自System.Object,编译器将自动地自动地为类型添...

1132
来自专栏信安之路

php 不用字母,数字和下划线写 shell

还有这个师傅的 《记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)》

3841
来自专栏绿巨人专栏

TypeScript中的怪语法

1173
来自专栏Java技术栈

JDK8新特性之Stream流

是什么是Stream流 java.util.stream.Stream Stream流和传统的IO流,它们都叫流,却是两个完全不一样的概念和东西。 流可以简单的...

2926
来自专栏盛国存的专栏

A Bite of GoLang(上)

A bite of GoLang(浅尝GoLang),本文只是Go语言的冰山一角,本文包含作者学习Go语言期间积累的一些小的经验,同时为了方便让读者了解到Go语...

55210
来自专栏绿巨人专栏

TypeScript中的怪语法

4705
来自专栏大内老A

ASP.NET MVC三个重要的描述对象:ControllerDescriptor

ASP.NET MVC应用的请求都是针对某个Controller的某个Action方法,所以对请求的处理最终体现在对目标Action方法的执行。而Action方...

1847
来自专栏向治洪

Swift 4.0 新特性

WWDC 2017 带来了很多惊喜,在这次大会上,Swift 4 也伴随着 Xcode 9 测试版来到了我们的面前,虽然正式版要8月底9月初才会公布,但很多强大...

2269

扫码关注云+社区

领取腾讯云代金券