一次实现多种类型的特征

时间:2016-08-25 16:18:04

标签: rust

我有两个结构和特征:

UPDATE movieDataset
SET budget=REPLACE(movie_info.info,',','')
WHERE movieDataset.movie_id IN (
  SELECT movie_info.movie_id
  FROM movie_info
  WHERE movie_info.info_type_id=105
  )

我想使用struct A { x: u32, } struct B { x: u32, } trait T { fn double(&self) -> u32; } 为两个结构实现T

有没有办法写出像

这样的东西
x

如果可能,我不想使用宏。

4 个答案:

答案 0 :(得分:12)

为许多具体类型实现一次特征的唯一方法是为已经实现另一个特征的所有类型实现特征。

例如,您可以实现标记特征Xed,然后:

impl<T> Double for T
where
    T: Xed,
{
    fn double(&self) {
        /* ... */
    }
}

然而,Rust的原则是泛型。您在前一个实现中对T唯一了解的是T实现了Xed trait,因此您可以使用的唯一关联类型/函数即将到来来自Xed

特征不能公开字段/属性,只能显示关联的类型,常量和函数,因此Xed需要x的getter(不需要调用x)。< / p>

如果您希望依赖代码的语法(而不是语义)属性,请使用宏。

答案 1 :(得分:4)

使用the duplicate attribute macro,您可以执行以下操作:

use duplicate::duplicate;
#[duplicate(name; [A]; [B])]
impl T for name {
    fn double(&self) -> u32 {
        self.x * 2
    }
}

这将扩展为两个结构的两个相同的实现。 我知道您说过您不想使用宏,但是我将其解释为您不想滚动自己的宏,因此我认为这是一个很好的妥协。

您还可以使用duplicate来避免重复您的结构定义:

use duplicate::duplicate;
#[duplicate(name; [A]; [B])]
struct name {
    x: u32,
}

或者全力以赴,如果您由于某种原因需要两个具有相同工具的相同结构(在这一点上,我们应该开始质疑为什么我们根本需要2个结构:D):

use duplicate::duplicate;
#[duplicate(
     mod_name struct_name; 
     [a]      [A]; 
     [b]      [B];
)]
mod mod_name {
    pub struct name {
        x: u32,
    }
    impl T for name {
        fn double(&self) -> u32 {
            self.x * 2
        }
    }
}
mod a;
mod b;
pub use self::{a::*, b::*};

答案 2 :(得分:3)

创建宏也可以解决您的问题:

struct A {
    x: u32,
}

struct B {
    x: u32,
}

trait T {
    fn double(&self) -> u32;
}

macro_rules! impl_T {
    (for $($t:ty),+) => {
        $(impl T for $t {
            fn double(&self) -> u32 {
                self.x * 2
            }
        })*
    }
}

impl_T!(for A, B);

fn main() {}

答案 3 :(得分:2)

由于结构的内部结构相同/共享公共组件,因此应将它们提取到一个公共结构中,并将公共部分嵌入到父结构中。公共结构将具有特征的“复杂”实现,然后父结构的特征实现将委托给公共实现:

trait T {
    fn double(&self) -> u32;
}

struct A {
    common: Common,
}

impl T for A {
    fn double(&self) -> u32 {
        self.common.double()
    }
}

struct B {
    common: Common,
}

impl T for B {
    fn double(&self) -> u32 {
        self.common.double()
    }
}

struct Common {
    x: u32,
}

impl T for Common {
    fn double(&self) -> u32 {
        self.x * 2
    }
}

任何更好的代码都需要更改语言。两条可能的路径: