How it works...

Until now, in the preceding recipes, we were only looking into modules that had functions that acted as their items. In this recipe, we will create struct items that have an extra level of visibility with their fields.

The visibility, by default, is private and can be changed using the pub keyword. The visibility allows us to hide information when we try to access a modules', items out of the scope of the module.

We created a module named sample_struct using the mod keyword. We created two structs with public visibility, named WhiteBox and BlackBox, using the pub and struct keywords. In both the struct items, we had a generic type T.

In Rust, generic means that the particular unit can accept one or more generic type parameters, <T>. For example, consider fn foo<T>(T) { ... }. Here, T is the argument that is specified as a generic type parameter using <T>, and it allows it to take any argument of any type.

In both structs, we had a field named information, which was tied up with T, which is the argument we received. The only difference is that we mentioned information in WhiteBox as public inside the struct and information inside BlackBox as private by default.

Next up, we created an implementation block for BlackBox where we explicitly specified the generic type T in the impl block. Inside it, we created a method named const_new, which we made publically visible, that accepted the generic type T as an argument and returned a BlackBox struct. The const_new acts as a public constructor for BlackBox, where we wanted to create the data type.

In the main block, we created the WhiteBox structure first and assigned it to a variable named white_box by sample_struct::WhiteBox { information: "public information " }. Here, we were calling the module, creating a complex data structure and printing the white_box, information field, which was delivered in the preceding step. Next, we tried to create a variable with the data structure of BlackBox in a similar manner. This led to an error saying the field name is private. This is the reason why we created a public method const_new, which is a constructor for the BlackBox data type. We performed this step by sample_struct::BlackBox::const_new("classified information ") and assigned it to _black_box.

This passed the argument from main to the impl block and created the structure. In this way, we were able to define a public struct with private fields, but we were still not able to publically access the information field by _black_box.information, as it was a private field originally.

The private members can be accessed by indirect methods in the module. Consider the following code snippet:

pub mod root {
use self::foo::create_foo;
mod foo {
pub struct Foo {
i: i32,
}
impl Foo{
pub fn hello_foo(&self){
println!("Hello foo");
}
}
pub fn create_foo(i: i32) -> Foo{
Foo { i: i }
}
}
pub mod bar {
pub struct Bar {
pub f: ::root::foo::Foo,
}
impl Bar {
pub fn new(i: i32) -> Self {
Bar { f: ::root::foo::create_foo(i) }
}
}
}
}
fn main() {
//still private
//let f = root::foo::create_foo(42);
let b = root::bar::Bar::new(42);
b.f.hello_foo();
}

We expose a public constructor create_foo in the foo module, but the module foo still remains private and we only expose create_foo in root by the use keyword, which means that bar can now create a Foo struct but create_foo is still private outside of root.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.2.157