【问题标题】:How are you able to create partially initialised structs?您如何创建部分初始化的结构?
【发布时间】:2015-05-22 05:35:19
【问题描述】:

在 Rust 中创建结构时,如果没有设置所有字段,似乎很难创建一个。比如下面的代码

struct Connection {
    url: String,
    stream: TcpStream
}

如果不提供stream,您也无法设置url

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

您如何才能创建这些可能是Option<None> 的引用,直到以后?

我发现最好的方法是使用Default 特征,但我宁愿在初始化结构之前不必创建TcpStream。我可以用Box 之类的东西来做到这一点吗?

【问题讨论】:

  • 如果不设置所有字段似乎很难创建一个 => 实际上,在安全的 Rust 中这是不可能的:编译器让你诚实。
  • 这是一件好事。不再意外使用 NULL 的东西!更好的是,不会再意外使用非 NULL 但也未初始化的东西!

标签: rust


【解决方案1】:

您可以做的一件事是将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 中所做的。

【讨论】:

  • 谁能解释一下if let Some(ref mut stream) = self.stream {的语法?
  • 当然。那应该是ref stream,我已经修好了。它只是意味着获得了对 Option 中流的引用,而不是完全移动值。如需更多信息,请查看the Rust book
【解决方案2】:

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

当您不知道字段的大小时,我会使用Box(就像Vec 一样)。

【讨论】:

    【解决方案3】:

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

    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
        }
    }
    

    这意味着您不必在代码中乱扔垃圾来检查流是否已设置。

    另见:

    【讨论】:

      猜你喜欢
      • 2016-09-29
      • 1970-01-01
      • 2016-12-11
      • 1970-01-01
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多