
回复
在鸿蒙开发中,自定义枚举与标准库的Option
、Result
类型协同,是构建健壮应用的关键。这套组合拳能高效处理值缺失、操作失败等场景,比传统null判断更安全。下面结合实战经验,分享如何用枚举构建类型安全的业务逻辑。
标准库的Option<T>
是处理"可能不存在值"的利器:
enum Option<T> {
| Some(T) // 值存在
| None // 值缺失
}
相比null,它有两大优势:
当业务需要更具体的缺失场景时,可扩展Option逻辑:
// 用户权限枚举(比Option更具象)
enum UserPermission {
| Granted(String) // 已授权(带权限范围)
| Denied // 拒绝授权
| Uninitialized // 未初始化
}
// 转换为标准Option
func permissionToOption(perm: UserPermission) -> Option<String> {
match perm {
case .Granted(scope) => Some(scope)
case .Denied | .Uninitialized => None
}
}
利用if-let
简化Option处理:
let perm = UserPermission.Granted("read")
if let Some(scope) = permissionToOption(perm) {
println("有权限:\(scope)") // 输出:有权限:read
} else {
println("权限不足")
}
Result<T, E>
是处理失败场景的最佳实践:
enum Result<T, E> {
| Ok(T) // 成功,带结果
| Err(E) // 失败,带错误
}
适用于文件操作、网络请求等可能失败的场景。
定义业务专属错误,让失败处理更精准:
// 文件操作错误枚举
enum FileError {
| NotFound(String) // 文件名
| PermissionDenied // 权限问题
| CorruptedData // 数据损坏
}
// 返回Result的文件读取函数
func readConfig(path: String) -> Result<String, FileError> {
if !fileExists(path) {
return Err(.NotFound(path))
} else if !hasReadPermission(path) {
return Err(.PermissionDenied)
} else {
let content = readFile(path)
return content.isCorrupted ? Err(.CorruptedData) : Ok(content)
}
}
分层处理不同错误类型:
func processConfig() {
let result = readConfig("/app/config.json")
match result {
case .Ok(content) => applyConfig(content)
case .Err(error) => handleFileError(error)
}
}
func handleFileError(error: FileError) {
match error {
case .NotFound(path) => println("文件未找到:\(path)")
case .PermissionDenied => showPermissionDialog()
case .CorruptedData => promptRepair()
}
}
让自定义错误适配标准库接口:
// 使FileError符合标准Error协议
extension FileError : Error {}
// 转换为Throws风格接口
func loadConfig() throws {
let result = readConfig("/data.json")
if let .Err(e) = result {
throw e // 适配try/catch语法
}
}
解决"可能缺失值+可能失败"的双重场景:
func fetchRemoteData() -> Result<Option<String>, NetworkError> {
if isNetworkAvailable() {
let data = networkRequest() // 可能返回None
return .Ok(data)
} else {
return .Err(.NoConnection)
}
}
// 处理嵌套类型
match fetchRemoteData() {
case .Ok(Some(data)) => processData(data)
case .Ok(None) => println("远程数据不存在")
case .Err(error) => showNetworkError(error)
}
参考标准库设计可复用的枚举:
// 类似Result的Either类型
enum Either<L, R> {
| Left(L)
| Right(R)
}
// 转换工具函数
func resultToEither<T, E>(result: Result<T, E>) -> Either<E, T> {
match result {
case .Ok(t) => .Right(t)
case .Err(e) => .Left(e)
}
}
Result<T, AppError>
复杂枚举解构拆分为独立函数:
func parseJson(data: Data) -> Result<Model, ParseError> { /* ... */ }
func handleParseResult(result: Result<Model, ParseError>) {
match result {
case .Ok(model) => displayModel(model)
case .Err(error) => logParseError(error)
}
}
自定义枚举与标准库的协同本质是: