当特征和类型都不在此包中时提供实现

时间:2014-06-21 10:30:59

标签: traits rust

我想为基本类型ToHex提供特征serialize(我未定义,来自u8)的实现:

impl ToHex for u8 {
    fn to_hex(&self) -> String {
        self.to_str_radix(16)
    }
}

问题是我得到了这个编译错误:

error: cannot provide an extension implementation where both trait and type are not defined in this crate

我理解这个错误的原因及其逻辑,这是因为特征和原始类型都在我的代码外部。但是,我如何处理这种情况并为ToHex提供u8实施?更一般地说,你如何处理这类问题,在我看来,这个问题必须是常见的,并且应该可以轻松扩展这样的类型?

2 个答案:

答案 0 :(得分:10)

您应该使用newtype结构来执行此操作:

pub struct U8(pub u8)

impl ToHex for U8 {
    fn to_hex(&self) -> String {
        let U8(x) = *self;
        x.to_str_radix(16)
    }
}

但这确实意味着您应该将u8包装到需要执行此转换的U8中:

let x: u8 = 127u8

// println!("{}", x.to_hex());   // does not compile
println!("{}", U8(x).to_hex());

这在性能方面完全免费。

答案 1 :(得分:4)

我意识到这已经差不多一年了,但答案从未被接受过,我想我已经找到了一个替代解决方案,我认为在这里记录会很好。

为了通过特征扩展 u8 的功能,而不是尝试扩展 ToHex ,为什么不创建新的特征呢?

trait MyToHex {
    fn to_hex(&self) -> String;
}

impl MyToHex for u8 {
    fn to_hex(&self) -> String {
        format!("{:x}", *self)
    }
}

然后像这样使用

fn main() {
    println!("{}", (16).to_hex());
}

这样做的好处是,您不必使用新的多余数据类型包装每个 u8 变量。

缺点是您仍然无法在外部函数(即std库或无法控制的函数库)中使用 u8 ,这需要 ToHex trait(弗拉基米尔·马特维耶夫的解决方案适用于这种情况),但是从OP来看,你只想在你的代码中扩展 u8