rust - 如何指定特征的所有实现者也必须实现序列化?
问题描述
我很想知道通过内置反射可以节省多少样板。
一点背景
我在结构化日志背后的想法是使用各种小型定制类型将内容与表示分离。而不是非结构化logger.info("Found a bar with {} foos", bar.foo)
的使用类似的东西logger.info(FoundBar{ _bar: bar })
我的 Rust 风格
- 定义一个
Log
特征 - 提供调用 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
建议添加到我的 trait 函数只会产生不同的错误 ( error[E0433]: failed to resolve. Use of undeclared type or module _IMPL_DESERIALIZE_FOR_Message
),但除此之外,让 Serde 的这个实现细节泄漏到我的代码中似乎是个坏主意。
我如何可移植地限制我的特征(使用where
?)仅适用于具有正确派生的类型?更好的是,我可以使用 trait 将派生功能“注入”到类型中吗?
解决方案
如果您在 playground 上创建问题的MCVE,您会得到更准确的错误:
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());
}
也可以看看:
推荐阅读
- javascript - 验证基于 Javascript 字符串的特定验证规则
- delphi - 在 Firemonkey 中使用大位图会导致错误
- java - mySQL在JavaFX中将重复数据添加到TableView
- html - 如何使用 CCS 和 HTML 将三张卡片对齐在一行中?
- google-bigquery - 运行 dbt 时 BigQuery“超过最大重试次数”
- r - 如何从带有数字指示的列表中获取R中的数据框
- r - 如何用 R 绘制大笔款项?
- django - 当我单击页面时,此错误会引发 Reverse for 'delete' with arguments '('',)' not found。尝试了 1 种模式:['delete/(?P
[0-9]+)$'] - flutter - 如何在 Flutter 中将额外参数传递给 onExpansionChanged?
- python - 在硒中找不到任何元素