美文网首页scala程序员
Scala学习笔记(七) Sealed Class 和 En

Scala学习笔记(七) Sealed Class 和 En

作者: fengzhizi715 | 来源:发表于2017-04-12 19:35 被阅读0次

    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学习笔记(一)

    相关文章

      网友评论

        本文标题:Scala学习笔记(七) Sealed Class 和 En

        本文链接:https://www.haomeiwen.com/subject/dhrhattx.html