< 返回版块

qqzj 发表于 2021-04-21 18:08

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

评论区

写评论
munpf 2021-04-21 20:30

你应该看错了,他说的是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的任意类型,这两个完全不是一回事。

Aya0wind 2021-04-21 19:26

这跟面向对象那个继承不一样,这个是指要实现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的任意类型,这两个完全不是一回事。

c5soft 2021-04-21 19:11

Rust不骚,一点也不!不理解Trait继承是因为套用了传统的面向对象的思路。实质上,Rust所谓的“继承”没有父子关系。trait B: A {...}在这里B不是A的子类型 ,trait A与trait B是平等的关系。

trait B: A {
    fn b(&self) {
        println!("{}", "B.b");
    }
}

是下列关系的简写:

trait B where Self:A {
    fn b(&self) {
        println!("{}", "B.b");
    }
}

理解了这点,剩余代码就好理解了

1 共 3 条评论, 1 页