2017-05-25 97 views
1

我想学习斯卡拉语言。
在许多文档或视频教程中,我看到scala开发人员创建空的类或对象,并将其用于另一个类作为参数或实现空的特征!
例如:斯卡拉空课堂,对象,特质

object Controller { 
    sealed trait Controller 
    case object Login extends Controller 
    case object Logout extends Controller 
} 

或者这样:

sealed trait Expression 
case class Number(num: Int) extends Expression 
case class Plus(a: Expression, b: Expression) extends Expression 
case class Minus(a: Expression, b: Expression) extends Expression 

object ExpressionEvaluate { 
    def value(expression: Expression): Int = expression match { 
    case Number(value) => value 
    case Plus(a, b) => value(a) + value(b) 
    case Minus(a, b) => value(a) - value(b) 
    } 
} 

我想知道这是什么模式呢?
什么是空义类,对象或特征?
为什么开发人员使用这种模式?

回答

5

这种模式:

sealed trait Controller 
case object Login extends Controller 
case object Logout extends Controller 

或者这

sealed trait Expression 
case class Number(num: Int) extends Expression 
case class Plus(a: Expression, b: Expression) extends Expression 
case class Minus(a: Expression, b: Expression) extends Expression 

被称为algebraic data types。他们是创建co-product/sum types(也被称为标记联盟)的斯卡拉方式。当您在签名中收到类型Expression的特征时,您知道您将收到具体实现之一。您发现哪种类型是具体类型的方式是通过pattern matching,这是匹配类型的能力。越是这样,编译器就足够了sealed trait聪明,知道它的所有底层的具体类型,让你知道如果你的模式匹配并不详尽,例如,如果我添加一个Divide类型:

case class Divide(a: Expression, b: Expression) extends Expression 

而且编译时,编译器会报错:

Warning:(18, 48) match may not be exhaustive. 
It would fail on the following input: Divide(_, _) 
     def value(expression: Expression): Int = expression match { 

至于“空类”,我们必须区分两种类型。一个是case class。 case类是一种在Scala中创建不可变记录类型的方法,将它们想象成类固醇上的product type。这些是编译器自动派生实现hashCodeequals的类,并且还增加了当我们通过apply/unapply进行模式匹配时为我们提供语法糖的方法。例如:

case Number(value) => value 

你看,我们都能够访问Number的模式匹配的value场,这怎么可能?这是可能的,因为编译器为我们提供了一个用于解构案例类的方法unapply

另一个是case object,这是一种在Scala中创建singleton type(正好代表一个值的类型)的方法。由于我们在LoginLogout上没有任何字段,我们可以创建该类型的单个表示。