gpt4 book ai didi

rust - 如何指定特征的所有实现者也必须实现序列化?

转载 作者:行者123 更新时间:2023-11-29 07:54:49 24 4
gpt4 key购买 nike

我很想知道通过内置反射可以节省多少样板文件。

一点背景

我在结构化日志背后的想法是使用各种小型定制类型将内容与表示分开。而不是非结构化的 logger.info("Found a bar with {} foos", bar.foo) 一个使用像 logger.info(FoundBar{ _bar: bar })

我的 Rust-ish 方法

  • 定义一个Log trait
  • 提供调用 Serde 机制以序列化类型(在本例中为 JSON)的默认实现
  • 通过让它们“继承”默认实现来轻松定义可记录类型
  • 利润

定义特征,提供默认实现:

trait Log {
fn to_log(&self) -> String {
serde_json::to_string(&self).unwrap()
}
}

(RLS 已经画出了愤怒的红色波浪线,但请耐心等待)

定义要记录的简单类型:

#[derive(Serialize)]
struct Message {
msg: String,
}

并让它使用默认实现:

impl Log for Message {}

最后是根据特征定义的多态日志记录函数:

fn log(log: &Log) {
println!("serialized = {}", log.to_log());
}

编译器提示:

error[E0277]: the trait bound `Self: _IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` is not satisfied
--> src\main.rs:8:9
|
8 | serde_json::to_string(&self).unwrap()
| ^^^^^^^^^^^^^^^^^^^^^ the trait `_IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` is not implemented for `Self`
|
= help: consider adding a `where Self: _IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` bound
= note: required because of the requirements on the impl of `_IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` for `&Self`
= note: required by `serde_json::ser::to_string`

where Self 建议添加到我的特征函数中只会产生不同的错误(error[E0433]: failed to resolve. Use of undeclared type or module _IMPL_DESERIALIZE_FOR_Message),但是除此之外,将 Serde 的实现细节泄漏到我的代码中似乎是一个坏主意。

我如何可移植地限制我的特征(使用 where?)仅适用于具有正确派生的类型?更好的是,我可以使用 trait 将派生功能“注入(inject)”到类型中吗?

最佳答案

如果您创建一个 MCVEyour problem on the playground ,你会得到一个更准确的错误:

error[E0277]: the trait bound `Self: serde::Serialize` is not satisfied
--> src/lib.rs:6:9
|
6 | serde_json::to_string(&self).unwrap()
| ^^^^^^^^^^^^^^^^^^^^^ the trait `serde::Serialize` is not implemented for `Self`
|
= help: consider adding a `where Self: serde::Serialize` bound
= note: required because of the requirements on the impl of `serde::Serialize` for `&Self`
= note: required by `serde_json::ser::to_string`

按照建议,但使用惯用的 supertrait 语法,回答您的问题:

trait Log: serde::Serialize {
fn to_log(&self) -> String {
serde_json::to_string(&self).unwrap()
}
}

出于对象安全的原因,您需要更改日志功能:

fn log(log: &impl Log) {
println!("serialized = {}", log.to_log());
}

另见:

关于rust - 如何指定特征的所有实现者也必须实现序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53488328/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com