话说模式匹配(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)


目录
相关文章
|
5月前
|
存储 前端开发 JavaScript
条件判断的模式问题之如果混淆了断言和卫述如何解决
条件判断的模式问题之如果混淆了断言和卫述如何解决
|
3月前
|
Java Spring
巧用switch-case消除条件判断
`shigen`是一位致力于撰写博客文章的作者,通过记录成长历程、分享见解并留住感动瞬间。在其文章中,`shigen`介绍了多种消除if-else代码的方法,包括使用HashMap、枚举以及switch-case。最新示例展示了如何通过简洁的switch-case语句处理不同类型的请求,代码优雅且直观。此外,还预告了下一章节将探讨如何利用Spring框架的IOC能力来进一步优化条件判断。与`shigen`一起探索编程世界的每一天都充满新意!**个人IP:shigen**
35 0
巧用switch-case消除条件判断
|
4月前
|
存储
访问者模式问题之在 extractFunctions 方法中, FunctionCallExpression 类型的 Expression如何处理
访问者模式问题之在 extractFunctions 方法中, FunctionCallExpression 类型的 Expression如何处理
|
5月前
switch的使用细节
switch的使用细节
38 0
|
7月前
|
开发框架 .NET C#
C# 10.0中的扩展属性与模式匹配:深入解析
【1月更文挑战第20天】C# 10.0引入了众多新特性,其中扩展属性与模式匹配的结合为开发者提供了更强大、更灵活的类型检查和代码分支能力。通过这一特性,开发者可以在不修改原始类的情况下,为其添加新的行为,并在模式匹配中利用这些扩展属性进行更精细的控制。本文将详细探讨C# 10.0中扩展属性与模式匹配的工作原理、使用场景以及最佳实践,帮助读者更好地理解和应用这一新功能。
|
Java
JEP 420:简化的 switch 表达式
Java 14 引入了 switch 表达式, Java 18 实现了 JEP 420 以下是 switch 表达式
125 0
|
7月前
|
安全 Java 开发者
JDK 21中的Switch模式匹配:一种更强大且灵活的分支选择机制
本文深入探讨了JDK 21中引入的Switch模式匹配的新特性。这种新的模式匹配机制不仅简化了传统的switch语句,还引入了类型检查和模式匹配,使得代码更加简洁、易读且功能强大。本文将详细介绍Switch模式匹配的语法、使用场景以及与传统switch语句的区别,并通过示例代码展示其在实际开发中的应用。
1269 0
|
7月前
|
存储 程序员 编译器
【新手解答5】深入探索 C 语言:宏中的文本、标识符和字符串 + 递归运算、条件语句、循环 + `switch-case` 与多项条件和枚举的差别
【新手解答5】深入探索 C 语言:宏中的文本、标识符和字符串 + 递归运算、条件语句、循环 + `switch-case` 与多项条件和枚举的差别
80 0
|
存储 缓存 安全
Java 编程问题:二、对象、不变性和`switch`表达式2
Java 编程问题:二、对象、不变性和`switch`表达式
91 0
|
JSON IDE Java
Java 编程问题:二、对象、不变性和`switch`表达式3
Java 编程问题:二、对象、不变性和`switch`表达式
115 0