【问题标题】:How do I disambiguate traits in Rust?如何消除 Rust 中的特征?
【发布时间】:2017-07-06 15:28:45
【问题描述】:

我想对两种不同类型的对象使用write_fmt 方法:

use std::fmt::Write;
use std::io::Write;

fn main() {
    let mut a = String::new();
    let mut b = std::fs::File::create("test").unwrap();

    a.write_fmt(format_args!("hello"));
    b.write_fmt(format_args!("hello"));
}

使用Write 时出现错误,因为它们的名称相同:

error[E0252]: a trait named `Write` has already been imported in this module
 --> src/main.rs:8:5
  |
7 | use std::fmt::Write;
  |     --------------- previous import of `Write` here
8 | use std::io::Write;
  |     ^^^^^^^^^^^^^^ `Write` already imported
      a.write_fmt(format_args!("hello"));
      b.write_fmt(format_args!("hello"));

或者我收到一条错误消息,说该特征不可用:

error[E0599]: no method named `write_fmt` found for type `std::fs::File` in the current scope
  --> src/main.rs:76:4
   |
76 |    b.write_fmt(format_args!("hello"));
   |      ^^^^^^^^^
   |
   = help: items from traits can only be used if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
   = help: candidate #1: `use std::io::Write;`

【问题讨论】:

    标签: rust


    【解决方案1】:

    你可以直接调用trait方法:

    fn main() {
        let mut a = String::new();
        let mut b = std::fs::File::create("test").unwrap();
    
        std::fmt::Write::write_fmt(&mut a, format_args!("hello"));
        std::io::Write::write_fmt(&mut b, format_args!("hello"));
    }
    

    您也可以选择仅在较小范围内导入特征:

    fn main() {
        let mut a = String::new();
        let mut b = std::fs::File::create("test").unwrap();
    
        {
            use std::fmt::Write;
            a.write_fmt(format_args!("hello"));
        }
    
        {
            use std::io::Write;
            b.write_fmt(format_args!("hello"));
        }
    }
    

    注意,如果选择使用更小的作用域,也可以直接使用write!宏:

    fn main() {
        let mut a = String::new();
        let mut b = std::fs::File::create("test").unwrap();
    
        {
            use std::fmt::Write;
            write!(a, "hello");
        }
    
        {
            use std::io::Write;
            write!(b, "hello");
        }
    }
    

    在任何一种情况下,您都应该处理 Result 返回值。

    另见:

    【讨论】:

      【解决方案2】:

      您可以为use指定别名:

      use std::fmt::Write as FmtWrite;
      use std::io::Write;
      
      fn main() {
          let mut a = String::new();
          let mut b = std::fs::File::create("test").unwrap();
      
          a.write_fmt(format_args!("hello"));
          b.write_fmt(format_args!("hello"));
      }
      

      如果你只是想调用 traits 方法,你甚至可以将它们带入作用域:

      use std::fmt::Write as _;
      use std::io::Write as _;
      
      fn main() {
          let mut a = String::new();
          let mut b = std::fs::File::create("test").unwrap();
      
          a.write_fmt(format_args!("hello"));
          b.write_fmt(format_args!("hello"));
      }
      

      请注意,当不同类型实现具有相同名称的不同特征时,此解决方案有效。如果同一个类型实现了同名的不同trait,则必须使用Shepmaster's answer

      mod foo {
          pub trait Trait {
              fn do_something(&self) {}
          }
      }
      
      mod bar {
          pub trait Trait {
              fn do_something(&self) {}
          }
      }
      
      pub struct Concrete {}
      impl foo::Trait for Concrete {}
      impl bar::Trait for Concrete {}
      
      fn main() {
          let x = Concrete {};
      
          {
              use foo::Trait; // use limited to scope
      
              x.do_something(); // call foo::Trait::do_something
          }
          {    
              foo::Trait::do_something(&x); // complete path to disambiguate
              bar::Trait::do_something(&x); // complete path to disambiguate
          }
          {
              use foo::Trait as FooTrait;
              use bar::Trait;
      
              x.do_something(&x); // ERROR: multiple applicable items in scope
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-15
        • 2016-05-29
        • 2021-05-06
        • 1970-01-01
        • 2022-08-03
        相关资源
        最近更新 更多