trait A {
fn a(&self) {
println!("{}", "A.a");
}
}
// !!!注意此处
trait B: A {
fn b(&self) {
println!("{}", "B.b");
}
}
struct C {}
// 实现B, 则必须手动实现A
impl B for C {}
// 使用这可以, 能理解
// impl A for C {}
// 问题1: 使用这行也是可以的, 这个令人费解
impl<T: B + ?Sized> A for T {}
// 问题2: 使用这行就不行?
// impl A for dyn B {}
fn main() {
let c = C {};
c.a();
c.b();
}
1
共 3 条评论, 1 页
评论区
写评论你应该看错了,他说的是
impl A for dyn B {}
不行,而且我试了一下,impl B for dyn A {}
和impl A for dyn B {}
都可以通过编译。他不能通过编译,可能是因为和上面一行的impl<T: B + ?Sized> A for T {}
冲突了。--
👇
Aya0wind: 这跟面向对象那个继承不一样,这个是指要实现B trait必须也实现A trait,你这里用trait bound约束了T实现了A,那当然可以impl B for T了。trait B:A,这并不是指A是B的子类型,而是指实现了B trait的所有类型的集合是实现了A trait所有类型集合的子集,而面向对象中的的继承则是仅仅指子类是父类的子类型,换句话说,这两个都不是一个维度的东西。 你要拿java里的interface跟trait还有一定的可比性,拿类继承来类比就完全不对了。 另外dyn A不行,那是因为dyn A跟A本来就不一样,dyn A是一个trait object类型。而使用trait bound约束的T类型则是一个泛型,可以是实现了A trait的任意类型,这两个完全不是一回事。
这跟面向对象那个继承不一样,这个是指要实现B trait必须也实现A trait,你这里用trait bound约束了T实现了A,那当然可以impl B for T了。trait B:A,这并不是指A是B的子类型,而是指实现了B trait的所有类型的集合是实现了A trait所有类型集合的子集,而面向对象中的的继承则是仅仅指子类是父类的子类型,换句话说,这两个都不是一个维度的东西。 你要拿java里的interface跟trait还有一定的可比性,拿类继承来类比就完全不对了。 另外dyn A不行,那是因为dyn A跟A本来就不一样,dyn A是一个trait object类型。而使用trait bound约束的T类型则是一个泛型,可以是实现了A trait的任意类型,这两个完全不是一回事。
Rust不骚,一点也不!不理解Trait继承是因为套用了传统的面向对象的思路。实质上,Rust所谓的“继承”没有父子关系。trait B: A {...}在这里B不是A的子类型 ,trait A与trait B是平等的关系。
是下列关系的简写:
理解了这点,剩余代码就好理解了