我有一个特征 ,MyGoodTrait具有函数label(&self) -> &str。我希望 的每个实现者MyGoodTrait也实现Display和FromStr。然而,我并不一定需要Display和FromStr成为 的超特质MyGoodTrait。我宁愿以某种方式拥有Displayand的默认实现FromStr,它将在内部使用label来自 的函数MyGoodTrait。这样,每个实现者都MyGoodTrait将“免费”获得Display,FromStr就好像这些特征有一个默认实现一样。
这是一个与我想要做的类似的示例,但它无法编译:
use std::str::FromStr;
pub trait MyGoodTrait {
fn new() -> Self;
fn label(&self) -> &'static str;
}
impl FromStr for dyn MyGoodTrait {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new())
}
}
pub struct A {}
impl MyGoodTrait for A {
fn new() -> Self {
A{}
}
fn label(&self) -> &'static str {
"A"
}
}
pub struct B {}
impl MyGoodTrait for B {
fn new() -> Self {
B{}
}
fn label(&self) -> &'static str {
"B"
}
}
// In this hypothetical, A and B now both have `fmt` and `from_str` functions
Run Code Online (Sandbox Code Playgroud)
有没有办法编写Displayand的默认实现FromStr,这样我就不必为实现的每个结构重复代码MyGoodTrait?
注意:我的实际用例是我有一个具有serde::se::Serialize和serde::de::Deserialize作为超级特征的特征。我的特征的实现者将用作映射中的键,并且我会将映射序列化为 JSON,因此我需要将实现者序列化为字符串。所以这可能是XY 问题的一个例子
TL;DR:你不能。
您无法实现FromStrfordyn SomeTrait因为它有一个返回 a 的方法Result<Self, _>,因此您只能为在编译时知道大小的类型实现它,而特征对象则不是这种情况。
你真正想要的是
impl<T: MyGoodTrait> FromStr for T
Run Code Online (Sandbox Code Playgroud)
但现在你可能违反了孤儿规则。正如编译器所解释的:
仅当所实现的至少一种类型是本地类型时,才可能实现外来特征。类型参数只能实现当前包中定义的特征。
FromStr但如果是本地特征,你也可以这样做:
/// Copy of `std::str::FromStr`
trait Foo: Sized {
type Err;
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
impl<T: MyGoodTrait> Foo for T {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new())
}
}
Run Code Online (Sandbox Code Playgroud)
或者您可以为任何特定的本地类型实现它:
impl FromStr for A {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new())
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1882 次 |
| 最近记录: |