G.NAM.02 类型转换函数命名需要遵循所有权语义
【级别】 建议
【描述】
进行特定类型转换的方法名应该包含以下前缀:
| 名称前缀 | 内存代价 | 所有权 |
|---|---|---|
as_ | 无代价 | borrowed -> borrowed |
to_ | 代价昂贵 | borrowed -> borrowed borrowed -> owned (非 Copy 类型) owned -> owned (Copy 类型) |
into_ | 看情况 | owned -> owned (非 Copy 类型) |
以 as_ 和 into_ 作为前缀的类型转换通常是 降低抽象层次 ,要么是查看背后的数据 ( as ) ,要么是分解 (deconstructe) 背后的数据 ( into ) 。
相对来说,以 to_ 作为前缀的类型转换处于同一个抽象层次,但是底层会做更多工作,比如多了内存拷贝等操作。
当一个类型用更高级别的语义 (higher-level semantics) 封装 (wraps) 一个内部类型时,应该使用 into_inner() 方法名来取出被封装类型的值。
这适用于以下封装器:
读取缓存 (BufReader) 、编码或解码 (GzDecoder) 、取出原子 (AtomicBool 、
或者任何相似的语义封装 (BufWriter)。
【正例】
标准库 API 命名有如下示例:
as_str::as_bytes()用于查看 UTF-8 字节的str切片,这是无内存代价的(不会产生内存分配)。 传入值是&str类型,输出值是&[u8]类型。
to_Path::to_str对操作系统路径进行 UTF-8 字节检查,开销昂贵。 虽然输入和输出都是借用,但是这个方法对运行时产生不容忽视的代价, 所以不应使用as_str名称。str::to_lowercase()生成正确的 Unicode 小写字符, 涉及遍历字符串的字符,可能需要分配内存。 输入值是&str类型,输出值是String类型。f64::to_radians()把浮点数的角度制转换成弧度制。 输入和输出都是f64。没必要传入&f64,因为复制f64花销很小。 但是使用into_radians名称就会具有误导性,因为输入数据没有被消耗。
into_String::into_bytes()从String提取出背后的Vec<u8>数据,这是无代价的。 它转移了String的所有权,然后返回具有所有权的Vec<u8>。BufReader::into_inner()转移了 buffered reader 的所有权,取出其背后的 reader ,这是无代价的。 存于缓冲区的数据被丢弃了。BufWriter::into_inner()转移了 buffered writer 的所有权,取出其背后的 writer ,这可能以很大的代价刷新所有缓存数据。
如果类型转换方法返回的类型具有 mut 修饰,那么这个方法的名称应如同返回类型组成部分的顺序那样,带有 mut 。
比如 Vec::as_mut_slice 返回 &mut [T] 类型,这个方法的功能正如其名称所述,所以这个名称优于 as_slice_mut 。
其他参考示例:
【Lint 检测】
| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | Lint Level |
|---|---|---|---|---|
| wrong_self_convention | yes | no | Style | warn |