(三)实战案例 1:为 String 拓展邮箱验证方法
1. 需求说明
为 Scala 原生 String 类拓展 isEmail 方法,用于验证字符串是否为合法邮箱格式,要求:
val str1 = "example@example.com"
val str2 = "not an email"
println(str1.isEmail) // 输出 true
println(str2.isEmail) // 输出 false
2. 思路拆解(四步分析法)
| 问题 | 答案 |
|---|---|
1. String 本身是否有 isEmail 方法? | 无,Scala 原生 String 无此方法 |
2. 能否自定义类封装 isEmail 方法? | 能,定义 StrongStr 类,接收 String 并实现 isEmail |
3. 能否写转换函数将 String 转 StrongStr? | 能,隐式转换函数可自动完成转换 |
| 4. 转换函数能否隐式调用? | 能,通过隐式类简化「转换函数 + 拓展类」 |
3. 完整可运行代码
object EmailValidationDemo {
// 定义隐式类:为String拓展isEmail方法
implicit class StrongStr(s: String) {
// 邮箱验证核心逻辑(正则匹配)
def isEmail: Boolean = {
// 邮箱正则规则:覆盖大部分合法邮箱格式
val emailPattern = """^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$""".r
// 注意:原代码笔误,正确方法是 matches(全量匹配)
emailPattern.matches(s)
}
}
def main(args: Array[String]): Unit = {
// 测试用例1:合法邮箱
val validEmail = "example@example.com"
// 测试用例2:非法邮箱(无@)
val invalidEmail1 = "not an email"
// 测试用例3:非法邮箱(@后无域名)
val invalidEmail2 = "example@.com"
println(s"$validEmail 是否为合法邮箱:${validEmail.isEmail}") // true
println(s"$invalidEmail1 是否为合法邮箱:${invalidEmail1.isEmail}") // false
println(s"$invalidEmail2 是否为合法邮箱:${invalidEmail2.isEmail}") // false
}
}
4. 关键说明
-
邮箱正则规则解读:
^[a-zA-Z0-9_.+-]+:邮箱前缀,允许字母、数字、下划线、点、加号、减号;@:固定分隔符;[a-zA-Z0-9-]+:邮箱域名(如 gmail、163);.[a-zA-Z0-9-.]+$:域名后缀(如 .com、.cn、.co.uk);
-
核心方法:
matches是正则的全量匹配方法,确保整个字符串符合邮箱格式(原代码笔误为matche,已修正)。
(四)实战案例 2:为 Int 拓展阶乘方法
1. 需求说明
为 Scala 原生 Int 类拓展阶乘方法(!()),支持 3! 形式调用,计算 3*2*1:
println(3!) // 输出 6
println(5!) // 输出 120
2. 思路分析
- 原生
Int无!()方法,需通过隐式类拓展; - 阶乘逻辑:
n! = n*(n-1)*...*1,特殊值0! = 1、1! = 1; - 隐式类接收
Int参数,实现!()方法封装阶乘计算。
3. 完整可运行代码(优化版)
package pub
object FactorialDemo {
// 定义隐式类:为Int拓展阶乘方法
implicit class FactorialInt(n: Int) {
// 阶乘方法:!() (符号方法,符合数学习惯)
def !(): Int = {
// 边界处理:0! 和 1! 均为1
if (n <= 1) 1
else (1 to n).product // 优化:用Range的product方法直接计算乘积,替代循环
}
}
def main(args: Array[String]): Unit = {
// 测试用例
println(s"0! = ${0!}") // 输出 1
println(s"1! = ${1!}") // 输出 1
println(s"3! = ${3!}") // 输出 6
println(s"5! = ${5!}") // 输出 120
println(s"7! = ${7!}") // 输出 5040
}
}
4. 进阶优化说明
- 边界处理:补充
n <= 1的情况,避免负数阶乘或 0/1 阶乘计算错误; - 代码简化:用
(1 to n).product替代手动循环,Scala 集合的product方法可直接计算区间内所有数字的乘积,更简洁高效; - 符号方法:Scala 支持用符号定义方法(如
!()、+()),贴合数学中阶乘的书写习惯。
核心知识点总结
- 隐式对象:单例 + 隐式参数结合,用于提供全局统一的默认实例(如配置);
- 隐式类:「拓展类 + 隐式转换函数」的语法糖,核心用于无侵入拓展已有类的方法;
- 隐式类关键规则:必须有且仅有一个构造器参数、需定义在类 / 对象 / 包对象内部;
- 实战核心:隐式类可灵活拓展原生类(String、Int)或自定义类的功能,完全遵循 OCP 原则(不修改原代码,仅拓展)。