MikeTheSapien
MikeTheSapien

Reputation: 297

How do I access "private" struct's field from other files in Rust?

As advised by my lead programmer, who's not knowledgeable in Rust but knows a lot about OO languages like Java, C#, and such, I should separate the functions and associated methods of a particular "class," in Rust it's more or less a struct, from its model or definition to another file. But I had trouble accessing a struct's field/data member from another file. It feels icky to just attach pub before every struct field's name.

// some_model.rs
// This feels icky
pub struct SomeStruct {
    pub name: String,
    pub id: u32,
}

Just so other files could access the aforementioned struct above

// some_adapter.rs
impl SomeStruct {
    pub fn get_id(&self) -> u32 {
        self.id
    }

    pub fn get_name(&self) -> &'static str {
        self.name
    }

    pub fn new(name: &'static str, id: u32) -> Self {
        SomeModel {
            name,
            id
        }
    }
}

So how does one access such fields from a different file?

Upvotes: 2

Views: 6219

Answers (1)

MikeTheSapien
MikeTheSapien

Reputation: 297

Warning

Based from the comments I've received, I'll put this at the top

THIS IS AN UN-RUSTY SOLUTION

If your lead programmer says you should do the following, or do what's indicate in the question, protest and show them this post.

Proposed Answer

I've scoured the net for some answers, every link is a piece of the whole puzzle. See the references below the post. And eventually, I think I found an apt solution, without using the much warned include! macro.

I used the following syntax profusely:

Syntax
Visibility :
     pub
   | pub ( crate )
   | pub ( self )
   | pub ( super )
   | pub ( in SimplePath )

At first glance it was confusing for me, and for the others like me who might be perplexed as well, I had posted my findings with a sample code.

The directory, using broot

src                     
├──dal                  
│  ├──adapter           
│  │  └──some_adapter.rs
│  ├──adapter.rs        
│  ├──model             
│  │  └──some_model.rs  
│  └──model.rs          
├──dal.rs               
├──lib.rs               
└──main.rs              

I intended to include numerous sub-directories as well, as I reckoned it might add incidental information to those likely having the same knowledge as I in Rust.

I executed cargo new visibility_sample

dal/model/some_model.rs

// dal/model/some_model.rs
pub struct SomeModel {
    // take note of the following syntax
    pub(in super::super) name: &'static str,
    pub(in super::super) id: u32,
}

dal/adapter/some_adapter.rs

// dal/adapter/some_adapter.rs

use super::super::model::some_model::SomeModel;

impl SomeModel {
    pub fn get_id(&self) -> u32 {
        self.id
    }

    pub fn get_name(&self) -> &'static str {
        self.name
    }

    pub fn new(name: &'static str, id: u32) -> Self {
        SomeModel {
            name,
            id
        }
    }
}

dal/model.rs

// dal/model.rs
pub mod some_model;

dal/adapter.rs

// dal/adapter.rs
pub mod some_adapter;

dal.rs

// dal.rs
pub mod model;
pub mod adapter;

lib.rs

// lib.rs
pub mod dal;

And finally main.rs

// main.rs
use visibility_sample::dal::model::some_model::SomeModel;

fn main() {
    let object = SomeModel::new("Mike", 3);
    println!("name: {}, id: {}", object.get_name(), object.get_id());
}

running cargo run

Compiling visibility_sample v0.1.0 (C:\Users\miked\git\visibility_sample)
Finished dev [unoptimized + debuginfo] target(s) in 1.40s
Running `target\debug\visibility_sample.exe`

name: Mike, id: 3

but if main.rs has the following code:

// main.rs
use visibility_sample::dal::model::some_model::SomeModel;

fn main() {
    let object = SomeModel::new("Mike", 3);
    println!("name: {}, id: {}", object.name, object.id);
}

Powershell prints out Rust compiler's beautiful and informative error printing:

error[E0616]: field `name` of struct `SomeModel` is private
 --> src\main.rs:5:41
  |
5 |     println!("name: {}, id: {}", object.name, object.id);
  |                                         ^^^^ private field

error[E0616]: field `id` of struct `SomeModel` is private
 --> src\main.rs:5:54
  |
5 |     println!("name: {}, id: {}", object.name, object.id);
  |                                                      ^^ private field

error: aborting due to 2 previous errors

I placed "" quotation marks in the title for "private" because I'm not certain whether that word is still applicable with the term I'm trying to convey with my posted solution.

References

https://doc.rust-lang.org/reference/visibility-and-privacy.html

https://users.rust-lang.org/t/implement-private-struct-in-different-files/29407

Move struct into a separate file without splitting into a separate module?

Proper way to use rust structs from other mods

P.S.

Perhaps to those gifted and keen, they can easily understand the solution with a few or even a single link in my references on their own, but to someone like me, I have to read these links a whole lot and repeatedly get back to it for tinkering on my own.

Upvotes: 3

Related Questions