你怎么能够创建部分初始化的结构?

时间:2015-05-22 05:35:19

标签: rust

在Rust中创建结构时,在没有设置所有字段的情况下创建结构似乎很困难。例如,使用以下代码

struct Connection {
    url: String,
    stream: TcpStream
}

您也无法在不url的情况下设置stream

// Compilation error asking for 'stream'
let m = Connection { url: "www.google.com".to_string() }; 

如何在以后创建这些可能Option<None>的引用?

我发现的最好的是使用Default特征,但我不必创建TcpStream,直到比结构初始化时更晚。我能用Box吗?

这样做

3 个答案:

答案 0 :(得分:9)

您可以做的一件事是将TcpStream包裹在Option中,即Option<TcpStream>。当你第一次构造结构时,它将是None,当你初始化它时,你将它self.stream = Some(<initialize tcp stream>)。无论您在何处使用TCPStream,都必须检查它是否为Some,即它是否已经初始化。如果您可以保证自己的行为,那么您可以unwrap(),但最好还是进行检查。

struct Connection {
    url: String,
    stream: Option<TcpStream>
}

impl Connection {
    pub fn new() -> Connection {
        Connection {
            url: "www.google.com".to_string(),
            stream: None,
        }
    }

    pub fn initialize_stream(&mut self) {
        self.stream = Some(TcpStream::connect("127.0.0.1:34254").unwrap());
    }

    pub fn method_that_uses_stream(&self) {
        if let Some(ref stream) = self.stream {
            // can use the stream here
        } else {
            println!("the stream hasn't been initialized yet");
        }
    }
}

这与Swift中的内容类似,以防您熟悉该语言。

答案 1 :(得分:3)

创建struct实例(Rust中没有 null )时,确实必须初始化所有字段,以便分配所有内存。 通常有一个专用方法(如new)为设置在以后阶段修改的字段设置默认值。

当您不知道字段的大小时(例如Box),我会使用Vec

答案 2 :(得分:1)

作为Jorge Israel Peña's answer的扩展,可以使用 builder 。构建器具有所有可选字段,并生成不包含Option的最终值:

use std::net::TcpStream;

struct ConnectionBuilder {
    url: String,
    stream: Option<TcpStream>,
}

impl ConnectionBuilder {
    fn new(url: impl Into<String>) -> Self {
        Self {
            url: url.into(),
            stream: None,
        }
    }

    fn stream(mut self, stream: TcpStream) -> Self {
        self.stream = Some(stream);
        self
    }

    fn build(self) -> Connection {
        let url = self.url;
        let stream = self
            .stream
            .expect("Perform actual error handling or default value");
        Connection { url, stream }
    }
}

struct Connection {
    url: String,
    stream: TcpStream,
}

impl Connection {
    fn method_that_uses_stream(&self) {
        // can use self.stream here
    }
}

这意味着您无需检查代码就可以设置流,而无需检查代码。

另请参阅: