高阶函数通过封装校验逻辑实现验证守卫,替代重载机制——它将校验规则变为可传递、复用、组合的一等公民,在业务分支前统一守住数据入口,解耦守卫与目标函数,支持动态组合验证链与正交分支路由。

高阶函数本身不支持重载,但能和验证逻辑天然协同——它把“校验规则”变成可传递、可复用、可组合的一等公民,从而在进入任何业务分支(包括模拟重载的多态逻辑)前,先守住数据入口。
验证守卫不是拦截器,而是前置契约
所谓“参数验证守卫”,本质是用高阶函数封装校验逻辑,并在调用真正业务函数前强制执行。它不依赖语言级重载机制,因此规避了 JavaScript 没有重载、TypeScript 重载仅限声明、Kotlin/Scala 重载与高阶函数属不同维度等问题。
- 守卫函数接收原始参数,返回 Boolean 或 Result
,失败即中断后续流程 - 它和目标函数解耦:同一个守卫可复用于多个函数;同一个函数也可叠加多个守卫
- 例如:
fun validateNonEmptyString(input: String): Boolean = input.isNotBlank(),可作为通用前置条件
用高阶函数动态组装验证链
不必为每种参数组合写一堆重载函数,而是把验证逻辑参数化、函数化,再组合调用:
- 定义基础验证器:
fun minLength(min: Int): (String) -> Boolean = { it.length >= min } - 组合多个验证:
val safePasswordCheck = allOf(minLength(8), hasDigit(), hasUppercase()) -
allOf是一个高阶函数,接收多个(T) -> Boolean,返回新的(T) -> Boolean - 这样,你无需定义
processPasswordLow()、processPasswordMedium()等重载,只需传入对应验证器
在“模拟重载”的分支逻辑前统一守卫
当业务需要根据参数类型或结构走不同路径(类似重载语义),高阶函数可让守卫逻辑与分支选择正交分离:
- 先用统一守卫校验输入是否合法(如非空、格式正确、范围合规)
- 再用另一个高阶函数决定走哪条分支,例如:
fun routeByInput(input: Any): (Any) -> Unit = when (input) { is String -> ::handleString; is Int -> ::handleInt; else -> ::handleDefault } - 整个流程可写成:
if (guard(input)) routeByInput(input)(input) else throw InvalidInputException() - 这种写法比分散在多个重载函数里重复写 if-check 更安全、更易测试、更易审计
结合 Kotlin 的 apply / let / run 实现声明式守卫
利用作用域函数,在构造或调用瞬间嵌入验证,避免“先创建后检查”的时序漏洞:
val user = User(name, email).apply { require(name.isNotBlank()) { "name required" }; require(email.contains('@')) }- 或封装为扩展:
inline fun <t> T.guard(validate: T.() -> Unit): T { validate(); return this }</t> - 调用:
User(name, email).guard { require(name.length > 2); require(email.isValid()) } - 这确保对象一旦构建完成,就已通过全部守卫,后续所有重载/分支逻辑都基于可信状态运行










