话说模式匹配(6) case类的细节

简介:

我们在第二篇文章里曾提到过:

本质上case class是个语法糖,对你的类构造参数增加了getter访问,还有toString, hashCode, equals 等方法; 最重要的是帮你实现了一个伴生对象,这个伴生对象里定义了apply方法和unapply方法。

现在我们来详细的分析一下case class,对一个简单的样本类


case class B()


反编译后看到编译器自动给它混入了Product特质,以及Serializable特质:


public class B implements scala.Product,scala.Serializable {
    public B copy();
    public java.lang.String productPrefix();
    public int productArity();
    public java.lang.Object productElement(int);
    public scala.collection.Iterator<java.lang.Object> productIterator();
    public boolean canEqual(java.lang.Object);
    public int hashCode();
    public java.lang.String toString();
    public boolean equals(java.lang.Object);
    public B();
}


再看看它的半生对象:


//伴生对象也混入了AbstractFunction0 和 Serializable 特质
public final class B$ extends scala.runtime.AbstractFunction0<B> implements scala.Serializable {
    public static final B$ MODULE$;
    public static {};
    public final java.lang.String toString();
    public B apply();
    public boolean unapply(B);
    public java.lang.Object apply();
}


通过反编译的结果我们了解到了几点:

  1. 编译器对case类混入了Product特质
  2. 编译器对case类增加了copy方法;
  3. 编译器对case类实现了equals/hashCode/toString等方法
  4. 伴生对象中最重要的方法是 unapply 这个方法是在进行构造器模式匹配时的关键。
  5. 伴生对象中apply方法则为创建对象提供方便,相当于工厂方法。
  6. 伴生对象继承了AbstractFunction

从case类的设计目的来看,最重要的是提供构造器模式匹配(且构造时的参数,与解构的结果一致),另外case类可看作是数据对象,不可变的数据对象。

因为case类封装的数据有不变的特点,以及可以进行模式匹配,所以它在actor中经常使用,很适合封装消息在actor之间传递。

上面列出的几点中,对于第6点“伴生对象继承自 Function”可能感到奇怪,Martin在这里回答了为什么case类的伴生对象会继承FunctionN

The reason why case class companion objects implement FunctionN is that before, case classes generated a class and a factory method, not a companion object. When we added extractors to Scala it made more sense to turn the factory method into a full companion object with apply and unapply methods. But then, since the factory method did conform to FunctionN, the companion object needed to conform, too.

另外,当参数大于2个时,FunctionN 都提供了tupled方法生成一个函数,该函数可以接受一个tuple作为参数构造出结果,比如:


scala> case class A(x: Int, y:Int)

scala> A.tupled
res11: ((Int, Int)) => A = <function1>

scala> val t = (100,100)
t: (Int, Int) = (100,100)

scala> A.tupled(t)
res9: A = A(100,100)


目录
相关文章
|
2月前
|
Java 开发者
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案。本文通过技术综述及示例代码,剖析两者在性能上的差异。if-else具有短路特性,但条件增多时JVM会优化提升性能;switch则利用跳转表机制,在处理大量固定选项时表现出色。通过实验对比可见,switch在重复case值处理上通常更快。尽管如此,选择时还需兼顾代码的可读性和维护性。理解这些细节有助于开发者编写出既高效又优雅的Java代码。
38 2
|
2月前
|
存储
访问者模式问题之在 extractFunctions 方法中, FunctionCallExpression 类型的 Expression如何处理
访问者模式问题之在 extractFunctions 方法中, FunctionCallExpression 类型的 Expression如何处理
|
3月前
switch的使用细节
switch的使用细节
27 0
|
5月前
|
安全 Java 开发者
JDK 21中的Switch模式匹配:一种更强大且灵活的分支选择机制
本文深入探讨了JDK 21中引入的Switch模式匹配的新特性。这种新的模式匹配机制不仅简化了传统的switch语句,还引入了类型检查和模式匹配,使得代码更加简洁、易读且功能强大。本文将详细介绍Switch模式匹配的语法、使用场景以及与传统switch语句的区别,并通过示例代码展示其在实际开发中的应用。
1135 0
|
5月前
|
存储 程序员 编译器
【新手解答5】深入探索 C 语言:宏中的文本、标识符和字符串 + 递归运算、条件语句、循环 + `switch-case` 与多项条件和枚举的差别
【新手解答5】深入探索 C 语言:宏中的文本、标识符和字符串 + 递归运算、条件语句、循环 + `switch-case` 与多项条件和枚举的差别
77 0
|
JSON 程序员 数据格式
优雅地处理Python中的条件分支:字典映射、函数组合与match-case语句
在本文中,我们探讨了如何在Python中优雅地处理条件分支,以避免使用过多的if语句。文章介绍了两种解决方案:字典映射与函数组合以及Python 3.10中引入的match-case语句。这些方法使得代码结构更加清晰、简洁且易于维护和扩展。
116 0
|
设计模式 存储 Java
【Java设计模式 规范与重构】 五 重构实战:基于ID生成器case(下)
【Java设计模式 规范与重构】 五 重构实战:基于ID生成器case(下)
196 0
|
设计模式 存储 SQL
【Java设计模式 规范与重构】 五 重构实战:基于ID生成器case(上)
【Java设计模式 规范与重构】 五 重构实战:基于ID生成器case(上)
131 0
JavaScirpt基础break关键字
JavaScirpt基础break关键字
77 0
|
Go 开发者
break 语法和流程图 | 学习笔记
快速学习 break 语法和流程图
690 0
break 语法和流程图 | 学习笔记