如何为一个带参数的 trait 实现另一个 trait

12

我有一个设计问题,当使用类似以下的代码时:

trait MyTrait<K: OtherTrait> { ... }

impl<K: OtherTrait, M: MyTrait<K>> AnyTrait for M { ... }

由于出现了 E207 错误(“类型参数 K 没有被 impl trait、self type 或 predicates 约束”),我无法为此 trait 实现 trait。

找不到解决此错误的方法,所以我采用了这个不太好看的解决方法(冗长且没有内在价值的结构):链接

use std::fmt;
use std::marker::PhantomData;

pub trait MyTrait<K: fmt::Display> {
    fn get_some_k(&self) -> Option<K>;
}

/* // This is my target impl but results in E207 due to K not constrained
impl<K: fmt::Display, S: MyTrait<K>> fmt::Display for S {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.get_some_k().unwrap())
    }
} */
pub struct Ugly<'a, K: fmt::Display, S: 'a + MyTrait<K>>(&'a S, PhantomData<K>);
impl<'a, K: fmt::Display, S: MyTrait<K>> fmt::Display for Ugly<'a, K, S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0.get_some_k().unwrap())
    }
}

fn main() { }

我认为应该有一种更好的方式来实现这种参数化特质。

在标准库中,我没有找到很好的例子(例如,对于像Iterator这样具有关联类型的特质没有Display实现)?


只是想提一下,我遇到了完全相同的问题,但是我没有包装impl在一个Ugly中的奢侈条件,因为MyTrait是向用户公开的公共特质,并要求他们使用一个Ugly会通过增加不必要的复杂性来破坏API。 - mindTree
可能是 为自定义 Trait 提供 Blanket Trait 实现 的重复问题。 - wimh
1个回答

5

这里有一个使用关联类型实现的例子(这意味着您只能为每种类型实现一次MyTrait):

use std::fmt;

pub trait MyTrait {
    type K: fmt::Display;
    fn get_some_k(&self) -> Option<Self::K>;
}

impl<S: MyTrait> fmt::Display for S {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.get_some_k().unwrap())
    }
}

fn main() { }

然而,当像这样澄清时,就变得清楚了,这种方法也行不通,因为您正在为实现“ MyTrait”的所有类型实现“ Display”——这些类型可能具有自己的“ Display”实现。这是被禁止的,因此您会收到E0210错误:
错误:类型参数S必须用作某些本地类型(例如MyStruct )的类型参数;只有在当前crate中定义的traits才能为类型参数实现[E0210]
将其包装在某个东西中——就像您的“ Ugly”所做的那样——是允许这种实现的唯一方法。或者在您自己的crate中实现trait,而不是在其他人的crate中实现(如“ Display”)。

谢谢,我考虑了关联类型,但是我需要每个类型多个实现的情况,否则它就能胜任(我的使用场景不是Display)。 - cheme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接