上级特征的默认实现

时间:2020-04-08 19:31:36

标签: rust traits

我有一个特征( Select * From tabl1 where Date = '04-MAR-2020' FETCH FIRST 1 ROW ) UNION ALL ( Select * From tabl1 where Date = '05-MAR-2020' FETCH FIRST 1 ROW ) ,具有功能(select object_name from user_objects where object_type = 'TABLE' order by object_name fetch first 1 row only) UNION ALL (select object_name from user_objects where object_type = 'VIEW' order by object_name fetch first 1 row only); 。我希望每个MyGoodTrait的实现者也实现label(&self) -> &strMyGoodTrait。但是,我不一定需要DisplayFromStr才能成为Display的特征。我宁愿以某种方式使用FromStrMyGoodTrait的默认实现,它们将在内部使用Display中的FromStr函数。这样,label的每个实现者都将免费获得MyGoodTraitMyGoodTrait,就像这些特征有默认实现一样。

这是一个与我想要执行的操作类似的示例,但是无法编译:

Display

是否有一种方法可以编写FromStruse 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 的默认实现,这样我就不必为实现Display的每个结构重复代码?

注意:我的实际用例是我有一个特征,该特征具有FromStrMyGoodTrait作为超特征。我特质的实现者将用作映射中的键,并且我将序列化为JSON,因此我需要将实现者序列化为String。因此,这可能是XY Problem

的示例

1 个答案:

答案 0 :(得分:2)

TL; DR:您不能。


您无法为FromStr实现dyn SomeTrait,因为它有一个返回Result<Self, _>的方法,因此您只能为在编译时知道大小的类型实现它。特质对象不是这种情况。

您真正想要的是

impl<T: MyGoodTrait> FromStr for T

但是现在您可能违反了孤立规则。如编译器所解释:

只有在至少一种实施本地特征的类型是本地的情况下,才能实现该特征。 对于类型参数,只能实现当前包装箱中定义的特征。

但是如果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())
    }
}

或者您可以将其实现为任何特定的本地类型:

impl FromStr for A {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self::new())
    }
}