为什么我需要导入特征以使用它为类型定义的方法?

mhr*_*che 17 rust

我有一个非常简单的Rust代码示例,无法编译:

extern crate rustc_serialize;
use rustc_serialize::base64;

fn main() {
    let auth = format!("{}:{}", "user", "password");
    let auth_b64 = auth.as_bytes().to_base64(base64::MIME);
    println!("Authorization string: {}", auth_b64);
}
Run Code Online (Sandbox Code Playgroud)

编译错误:

error[E0599]: no method named `to_base64` found for type `&[u8]` in the current scope
 --> src/main.rs:6:36
  |
6 |     let auth_b64 = auth.as_bytes().to_base64(base64::MIME);
  |                                    ^^^^^^^^^
  |
  = help: items from traits can only be used if the trait is in scope
  = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
          candidate #1: `use rustc_serialize::base64::ToBase64;`
Run Code Online (Sandbox Code Playgroud)

如果我明确导入特征,它可以工作:

extern crate rustc_serialize;

use rustc_serialize::base64::{self, ToBase64};

fn main() {
    let auth = format!("{}:{}", "user", "password");
    let auth_b64 = auth.as_bytes().to_base64(base64::MIME);
    println!("Authorization string: {}", auth_b64);
}
Run Code Online (Sandbox Code Playgroud)

我为什么需要use rustc_serialize::base64::ToBase64;

Chr*_*gan 22

这就是它的方式.在Rust中,特征必须在范围内,以便您能够调用其方法.

至于为什么,碰撞的可能性就是原因.在所有格式的性状std::fmt(Display,Debug,LowerHex,&C)有相同的方法签名fmt.例如; 怎么object.fmt(&mut writer, &mut formatter)办?Rust的答案是"你必须通过在方法范围内具有特征来明确指出."

另请注意错误消息如何表示" 当前作用域中没有为类型`T`找到名为`m`的方法".

请注意,您不具备导入它,如果你想使用特征方法的功能,而不是一个方法:

extern crate rustc_serialize;

use rustc_serialize::base64;

fn main() {
    let auth = format!("{}:{}", "user", "password");
    let auth_b64 = rustc_serialize::base64::ToBase64::to_base64(auth.as_bytes(), base64::MIME);
    //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    println!("Authorization string: {}", auth_b64);
}
Run Code Online (Sandbox Code Playgroud)

  • @Jim它确实:`=注意:以下特征已实现但不在范围内,也许为其添加一个\`use\`:候选#1:\`use rustc_serialize::base64::ToBase64;\`` (4认同)
  • 这是否也允许编译器将剩余的方法排除在发布之外,从而创建更紧凑的程序? (2认同)
  • @Jackalope:如果 trait 只通过静态调度(泛型)使用,那么只会编译使用的代码。如果使用动态调度(trait 对象),那么所有 trait 方法都将被编译。(理论上它可以确定只使用了某些方法,因此从 vtable 中驱逐了未使用的方法,但我不相信采用了这种优化。) (2认同)
  • 为什么编译器不能建议将什么内容带入当前范围? (2认同)