Neo
Neo

Reputation: 3786

Is it possible to make a private variable in Rust?

I'm trying to generate prime numbers. The code needs to store all the generated primes (to generate the next), to have some private functions to help and one public function (generate_next_prime).

In Java or C++, I would write a PrimesGen class, but in Rust there can't be private variables in a struct. In Python I would probably write a PrimesGen module, but in Rust modules can't have variables.

This code compiles and runs:

struct PrimesGen {
    primes_so_far: Vec<i32>,
    next_candidate: i32,
}

impl PrimesGen {
    pub fn new() -> PrimesGen {
        PrimesGen {
            primes_so_far: vec![],
            next_candidate: 2,
        }
    }
}

fn main() {
    let pg: PrimesGen = PrimesGen::new();
    println!("{}", pg.next_candidate);
}

So what do I do?

Upvotes: 30

Views: 26045

Answers (1)

Boiethios
Boiethios

Reputation: 42849

In Rust, a file is implicitly a module. When you put some code in a foo.rs file, if you want to use this code, you must type mod foo; because the name of this file is implicitly the name of the module. The file with the main is not an exception: it is one module (the base module).

Now, inside a module, everything has access to everything. See this little example to be convinced:

struct Foo {
    x: i32, // private
}

struct Bar {}

impl Bar {
    fn foo(f: Foo) {
        let _ = f.x;
    }
}

fn main() {
    let f = Foo { x: 42 };
    Bar::foo(f);
}

Bar can access the private members of Foo: in Rust, the visibility works by module, and not struct. Inside a same module you cannot do something private towards the same module.

So, if you want to make the variable private in your example, put your struct and implementation inside a module:

mod prime {
    pub struct PrimesGen {
        primes_so_far: Vec<i32>,
        next_candidate: i32,
    }

    impl PrimesGen {
        pub fn new() -> PrimesGen {
            PrimesGen {
                primes_so_far: vec![],
                next_candidate: 2,
            }
        }
    }
}

fn main() {
    use prime::*;

    let pg: PrimesGen = PrimesGen::new();
    println!("{}", pg.next_candidate); // error: field is private
}

Upvotes: 45

Related Questions