在impl块或方法上指定特征绑定是否更好?

时间:2016-03-21 22:12:51

标签: rust traits

假设我想创建一些包含其他泛型类型的类型,如下所示:

struct MyWrapper<T> {
    pub inner: T,
}

现在我希望我的类型有一个方法,如果内部类型满足特定的边界。例如:我想打印它(在此示例中,为简单起见,不使用fmt特征)。为此,我有两种可能性:向impl或方法本身添加绑定。

方法绑定

impl<T> MyWrapper<T> {
    pub fn print_inner(&self) where T: std::fmt::Display {
        println!("[[ {} ]]", self.inner);
    }
}

使用MyWrapper<()>调用此函数时,我得到:

error[E0277]: `()` doesn't implement `std::fmt::Display`
  --> src/main.rs:20:7
   |
20 |     w.print_inner();
   |       ^^^^^^^^^^^ `()` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
   |
   = help: the trait `std::fmt::Display` is not implemented for `()`

Impl Bound

impl<T: std::fmt::Display> MyWrapper<T> {
    pub fn print_inner(&self) {
        println!("[[ {} ]]", self.inner);
    }
}

再次调用不正确,给出:

error[E0599]: no method named `print_inner` found for type `MyWrapper<()>` in the current scope
  --> src/main.rs:19:7
   |
1  | struct MyWrapper<T> {
   | ------------------- method `print_inner` not found for this
...
19 |     w.print_inner();
   |       ^^^^^^^^^^^
   |
   = note: the method `print_inner` exists but the following trait bounds were not satisfied:
           `() : std::fmt::Display` 

我的问题是:什么更惯用?是否存在语义差异(除了具有特征的终身内容,解释here)?除编译器消息之外是否存在差异?

1 个答案:

答案 0 :(得分:3)

一个语义上的区别是,使用方法绑定的类型,您可以部分实现特征:

trait Trait {
    fn f(self) where Self: std::fmt::Display;
    fn g(self);
}

struct Struct<T>(T);

impl<T> Trait for Struct<T> {
    fn f(self) where Struct<T>: std::fmt::Display {
        println!("{}", self);
    }
    fn g(self) {
        println!("Hello world!");
    }
}

fn main() {
    let s = Struct(vec![1]);

    // f is not implemented, but g is
    //s.f();
    s.g();
}

如果您有许多具有不同类型边界的可选方法,这可能会有用,否则这些方法需要单独的特征。