特质实现其父特质的任何替代方式?

时间:2016-12-03 07:14:48

标签: rust traits

我正在为Rust构建一个Raft一致性算法中间件,其架构与copycat类似。我为开发人员编写了一个宏来定义命令方案。宏为用户定义的命令生成具有A函数的特征dispatch,这需要开发人员为其行为实现结构,并且编码器/解码器与此主题无关​​。

特征对象向Server对象注册以使其有效。因为trait A是动态生成的,所以我必须将另一个特征B定义为A的父特征。 ServerB配合使用,可以调用dispatch中定义的A函数。

我尝试了不同的组合,但没有一个有效。

trait B {
    fn dispatch(&mut self, fn_id: u64) -> Vec<u8>;
}

// macro generated trait
trait A: B {
    fn a(&self) -> Vec<u8>;
    fn b(&self) -> Vec<u8>;
    fn dispatch(&mut self, fn_id: u64) -> Vec<u8> {
        match fn_id {
            1 => a(),
            2 => b(),
            _ => {}
        }
    }
}

不幸的是,dispatch中的A功能无法在dispatch中实现B。当我实现A的结构时,编译器仍然要求为dispatch实现B

我还尝试将特征dispatch中的B移动到另一个特征作为B的父特征,但该特征无法实现A

我还审核了https://github.com/rust-lang/rfcs/issues/1024。似乎问题是开放的,但已被抛弃。有没有其他方法可以使这种模式有效?

1 个答案:

答案 0 :(得分:6)

您根本不需要B成为A的超级用户。您可以为任何B添加T: A的一揽子实施。我认为这更接近意图。

解释Rust代码:

trait A: B {

&#34;您可以实施A,但前提是您已实施B。&#34;

trait A {
    //...
}
impl<T: A> B for T {

&#34;如果您实施A,这里是B的免费实施。&#34;

这是完整版:

trait B {
    fn dispatch(&mut self, fn_id: u64) -> Vec<u8>;
}

// macro generated trait
trait A {
    fn a(&self) -> Vec<u8>;  // added &self
    fn b(&self) -> Vec<u8>;
}

impl<T: A> B for T {
    fn dispatch(&mut self, fn_id: u64) -> Vec<u8> {
        match fn_id {
            1 => self.a(),
            2 => self.b(),
            _ => panic!(),   // Needed so that match cases are exhaustive
        }
    }
}

struct S {}

impl A for S {
    fn a(&self) -> Vec<u8> {
        unimplemented!()
    }
    fn b(&self) -> Vec<u8> {
        unimplemented!()
    }
}

Playground