Rust 中具有默认实现的相互递归特征

问题描述 投票:0回答:1

我希望有几个具有一些默认实现(硬要求)的特征,相互调用。当然,直接的方法是行不通的,因为性状 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));
}
recursion rust traits
1个回答
0
投票

根据实际的最终目标,通过使用辅助特征和全面实施,可以更轻松地完成您正在做的事情。

简而言之,不要这样做:

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 {}
© www.soinside.com 2019 - 2024. All rights reserved.