簡體   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