在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
吗?
答案 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
}
}
这意味着您无需检查代码就可以设置流,而无需检查代码。
另请参阅: