Debug School

rakesh kumar
rakesh kumar

Posted on

Visibility controls in Rust

Visibility in Rust (purpose)
Different types of visibility in Rust
Rust code example + output (shows multiple visibility kinds)
Java code example + output (shows multiple visibility kinds)
Struct visibility
Tabular summary of visibility (Rust vs Java)

Visibility in Rust (purpose)

Visibility controls who can access what (structs, functions, modules, fields).
It helps you:

Hide internal implementation (encapsulation)

Expose only stable APIs to other modules/crates

Prevent accidental misuse of private helpers

Organize large projects cleanly with modules and crates
Enter fullscreen mode Exit fullscreen mode

Rust is private by default: anything you define is only accessible inside the same module unless you make it public.

Different types of visibility in Rust

1) private (default)

Accessible only inside the same module (and its child modules can’t access it unless it’s in scope rules; generally: items are private to the module).

2) pub

Accessible from anywhere that can reach the module path (outside module + outside crate too).

3) pub(crate)

Accessible anywhere inside the same crate, but not outside the crate.

4) pub(super)

Accessible to the parent module of the current module.

5) pub(in path)

Accessible only inside a specific module path (like “friend access” scoped to a subtree).

Important related rule (very common confusion)

If a module is private, then even pub items inside it are not reachable from outside.

You must make the module itself pub too if you want external access.

Rust code example + output (shows multiple visibility kinds

mod company {
    pub mod hr {
        // Visible everywhere
        pub fn public_policy() {
            println!("HR: public policy (pub)");
        }

        // Visible only inside this crate
        pub(crate) fn internal_policy() {
            println!("HR: internal policy (pub(crate))");
        }

        // Visible only to parent module: company
        pub(super) fn policy_for_company() {
            println!("HR: policy for company module (pub(super))");
        }

        // Private (default): only inside hr
        fn secret_notes() {
            println!("HR: secret notes (private)");
        }

        // Visible only inside `company` module tree
        pub(in crate::company) fn company_only_policy() {
            println!("HR: company-only policy (pub(in crate::company))");
        }

        pub fn demo_inside_hr() {
            secret_notes(); // ✅ allowed (same module)
        }
    }

    pub fn demo_inside_company() {
        // ✅ company is parent of hr, so pub(super) works
        hr::policy_for_company();

        // ✅ pub(in crate::company) works inside company
        hr::company_only_policy();

        // ✅ pub(crate) works inside crate
        hr::internal_policy();

        // ✅ pub works
        hr::public_policy();

        // ❌ private function not accessible here:
        // hr::secret_notes();
    }
}

fn main() {
    // Accessible because hr is pub and function is pub
    company::hr::public_policy();

    // Accessible because pub(crate) and we're in same crate (main is same crate)
    company::hr::internal_policy();

    // Not accessible because pub(super) only to parent module (company), not to main:
    // company::hr::policy_for_company();

    // Not accessible because pub(in crate::company) only within company module tree:
    // company::hr::company_only_policy();

    // But company can call them internally:
    company::demo_inside_company();

    // This calls private inside hr indirectly:
    company::hr::demo_inside_hr();
}
Enter fullscreen mode Exit fullscreen mode

Expected Output

HR: public policy (pub)
HR: internal policy (pub(crate))
HR: policy for company module (pub(super))
HR: company-only policy (pub(in crate::company))
HR: internal policy (pub(crate))
HR: public policy (pub)
HR: secret notes (private)
Enter fullscreen mode Exit fullscreen mode

Rust (public vs private)

By default, items are private to the module.

Use pub to make them accessible outside the module.

mod account {
    pub fn public_fn() {
        println!("public_fn called");
    }

    fn private_fn() {
        println!("private_fn called");
    }

    pub fn call_private_inside() {
        private_fn(); // OK: same module
    }
}

fn main() {
    account::public_fn();
    account::call_private_inside();

    // account::private_fn(); // ❌ error: private
}
Enter fullscreen mode Exit fullscreen mode

Output

public_fn called
private_fn called
Enter fullscreen mode Exit fullscreen mode

Same program idea in Java (visibility)

Java visibility is mainly at class/member level:

private → only inside the same class

(default) package-private → only inside same package

protected → same package + subclasses

public → everywhere

Java code example + output (shows multiple visibility kinds)

public class Main {

    static class Company {

        static class HR {

            public static void publicPolicy() {
                System.out.println("HR: public policy (public)");
            }

            // package-private (default): same package only
            static void internalPolicy() {
                System.out.println("HR: internal policy (package-private)");
            }

            protected static void policyForCompany() {
                System.out.println("HR: policy for company (protected)");
            }

            private static void secretNotes() {
                System.out.println("HR: secret notes (private)");
            }

            public static void demoInsideHR() {
                secretNotes(); // ✅ allowed
            }
        }

        public static void demoInsideCompany() {
            HR.policyForCompany();  // ✅ allowed (same outer context/package)
            HR.internalPolicy();    // ✅ allowed (same package)
            HR.publicPolicy();      // ✅ allowed
            // HR.secretNotes();     // ❌ not allowed (private)
        }
    }

    public static void main(String[] args) {
        Company.HR.publicPolicy();      // ✅
        Company.HR.internalPolicy();    // ✅ (same file/package)
        Company.demoInsideCompany();    // ✅
        Company.HR.demoInsideHR();      // ✅ (calls private internally)
    }
}
Enter fullscreen mode Exit fullscreen mode

Expected Output

HR: public policy (public)
HR: internal policy (package-private)
HR: policy for company (protected)
HR: internal policy (package-private)
HR: public policy (public)
HR: secret notes (private)
Enter fullscreen mode Exit fullscreen mode

Java (public / private)

Visibility is controlled using public, private, protected, package-private (no keyword).


class Account {
    public void publicFn() { System.out.println("publicFn called"); }
    private void privateFn() { System.out.println("privateFn called"); }

    public void callPrivateInside() {
        privateFn(); // OK: inside same class
    }
}

public class Main {
    public static void main(String[] args) {
        Account a = new Account();
        a.publicFn();
        a.callPrivateInside();

        // a.privateFn(); // ❌ error: private
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

publicFn called
privateFn called
Enter fullscreen mode Exit fullscreen mode

Struct visibility

Rust (struct fields are private by default)

You can make the struct public, but its fields stay private unless marked pub.

mod models {
    pub struct Person {
        pub name: String, // public field
        age: u32,         // private field
    }

    impl Person {
        pub fn new(name: &str, age: u32) -> Self {
            Self { name: name.to_string(), age }
        }

        pub fn age(&self) -> u32 { self.age } // public getter
    }
}

fn main() {
    let p = models::Person::new("Ashwani", 30);
    println!("name={}", p.name);
    println!("age={}", p.age());

    // println!("{}", p.age); // ❌ private field
}
Enter fullscreen mode Exit fullscreen mode

Output

name=Ashwani
age=30
Enter fullscreen mode Exit fullscreen mode

Java (fields can be private; access via getters)

class Person {
    public String name;
    private int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() { return age; }
}

public class Main {
    public static void main(String[] args) {
        Person p = new Person("Ashwani", 30);
        System.out.println("name=" + p.name);
        System.out.println("age=" + p.getAge());

        // System.out.println(p.age); // ❌ private
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

name=Ashwani
age=30
Enter fullscreen mode Exit fullscreen mode

Tabular summary of visibility (Rust vs Java)

Top comments (0)