题目
设计不可变Person类并实现伴生对象和模式匹配
信息
- 类型:问答
- 难度:⭐⭐
考点
不可变类设计,伴生对象应用,模式匹配实现,apply方法
快速回答
实现要点:
- 定义主构造器为
val的不可变类 - 伴生对象中实现
apply工厂方法 - 实现
unapply方法支持模式匹配 - 添加
isAdult业务方法
代码结构:
class Person private (val name: String, val age: Int) {
def isAdult: Boolean = age >= 18
}
object Person {
def apply(name: String, age: Int): Person = new Person(name, age)
def unapply(p: Person): Option[(String, Int)] = Some((p.name, p.age))
}
## 解析
问题核心
本题要求设计一个符合函数式编程规范的Scala类,重点考察:
- 不可变数据结构的实现
- 伴生对象的工厂模式应用
- 模式匹配的解构能力
- 业务方法的封装
完整实现代码
// 主构造器参数标记为val确保不可变
class Person private (val name: String, val age: Int) {
// 业务方法:检查是否成年
def isAdult: Boolean = age >= 18
}
// 伴生对象
object Person {
// apply工厂方法(创建实例)
def apply(name: String, age: Int): Person = new Person(name, age)
// unapply解构方法(支持模式匹配)
def unapply(p: Person): Option[(String, Int)] = Some((p.name, p.age))
}
原理说明
- 不可变性:通过
val声明构造参数,确保实例状态不可修改 - 伴生对象:与类同名且在同一文件,可访问私有构造器
- apply方法:实现工厂模式,允许
Person("Alice", 30)方式创建实例 - unapply方法:提取器方法,返回
Option[Tuple]支持模式匹配
使用示例
// 创建实例
val alice = Person("Alice", 25)
// 模式匹配
val status = alice match {
case Person(n, a) if a >= 18 => s"$n is adult"
case Person(n, _) => s"$n is minor"
}
println(status) // 输出: Alice is adult
println(alice.isAdult) // 输出: true
最佳实践
- 构造器私有化:通过
private修饰主构造器,强制使用工厂方法 - 返回Option:unapply应返回
Option[Tuple],None表示匹配失败 - case类替代方案:简单场景可直接用
case class(自动生成apply/unapply)
常见错误
- 忘记将构造参数声明为
val,导致无法外部访问 - unapply返回类型错误(需为
Option[TupleN]) - 未将主构造器私有化,允许
new Person(...)直接创建
扩展知识
- case类原理:case类自动生成apply/unapply/equals/copy等方法
- 提取器变体:可定义
unapplySeq支持变长参数匹配 - 类型安全:结合密封特质(sealed trait)实现完备的模式匹配检查