如何在rust中为另一个trait实现一个trait?

zbwhf8kr  于 2023-03-30  发布在  其他
关注(0)|答案(2)|浏览(164)

我在我的rust项目中有一个名为DataValue的trait,我所有的“DataValue”结构都继承自它,trait本身用于定义共享功能,以便我可以在Box中存储“任何”DataValue。

pub trait DataValue: Debug {
    fn serialize(
        &self,
    ) -> (
        PropertyType, /* serialized type */
        String,       /* serialized value */
    );

    fn ind_clone(&self) -> Box<dyn DataValue>;

    fn deserialize(
        serialized_type: &PropertyType,
        serialized_value: &str,
    ) -> Option<Box<dyn DataValue>>
    where
        Self: Sized;

    fn get_type(&self) -> PropertyType {
        self.serialize().0
    }

    fn get_value(&self) -> Box<dyn std::any::Any>;
}

我希望任何DataValue继承结构体都能实现fmt::Display,并且在我的用例中实现fmt::Display就像连接serialize函数返回的两个值一样简单。我如何为DataValue结构体实现fmt::Display trait,然后定义fmt函数,该函数如上所述接受serialize函数返回的值?
伪码:

impl fmt::Display for DataValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}: {}", self.serialize().0, self.serialize().1)
    }
}
4nkexdtk

4nkexdtk1#

你想要的是一个blanket implementation,可以这样写:

impl<T: DataValue> fmt::Display for T {

    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}: {}", self.serialize().0, self.serialize().1)
    }
}

这样做的问题是,你不能为外来的trait创建一个一揽子的实现,而fmt::Display显然就是一个,所以答案是不能这样做。
相反,你可以为trait包含一个方法display,并返回一个实现Display的 Package 器:

trait DataValue: Debug {
    // …
    fn display(&self) -> DisplayDataValue<&Self>
    {
        DisplayDataValue(self)
    }
}
pub struct DisplayDataValue<T>(T);

impl<T: DataValue> fmt::Display for DisplayDataValue<&'_ T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let ser = self.0.serialize();
        write!(f, "{}: {}", ser.0, ser.1)
    }
}

使用#![feature(return_position_impl_trait_in_trait)],我们可以隐藏该实现,只返回实现Display的内容,而不需要导出DisplayDataValue

fn display(&self) -> impl fmt::Display + '_
ttygqcqt

ttygqcqt2#

您可以在impl块中包含泛型,如下所示:

impl<T: DataValue> fmt::Display for T {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}: {}", self.serialize().0, self.serialize().1)
    }
}

查看Rust手册的第10.2节了解更多细节。

相关问题