How do I disambiguate traits in Rust?

前端 未结 2 1014
我寻月下人不归
我寻月下人不归 2020-11-28 15:18

I want to use the write_fmt method on two different types of object:

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

fn main() {
    let mut a = Strin         


        
相关标签:
2条回答
  • 2020-11-28 15:47

    You can call the trait method directly:

    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"));
    }
    

    You can also choose to only import the trait in a smaller scope:

    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"));
        }
    }
    

    Note that if you choose to use a smaller scope, you can also use the write! macro directly:

    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");
        }
    }
    

    In either case, you should handle the Result return value.

    See also:

    • How to call a method when a trait and struct use the same name?
    0 讨论(0)
  • 2020-11-28 15:53

    You can specify an alias for 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"));
    }
    

    If you just want to call the traits method, you can even just bring them in scope:

    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"));
    }
    

    Be careful, this solution works when different types implement different traits with the same name. If the same type implements different traits with the same name, you must use 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
        }
    }
    
    0 讨论(0)
提交回复
热议问题