有没有一种方法可以在多个traits上实现一个trait?

8
为什么这个不起作用:
trait Update {
    fn update(&mut self);
}

trait A {}
trait B {}

impl<T: A> Update for T {
    fn update(&mut self) {
        println!("A")
    }
}

impl<U: B> Update for U {
    fn update(&mut self) {
        println!("B")
    }
}

error[E0119]: conflicting implementations of trait `Update`:
  --> src/main.rs:14:1
   |
8  | impl<T: A> Update for T {
   | ----------------------- first implementation here
...
14 | impl<U: B> Update for U {
   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation

我认为如果类型重叠,它稍后会被检查。

你需要提到编译该代码时出现了什么问题。在这种情况下,由于实现冲突,它无法编译。另请参阅:http://stackoverflow.com/q/35127870/1233251 - E net4
2
这个主题有很多讨论,例如 https://github.com/rust-lang/rfcs/issues/1053。正在进行工作,以使这种或类似的事情成为可能,但目前像这样重叠的实现是不合法的。 - Chris Emerson
即使使用特化,这也行不通。为了理解原因,请考虑一个实现了AB的结构体。当您在其上调用update()时,您会期望什么输出?使用特化,将使用“最具体”的实现,但在这里,AB是完全等效的。 - Peter Hall
1个回答

5
这个程序的输出结果是什么?
struct AAndB {}
impl A for AAndB {}
impl B for AAndB {}

let a_and_b = AAndB {};
a_and_b.update();

有一个不稳定的编译器特性专门化(specialization),你可以在夜间版本中启用它,这样就可以拥有重叠实例,最“专门化”的实例将被使用。

但是,即使启用了专门化,你的示例也无法工作,因为AB是完全等价的,所以你永远无法明确选择一个实例。

只要有一个明显“更专门化”的实例,它就会编译并按预期工作——前提是你正在使用启用了专门化的Rust夜间构建。例如,如果其中一个trait受到另一个trait的限制,则它更加专门化,因此这将起作用:

#![feature(specialization)]

trait Update {
    fn update(&mut self);
}

trait A {}
trait B: A {}

impl<T: A> Update for T {
    default fn update(&mut self) {
        println!("A")
    }
}

impl<U: B> Update for U {
    fn update(&mut self) {
        println!("B")
    }
}

将实现方法指定为default允许另一个更具体的实现定义自己版本的方法。


问题在于,当不同的结构体实现了两个 trait 时,它甚至都不起作用。但如果一个结构体能够同时实现这两个 trait,那就更好了,就像你所写的那样,然后就能够调用这两个 trait。 结构体需要自己 impl Update 并手动调用不太具体的版本,因此这也只是次优解。 - porky11
链接,克里斯·埃默森在其他评论中留下的,描述了未来重叠实例可能如何工作的一些其他潜在增强功能。一些可能性是负界限,或者互斥特征。如果这两个中的任何一个被实现,您可以向编译器保证永远不会出现歧义。 - Peter Hall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接