< 返回我的博客
爱国的张浩予 发表于 2022-05-15 19:26
Tags:?,static-dispatch,dynamic-dispatch,conversion,syntax-suger
?
操作符是如何“抽象”错误类型与“短路”函数的
-
首先,
?
操作符是被用来勾连·函数体内Result<T, E1>
·与·函数返回值类型Result<T, E2>
·的【语法糖】。它的“去糖”展开式如下: -
其次,就功能而言,
?
操作符相当于“温和版”的Result::unwrap()
成员方法。即,- 成功线 —— 取出
?
操作符前Result<T, E1>
的内部值T
和作为表达式的返回结果。 - 失败线 ——
- 先将
?
操作符前Result<T, E1>
中的E1
·类型转换·为【函数】返回值类型Result<T, E2>
中的E2
。- 这一步要求
E2
实现了From<E1> trait
。
- 这一步要求
- 再“短路”当前执行函数和退出函数。注意:
- 这里是结束当前执行函数,而不像
Result::unwrap()
“粗暴”地结束当前执行线程。要不,怎么说?
“温和”呢! - 若开启了
Cargo.toml [package] panic = "abort"
,后者Result::unwrap()
还会造成内存泄露。
- 这里是结束当前执行函数,而不像
- 先将
- 成功线 —— 取出
-
接着,重点来了。【函数】返回值类型
Result<T, E2>
中的E2
是一个“同时兼容于所有其它错误类型的、统一的【“抽象”错误类型】”。按其“抽象”方式分为如下两种情况:- 静态分派(抽象):[例程1]
E2
是实现了From<E1> trait
的任何具体类型。即,E1
可被类型转换为E2
类型。【类型转换】是其底层机制。- 而且,不强制要求
E2
再显示地实现Error trait
。 - 这一块是我曾经的知识盲点
- 动态分派(抽象):[例程2]
E2
就是Box<dyn Error>
,因为【标准库】给Box<T>
实现了From<Error> trait
。其本质也是【类型转换】。- 这个,我一直以来使用得比较多。
上面两种方式都能把·从函数体内抛出的·不同类型的·错误,经由
?
操作符,收拢于“一处”。- 前者的“一处”是(类型转换至)一个具体类型 —— 静态分派;
- 后者的“一处”是(类型转换至)
trait Object
—— 动态分派。
在这里,我把【类型转换】称为“抽象”是否有些牵强呀? 毕竟,其基础原理与
oop
中的【抽象】不太一样。 - 静态分派(抽象):[例程1]
-
最后,借助于
Option::ok_or(_)
或Option::ok_or_else(FnOnce)
,Option<T>
也能与?
操作符搭配使用。即,[例程3]- 先将
Option<T>
类型转换为Result<T, E>
- 再搭配
?
操作符语法糖
- 先将
1
共 1 条评论, 1 页
评论区
写评论感谢大佬的贡献,为了 Rust 的普及。