-2

对不起,如果以下答案是直截了当的,但我似乎无法理解。

我需要创建一个 swarm 并将 swarm 返回到主函数,但我不知道如何返回一个通用结构,例如“P2p”结构。

特征用于抽象方法,因此我不能声明一个来抽象结构的属性。

ps: swarm 是 struct ExpandedSwarm<"依赖于行为和传输的东西">

pps:感谢您的任何意见。


fn create_swarm<T>() -> Result<T, Box<dyn Error>> {
    let local_key = identity::Keypair::generate_ed25519();
    let local_peer_id = PeerId::from(local_key.public());

    println!("Local peer id --> {}", local_peer_id);

    let transport = block_on(libp2p::development_transport(local_key))?;
    let behaviour = Ping::new(PingConfig::new().with_keep_alive(true));
    let local_swarm = Swarm::new(transport, behaviour, local_peer_id);
    
    let p = P2p::new(local_swarm);

    Ok(p)
}


struct P2p <T> {
    swarm: T
}

impl <T> P2p<T> {
    pub fn new(swarm: T) -> Self {
        return Self{swarm}
    }
}


4

2 回答 2

0

通用参数由调用者选择。这不是这里的情况:因为你的函数自己创建了 swarm,所以函数强加了返回类型。根据您的实际用例,有不同的可能解决方案:

如果调用者不需要能够选择返回类型

只需删除泛型并为您的函数使用常量类型:

fn create_swarm() -> Result<P2p<Swarm>, Box<dyn Error>> {

如果有多种 swarm 类型并且调用者必须能够在编译时进行选择:

您需要一种通用方法来创建适当类型的 swarm,这意味着您需要某种SwarmBuildertrait 来定义newswarms 的功能:

trait SwarmBuilder {
    fn new (t: Transport, b: Behaviour, i: PeerId) -> Self;
}

impl SwarmBuilder for Swarm {
    fn new (t: Transport, b: Behaviour, i: PeerId) -> Self {
        Swarm::new (t, b, i)
    }
}

fn create_swarm<T: SwarmBuilder>() -> Result<P2p<T>, Box<dyn Error>> {
    let local_key = identity::Keypair::generate_ed25519();
    let local_peer_id = PeerId::from(local_key.public());

    println!("Local peer id --> {}", local_peer_id);

    let transport = block_on(libp2p::development_transport(local_key))?;
    let behaviour = Ping::new(PingConfig::new().with_keep_alive(true));
    let local_swarm = T::new(transport, behaviour, local_peer_id);
    
    let p = P2p::new(local_swarm);

    Ok(p)
}

如果有多种 swarm 类型并且调用者必须能够在运行时进行选择:

您需要一个 trait 来定义所有 swarms 共有的行为,并且您需要返回一个装箱的 trait 对象而不是显式类型:

fn create_swarm() -> Result<P2p<Box<dyn SwarmTrait>>, Box<dyn Error>> {
于 2021-08-17T07:06:05.190 回答
0

如果您的所有 swarm 类型都实现了相同的 trait,例如Swarmer,您可以将其装箱,将P2pswarm 类型设置为 aBox<dyn Swarmer>并返回类型Result<P2p, Box<dyn Error>>

否则,您需要考虑如何抽象它。函数中的每个变量都create_swarm必须具有在编译时已知的固定类型。这可以是某种特征对象(装箱或其他),但您永远无法返回任意类型的对象。例如,transportwill 的每个实例都需要有一个固定的、可识别的类型,这将决定local_swarm(假设它是通用的)的类型,因此p.

如果您确实需要一个可以稍后向下转换为适当的具体类型的任意对象,则可以使用Box<dyn Any>(假设您的类型实现Any)。这就像 C's void *,并且在您需要在协作函数之间传递不同类型的不透明数据以及它们之间的一些遗忘函数时非常有用。但是,您将无法真正调用任何类型的Swarm特定方法。

于 2021-08-17T01:06:01.950 回答