When creating a struct in Rust it seems like it's difficult to create one without having all of the fields set. For example with the following code
struct Connection {
url: String,
stream: TcpStream
}
You aren't able to set url
without giving stream
as well.
// Compilation error asking for 'stream'
let m = Connection { url: "www.google.com".to_string() };
How are you able to create these references that might be Option<None>
until a later time?
The best I have found is using the Default
trait, but I'd rather not have to create the TcpStream
until a later time than when the struct is initialised. Am I able to do this with something like a Box
?
Hence in case of partially initialized structure, uninitialized member variable of numerical type (char, int, long, float, double) will be initialized to 0, and pointers will be initialized to NULL. Lets take one more case where in class is to be initialized with 8 and name and age is unknown.
When initializing a struct, the first initializer in the list initializes the first declared member (unless a designator is specified) (since C99), and all subsequent initializers without designators (since C99)initialize the struct members declared after the one initialized by the previous expression.
Structure members can be initialized using curly braces '{}'. For example, following is a valid initialization.
An initializer is a special type of function that is used to create an object of a class or struct. In Swift, we use the init() method to create an initializer. For example, class Wall { ... // create an initializer init() { // perform initialization ... } }
One thing you can do is to wrap the TcpStream
in an Option
, i.e. Option<TcpStream>
. When you first construct the struct, it'll be None
, and when you initialize it you make it self.stream = Some(<initialize tcp stream>)
. Wherever you use the TCPStream
, you'll have to check if it's Some
, i.e. if it has already been initialized. If you can guarantee your behavior then you can just unwrap()
, but it's probably better to make a check anyways.
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");
}
}
}
This is similar to what is done in Swift, in case you're familiar with that language.
All fields indeed have to be initialized when creating the struct
instance (there is no null in Rust) so all the memory is allocated.
There is often a dedicated method (like new
) that sets default values for fields which are supposed to be modified at a later stage.
I'd use the Box
when you don't know the size of the field (like Vec
does).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With