_类型类_是一种抽象的参数化类型,它允许您在不使用子类型的情况下向任何封闭数据类型添加新行为。 这在多用例中很有用,例如:
- 表达你不拥有的类型——来自标准库或第三方库——如何符合这种行为
- 为多种类型表达这种行为,而不涉及这些类型之间的子类型关系
在 Scala 3 中,类型类只是具有一个或多个参数的 traits,其实现由 given
实例提供。
例子
例如,Show
是 Haskell 中众所周知的类型类,下面的代码显示了在 Scala 3 中实现它的一种方法。
如果您认为 Scala 类没有 toString
方法,您可以定义一个 Show
类型类,然后把此行为添加到任意的类,这个类是能够转换为自定义字符串。
类型类
创建类型类的第一步是声明具有一个或多个抽象方法的参数化 trait。
因为 Showable
只有一个名为 show
的方法,所以写成这样:
// a type class
trait Showable[A]:
extension(a: A) def show: String
这是 Scala 3 的说法,任何实现此 trait 的类型都必须定义 show
方法的工作方式。
请注意,语法非常接近普通的 trait:
// a trait
trait Show:
def show: String
有几件重要的事情需要指出:
- 像
Showable
这样的类型类有一个类型参数A
来说明我们为哪种类型提供了show
的实现;相反,像Show
这样的正常特征不会。 - 要将 show 功能添加到特定类型
A
,正常 trait 需要A extends Show
,而对于类型类,我们需要实现Showable[A]
。 - 为了在两个
Showable
中允许相同的方法调用语法来模仿Show
,我们将Showable.show
定义为扩展方法。
实现具体实例
下一步是确定在应用程序中,Showable
适用于哪些类,然后为它们实现该行为。
例如,为这个 Person
类实现 Showable
:
case class Person(firstName: String, lastName: String)
你将为 Showable[Person]
定义一个 given
值。
这段代码为 Person
类提供了一个 Showable
的具体实例:
given Showable[Person] with
extension(p: Person) def show: String =
s"${p.firstName} ${p.lastName}"
如图所示,这被定义为 Person
类的扩展方法,它使用 show
方法主体内的引用 p
。
使用类型类
现在你可以像这样使用这个类型类:
val person = Person("John", "Doe")
println(person.show)
同样,如果 Scala 没有可用于每个类的 toString
方法,您可以使用此技术将 Showable
行为添加到您希望能够转换为 String
的任何类。
编写使用类型类的方法
与继承一样,您可以定义使用 Showable
作为类型参数的方法:
def showAll[S: Showable](xs: List[S]): Unit =
xs.foreach(x => println(x.show))
showAll(List(Person("Jane"), Person("Mary")))
具有多种方法的类型类
请注意,如果要创建具有多个方法的类型类,则初始语法如下所示:
trait HasLegs[A]:
extension (a: A)
def walk(): Unit
def run(): Unit
一个真实的例子
有关如何在 Scala 3 中使用类型类的真实示例,请参阅多元相等性部分中的 CanEqual
讨论。
Contributors to this page:
Contents
- 导言
- Scala 3 特性
- 为什么是 Scala 3 ?
- Scala 的味道
- Hello, World!
- The REPL
- 变量和数据类型
- 控制结构
- 领域建模
- 方法
- 头等函数
- 单例对象
- 集合
- 上下文抽象
- 顶层定义
- 总结
- 类型初探
- 控制结构
- 领域建模
- 工具
- OOP 领域建模
- 函数式领域建模
- 方法
- 方法特性
- main 方法
- 总结
- 函数
- 匿名函数
- 函数变量
- Eta 扩展
- 高阶函数
- 自定义 map 函数
- 创建可以返回函数的方法
- 总结
- 打包和导入
- Scala 集合
- 集合类型
- 集合方法
- 总结
- 函数式编程
- 什么是函数式编程?
- 不可变值
- 纯函数
- 函数是值
- 函数式错误处理
- 总结
- 类型和类型系统
- 类型推断
- 泛型
- 相交类型
- 联合类型
- 代数数据类型
- 型变
- 不透明类型
- 结构化类型
- 依赖函数类型
- 其他类型
- 上下文抽象
- 扩展方法
- Given 实例和 Using 语句
- 上下文绑定
- Given 导入
- 实现类型类
- 多元相等性
- 隐式转换
- 总结
- 并发
- Scala 工具
- 使用 sbt 构建和测试 Scala 项目
- worksheet
- 与 Java 交互
- 向 Java 开发者介绍Scala
- Scala for JavaScript Developers
- Scala for Python Developers
- 下一步去哪