我可以为单个结构以不同的方式多次实现相同的特征吗?

Posted

技术标签:

【中文标题】我可以为单个结构以不同的方式多次实现相同的特征吗?【英文标题】:Can I implement the same trait multiple times in different ways for a single struct? 【发布时间】:2018-02-20 09:36:22 【问题描述】:

我想根据情况以两种不同的方式序列化结构,但我面临一个问题:根据我目前的知识,我只能以一种方式序列化结构。

这是我的代码#[derive(Serialize)](自动派生)

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct TransactionContent 
    sender_addr: Vec<u8>,
    sender_pubkey: Vec<u8>,
    receiver_addr: Vec<u8>,
    amount: u32,
    timestamp: i64

我正在使用bincode::serialize 序列化我的结构并使其成为Vec&lt;u8&gt;,并且我想将该结构存储在 JSON 文件中。在序列化为 JSON 时,我想以我自己的方式对其进行序列化,例如为 Vec&lt;u8&gt; 字段返回一个 base58 字符串。

这是我自己的实现:

impl Serialize for TransactionContent 
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    
        let mut state = serializer.serialize_struct("TransactionContent", 5)?;
        state.serialize_field("sender_addr", &self.sender_addr.to_base58())?;
        state.serialize_field("sender_pubkey", &self.sender_pubkey.to_base58())?;
        state.serialize_field("receiver_addr", &self.receiver_addr.to_base58())?;
        state.serialize_field("amount", &self.amount)?;
        state.serialize_field("timestamp", &self.timestamp)?;
        state.end()
    

我不能同时使用上面的代码。如果我使用自动派生,第二个Impl 是不可能的。如果我使用第二个,bincode::serialize 函数将起作用,但不是我想要的(我想使用Vec&lt;u8&gt;

有没有一种方法可以同时使用Impl?比如有条件的Impl

【问题讨论】:

你可以为包装器struct TransactionContentBase58(TransactionContent);实现不同的序列化。它能解决你的问题吗? 【参考方案1】:

不,您不能以多种方式为单一类型多次实现相同的特征。

作为mentioned in a comment,您可以创建一个 newtype 来包装完整数据并在其上实现所需的特征:

use serde::ser::SerializeStruct, Serialize, Serializer; // 1.0.117
use serde_json; // 1.0.59

#[derive(Debug, Serialize)]
struct Real 
    data: Vec<u8>,


struct AsJson<'a>(&'a Real);

impl<'a> Serialize for AsJson<'a> 
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    
        let mut state = serializer.serialize_struct("Thing", 1)?;
        state.serialize_field("data", b"this is some data")?;
        state.end()
    


fn main() 
    let r = Real 
        data: vec![1, 2, 3, 4],
    ;
    println!(":?", serde_json::to_string(&r));
    println!(":?", serde_json::to_string(&AsJson(&r)));

如果你控制了特质

您可以为 trait 添加一个泛型参数并为同一类型多次实现它:

trait Example<T> 

struct Style1;
struct Style2;

impl Example<Style1> for i32 
impl Example<Style2> for i32 

但这并非没有缺点。

另见:

When is it appropriate to use an associated type versus a generic type?

【讨论】:

我明白了。优雅的!谢谢你的回答。

以上是关于我可以为单个结构以不同的方式多次实现相同的特征吗?的主要内容,如果未能解决你的问题,请参考以下文章

Chrome:多次填写相同的表格进行测试

CORBA 应用程序必须以与 ORB 相同的语言实现吗?

相同的变量名,但在两个单独的“ def”函数中具有不同的值。他们不能以某种方式更改代码吗?

执行多个黄瓜特征文件

以编程方式跨不同帐户访问cloudwatch

我们可以使用不同的过滤条件在同一个表字段或列上多次使用相同的聚合函数吗?