繁体   English   中英

一次为多种类型实现一个特征

[英]Implementing a trait for multiple types at once

我有两个结构和一个特征:

struct A {
    x: u32,
}

struct B {
    x: u32,
}

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

我想使用x为两个结构实现T

有没有办法写出类似的东西

impl T for A, B {
    fn double(&self) -> u32 {
        /* ... */
    }
}

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

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

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

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

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

trait 不能公开字段/属性,只能公开相关的类型、常量和函数,因此Xed需要x的 getter(不需要称为x )。

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

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

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

使用duplicate属性宏,您可以执行以下操作:

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,
}

或者,如果您出于某种原因需要两个具有相同实现的相同结构(此时我们应该开始质疑为什么我们需要两个结构: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::*};

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

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
    }
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM