改进rust代码的35种具体方法-类型(二十三)-避免通配符导入

上一篇文章-改进rust代码的35种具体方法-类型(二十二)-最小化可见度


Rust的use语句从另一个板条箱或模块中提取命名项目,并使该名称无需条件即可在本地模块的代码中使用。表单的通配符导入(或glob导入use somecrate::module::*表示,该模块的每个公共符号都应添加到本地命名空间中。

作为次要版本升级的一部分,外部板条箱可能会将新项目添加到其API中;这被视为向后兼容的更改。

这两个观察结果的结合让人担心,对依赖项的不间断性更改可能会破坏您的代码:如果依赖项添加一个与您已经使用的名称相冲突的新符号,会发生什么?

在最简单的层面上,事实证明这不是问题:通配符导入中的名称被视为优先级较低,因此代码中的任何匹配名称都优先:

use bytes::*;

// Local `Bytes` type does not clash with `bytes::Bytes`.
struct Bytes(Vec<u8>);

不幸的是,仍然有冲突可能发生的情况。例如,考虑依赖项添加新特征并为某种类型实现它的情况:

trait BytesLeft {
    // Name clashes with the `remaining` method on the wildcard-imported
    // `bytes::Buf` trait.
    fn remaining(&self) -> usize;
}

impl BytesLeft for &[u8] {
    // Implementation clashes with `impl bytes::Buf for &[u8]`.
    fn remaining(&self) -> usize {
        self.len()
    }
}

如果新特征中的任何方法名称与适用于该类型的现有方法名称相冲突,那么编译器就无法再明确确定是哪种方法:

let arr = [1u8, 2u8, 3u8];
let v = &arr[1..];

assert_eq!(v.remaining(), 2);

如编译时错误所示:

error[E0034]: multiple applicable items in scope
  --> src/main.rs:40:18
   |
40 |     assert_eq!(v.remaining(), 2);
   |                  ^^^^^^^^^ multiple `remaining` found
   |
note: candidate #1 is defined in an impl of the trait `BytesLeft` for the
      type `&[u8]`
  --> src/main.rs:18:5
   |
18 |     fn remaining(&self) -> usize {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: candidate #2 is defined in an impl of the trait `bytes::Buf` for the
           type `&[u8]`
help: disambiguate the method for candidate #1
   |
40 |     assert_eq!(BytesLeft::remaining(&v), 2);
   |                ~~~~~~~~~~~~~~~~~~~~~~~~
help: disambiguate the method for candidate #2
   |
40 |     assert_eq!(bytes::Buf::remaining(&v), 2);
   |                ~~~~~~~~~~~~~~~~~~~~~~~~~

因此,您应该避免从您无法控制的crate中导入通配符

如果您控制通配符导入源代码,那么先前提到的顾虑就会消失。例如,test模块通常会使用 use super::*;。对于主要使用模块来划分代码的 crate,也可能会从内部模块进行通配符导入。

mod thing;
pub use thing::*;

然而,另一个常见的例外情况是,通配符导入是有意义的。一些 crate 采用惯例,将 crate 的常用项从一个预导模块重新导出,该模块明确地用于通配符导入:

use thing::prelude::*;

虽然理论上同样的担忧也适用于这种情况,但在实践中,这样的前奏模块可能会被精心策划,更高的便利性可能超过未来问题的小风险。

最后,如果您没有遵循此项中的建议,请考虑将通配符导入的依赖项固定到精确版本,这样就不会自动允许对依赖项进行次要版本升级。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值