【发布时间】:2018-11-26 20:11:11
【问题描述】:
我很想知道通过内置反射可以节省多少样板代码。
一点背景
我在结构化日志背后的想法是使用各种小型定制类型将内容与表示分开。而不是非结构化的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 {}
最后是根据 trait 定义的多态日志记录函数:
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 将派生功能“注入”到类型中吗?
【问题讨论】:
-
@Shepmaster 好话:事后看来,问题应该是“[...] 实现 serde::Serialize”,这已经是答案的一半了...
-
我希望这就是你的意思。我认为拥有更准确的标题以吸引未来的搜索者没有任何害处。