我希望有几个具有一些默认实现(硬要求)的特征,相互调用。当然,直接的方法是行不通的,因为性状 A 具有性状 B 作为父项,而性状 B 又具有性状 A 作为父项……海龟一直如此。我应该怎么办? (我无法将这些特征连接在一起,它们应该位于不同的文件中。)
展示问题的非工作代码将是
use std::fmt::Display;
trait A: B + Display {
fn a(&self, count: i32) -> String {
if count == 0 {
String::new()
} else {
format!("[{}]a{}", self, self.b(count - 1))
}
}
}
impl A for String {}
trait B: A + Display {
fn b(&self, count: i32) -> String {
if count == 0 {
String::new()
} else {
format!("[{}]b{}", self, self.a(count - 1))
}
}
}
impl B for String {}
fn main() {
println!("{}", "Hello".to_string().a(3));
}
根据实际的最终目标,通过使用辅助特征和全面实施,可以更轻松地完成您正在做的事情。
简而言之,不要这样做:
trait Foo {
fn foo(&self) {
println!("default foo");
}
}
impl Foo for String {}
然后引入一个
trait HasFoo
并使用它来触发 Foo
的全面实施。看起来像这样:
trait Foo {
fn foo(&self);
}
trait HasFoo {}
impl<T> Foo for T
where
T: HasFoo,
{
fn foo(&self) {
println!("default foo");
}
}
impl HasFoo for String {}
我们可以对您的示例执行相同的操作,通过引入
trait HasAB
来触发 A
和 B
(Playground) 的全面实现:
trait HasAB {}
trait A {
fn a(&self, count: i32) -> String;
}
trait B {
fn b(&self, count: i32) -> String;
}
impl<T> A for T
where
T: HasAB + Display,
{
fn a(&self, count: i32) -> String {
if count == 0 {
String::new()
} else {
format!("[{}]a{}", self, self.b(count - 1))
}
}
}
impl<T> B for T
where
T: HasAB + Display,
{
fn b(&self, count: i32) -> String {
if count == 0 {
String::new()
} else {
format!("[{}]b{}", self, self.a(count - 1))
}
}
}
impl HasAB for String {}