Scala中的类型与函数深度解析
立即解锁
发布时间: 2025-08-19 00:05:37 阅读量: 2 订阅数: 12 


Scala 2.13编程实战与进阶
### Scala 中的类型与函数深度解析
#### 类型相关知识
##### 类型别名与类型 Lambda
在 Scala 中,有时定义一个类型别名仅用于函数参数定义,会显得有些冗长。类型 Lambda 提供了一种语法,可用于进行就地的部分类型应用。例如:
```scala
def fillWithWater[CC <: Container[Water], F: ({ type T[C] = Filler[Water, C] })#T[CC]](container: CC)(filler: F) = ???
```
类型 Lambda 还能直接定义参数类型:
```scala
def fillWithWater[CC <: Container[Water]](container: CC)(filler: ({ type T[C] = Filler[Water, C] })#T) = ???
```
内部定义的 `T[C]` 类似于之前定义的类型别名,新增的类型投影 `()#T[C]` 可用于引用刚定义的类型。
##### 使用类型定义领域约束
简单类型可用于表达领域约束,下面通过两个例子介绍类型参数和高阶类型在这方面的应用。
- **幽灵类型(Phantom Types)**:Scala 中的幽灵类型在运行时不会被实例化,仅在编译时用于表达类似(广义)类型约束的领域约束。
- 假设有一个 `Lock` 抽象,已通过继承以不同方式实现:
```scala
sealed trait Lock
class PadLock extends Lock
class CombinationLock extends Lock
```
- 我们希望在类型系统中编码,任何锁只允许以下状态转换:
| 起始状态 | 目标状态 |
| ---- | ---- |
| open | closed |
| closed | open |
| closed | broken |
| open | broken |
- 由于已有现有层次结构,难以通过继承 `Lock` 来建模这些状态转换。因此,使用幽灵类型 `Open`、`Closed` 和 `Broken` 来建模状态:
```scala
sealed trait LockState
sealed trait Open extends LockState
sealed trait Closed extends LockState
sealed trait Broken extends LockState
```
- 为 `Lock` 分配状态:
```scala
case class Lock[State <: LockState]()
```
- 定义状态转换方法:
```scala
def break: Lock[Broken] = Lock()
def open[_ >: State <: Closed](): Lock[Open] = Lock()
def close[_ >: State <: Open](): Lock[Closed] = Lock()
```
- 编译器会拒绝导致不适当状态转换的调用。也可使用广义类型约束提供另一种实现:
```scala
def open(implicit ev: State =:= Closed): Lock[Open] = Lock()
def close(implicit ev: State =:= Open): Lock[Closed] = Lock()
```
- 这种实现的错误消息更清晰。
- **自递归类型(Self-recursive Types)**:回顾之前从单个特质继承的不同实现:
```scala
sealed trait Lock
class PadLock extends Lock
class CombinationLock extends Lock
```
- 现在为 `Lock` 添加 `open` 方法,该方法应返回相同类型的 `Lock`:
```scala
sealed trait Secret[E]
sealed trait Lock[E] { def open(key: Secret[E]): E = ??? }
case class PadLock() extends Lock[PadLock]
case class CombinationLock() extends Lock[CombinationLock]
```
- 但这种实现存在问题,可能会使用非 `Lock` 的类型。因此,需要约束类型参数为 `Lock` 的子类型:
```scala
sealed trait Lock[E <: Lock[E]] {
def open(key: Secret[E]): E = ???
}
```
- 这种定义类型的方式称为自递归类型参数。还可添加另一个约束,确保类型参数引用自身:
```scala
sealed trait Lock[E <: Lock[E]] { self: E =>
def open(key: Secret[E]): E = self
}
```
- 通过自递归类型参数和自类型的组合,我们定义了一个只能由扩展该特质的类且只能由该类本身进行参数化的 `Lock` 特质。
#### 函数定义方式
##### 函数作为方法
对于大多数从 Java 转向 Scala 的开发者来说,最常见的方式是在类、特质或对象内部定义方法:
```scala
class MethodDefinition {
def eq(arg1: String, arg2: Int): Boolean = ! nonEqual(arg1, arg2)
private def nonEq(a:
```
0
0
复制全文
相关推荐










