如何将trait的实现拆分成多个文件?

4
我开始使用ws,希望将Handler特性的实现拆分为多个文件。因此,我在一个名为on_open.rs的文件中编写了以下内容:
impl Handler for Client {
    fn on_open(&mut self, _: Handshake) -> Result<()> {
        println!("Socket opened");
        Ok(())
    }
}

在另一个文件中,on_message.rs
impl Handler for Client {
    fn on_message(&mut self, msg: Message) -> Result<()> {
        println!("Server got message '{}'. ", msg);
        Ok(())
    }
}

在编译时,我遇到了以下错误:
error[E0119]: conflicting implementations of trait `ws::handler::Handler` for type `models::client::Client`:
 --> src\sockets\on_message.rs:9:1
  |
9 | impl Handler for Client {
  | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `models::client::Client`
  |
 ::: src\sockets\on_open.rs:8:1
  |
8 | impl Handler for Client {
  | ----------------------- first implementation here

我希望文件能够分开,这样每个开发人员都可以单独处理一个文件。是否有办法实现这一点,或者我必须在单个文件中拥有完整的特性实现?
2个回答

8

虽然你可以为同一对象拥有多个impl块,但两个完全相同的impl块是不允许存在的,这就是E0119错误所表示的冲突实现的原因:

由于特质不能被多次实现,因此这是一个错误。

(如果特质可以进行专门化,因为它需要任意数量的泛型类型参数,那么情况将非常不同,因为每个专门化都将是一个不同的impl块。然而即使在这种情况下,您也不能重复实现相同的专门化。)

如果您希望将功能拆分成单独的文件,则可以这样做,但方法略有不同于最初想法。您可以将Clientimpl块拆分,而不是Handler的实现,如下面的最小编译示例所示。(在playground中尝试它!)

正如您所看到的,Handler特质在一个地方为Client实现,但是所有Client的实现都拆分成多个文件/模块,并且Handler实现只是对这些实现的引用

mod handler
{
    pub type Result<T> = ::std::result::Result<T, HandlerError>;

    pub struct HandlerError;

    pub trait Handler
    {
        fn on_open(&mut self, h: usize) -> Result<()>;
        fn on_message(&mut self, m: bool) -> Result<()>;
    }
}

mod client
{
    use super::handler::{ self, Handler };

    struct Client
    {
        h: usize,
        m: bool,
    }

    impl Handler for Client
    {
        fn on_open(&mut self, h: usize) -> handler::Result<()>
        {
            self.handle_on_open(h)
        }

        fn on_message(&mut self, m: bool) -> handler::Result<()>
        {
            self.handle_on_message(m)
        }
    }

    mod open
    {
        use super::super::handler;
        use super::Client;

        impl Client
        {
            pub fn handle_on_open(&mut self, h: usize) -> handler::Result<()>
            {
                self.h = h;
                Ok(())
            }
        }
    }

    mod message
    {
        use super::super::handler;
        use super::Client;

        impl Client
        {
            pub fn handle_on_message(&mut self, m: bool) -> handler::Result<()>
            {
                self.m = m;
                Ok(())
            }
        }
    }
}

1
感谢 @Peter 的回答,我按照下面的方式重新编写了我的代码,并且它正常工作: socket.rs
use ws::Handler;
use crate::models::client::Client;
use ws::{Message, Request, Response, Result, CloseCode, Handshake};

impl Handler for Client {
    fn on_open(&mut self, hs: Handshake) -> Result<()> {
        self.handle_on_open(hs)
    }

    fn on_message(&mut self, msg: Message) -> Result<()> {
        self.handle_on_message(msg)
    }

    fn on_close(&mut self, code: CloseCode, reason: &str) {
        self.handle_on_close(code, reason)
    }

    fn on_request(&mut self, req: &Request) -> Result<(Response)> {
        self.handle_on_request(req)
    }
}

sockets/on_open.rs

use crate::models::client::Client;

use crate::CLIENTS;
use crate::models::{truck::Truck};
use ws::{Result, Handshake};

impl Client {
    pub fn handle_on_open(&mut self, _: Handshake) -> Result<()> {
        println!("socket is opened");
        Ok(())
    }
}

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