我正在尝试定义一个特征来比较两个给定的参数,并根据实现返回Result
。它有两个泛型,但是当我们实现它时它们可以是任何东西:
pub trait Assert<L: Any + Debug> {
fn compare<R: Any + Debug>(self, target: R) -> AssertResult;
}
现在,当我想实现平等时,我会这样做:
pub struct Equal<L> {
expected: L,
}
impl<L> Equal<L> {
pub fn new(expected: L) -> Equal<L> {
Equal { expected: expected }
}
}
impl<L: 'static + fmt::Debug> Assert<L> for Equal<L> {
fn compare<R: PartialEq<L> + fmt::Debug>(self, target: R) -> AssertResult {
if target == self.expected {
Ok(())
} else {
Err(format!(
"Expected {:?}, received {:?}",
self.expected,
target
))
}
}
}
链接到playground。
我希望能够接受L
和R
之类的内容,但在实施中限制它们。我不确定这是否是正确的方法。
答案 0 :(得分:3)
L
中的Assert<L>
未被特征使用,因此没有用处;我会忽略它。没有这种复杂性,这就是你写的:
pub trait Assert {
fn compare<R: Any + Debug>(self, target: R) -> AssertResult;
}
这是一个合同,上面写着“当一个类型实现Assert
时,它应该提供一个方法compare
,可以使用任何类型的参数调用Any
和{{ 1}}。“
Debug
这是实施impl<L: 'static + fmt::Debug> Assert for Equal<L> {
Assert
合同的协议,其中Equal<L>
是任何类型L
并实施'static
。
Debug
这违反了 fn compare<R: PartialEq<L> + fmt::Debug>(self, target: R) -> AssertResult {
合同,其中说:“应提供一种方法Assert
,可以使用任何类型的参数调用compare
和Any
“。您提供的Debug
方法不满足这些条件,但只能使用实现compare
和PartialEq<L>
的类型的参数调用。
或者,更简洁:你签了一份合同说Debug
并试图提供一个实际上compare<R: Any + Debug>
的产品,并且编译器生气了,因为你没有坚持你的结束合同。
一种可能的纠正(您已经知道)如下所示:
compare<R: PartialEq<L> + fmt::Debug>
一个合同,上面写着“实现pub trait Assert<R> {
fn compare(self, target: R) -> AssertResult;
}
的类型(其中Assert<R>
是任何类型)”应该提供一个方法R
,可以使用{{1}类型的参数调用}}“。
compare
只要R
实施impl<L: fmt::Debug, R: PartialEq<L> + fmt::Debug> Assert<R> for Equal<L> {
和Assert<R>
实施Equal<L>
和L
,就Debug
实施R
的协议
PartialEq<L>
履行Debug
合同:可以在 fn compare(self, target: R) -> AssertResult {
类型的参数上调用的方法Assert
。这种方法的主体可能取决于compare
的知识,因为这是“合同”的条款。
R
和R: PartialEq<L>
的组合确定了trait
必须履行的合同条款。您编写的第一件事建立了一组特定的术语,然后尝试提供不满足这些术语的产品(impl
方法)。上面概述的修补程序修改了术语以包含编写impl
方法所需的所有条件。