Menu
Coddy logo textTech

Private Fields

Part of the Object Oriented Programming section of Coddy's Rust journey — lesson 10 of 61.

In the previous lesson, you made everything public—the struct, its fields, and its methods. But true encapsulation means controlling how your data can be accessed. In Rust, you can make a struct public while keeping its fields private.

Consider a Wallet that should never have a negative balance. If the field is public, anyone could set it to any value:

// wallet.rs
pub struct Wallet {
    balance: f64,  // No pub = private!
}

impl Wallet {
    pub fn new(initial: f64) -> Wallet {
        Wallet { balance: initial }
    }
}

Notice that Wallet is public, but balance has no pub keyword. This means code outside the module can create a Wallet using the constructor, but cannot directly read or modify the balance field:

// main.rs
mod wallet;
use wallet::Wallet;

fn main() {
    let w = Wallet::new(100.0);
    // println!("{}", w.balance);  // Error! field is private
    // w.balance = -50.0;          // Error! can't access private field
}

This is the foundation of encapsulation—the struct controls its own data. External code must go through the methods you provide, which means you can add validation, logging, or any other logic. The data stays protected from invalid states.

In the upcoming lessons, you'll learn how to provide controlled access to this private data through getter and setter methods.

challenge icon

Challenge

Easy

Let's build a temperature sensor system that demonstrates encapsulation by keeping sensitive data protected inside a module.

You'll create two files to organize your code:

  • sensor.rs: Define a TemperatureSensor struct with two fields: location (String) and reading (f64). The struct should be public so it can be used from other files, but keep both fields private—external code shouldn't be able to directly access or modify the sensor's data. Add a public new constructor that takes a location name and an initial temperature reading.
  • main.rs: Bring in your sensor module and create a TemperatureSensor using the constructor. Since the fields are private, you won't be able to print them directly—instead, print a confirmation message showing that the sensor was created successfully.

This challenge focuses on the core concept of private fields: the struct is accessible, but its internal data is protected. External code can only interact with the sensor through the methods you provide (in this case, just the constructor).

Your output should follow this exact format:

Sensor created for: {location}

To access the location for printing, you'll need to have your new function print this message before returning the sensor, since the field itself is private.

For example, if you create a sensor with location "Kitchen" and reading 22.5, the output would be:

Sensor created for: Kitchen

You will receive two inputs: the location name and the initial temperature reading.

Try it yourself

mod sensor;

use sensor::TemperatureSensor;

fn main() {
    // Read input
    let mut location = String::new();
    std::io::stdin().read_line(&mut location).expect("Failed to read line");
    let location = location.trim().to_string();
    
    let mut reading_str = String::new();
    std::io::stdin().read_line(&mut reading_str).expect("Failed to read line");
    let reading: f64 = reading_str.trim().parse().expect("Failed to parse reading");
    
    // TODO: Create a TemperatureSensor using the constructor
    // The new function will handle printing the confirmation message
    
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming