9.7 Getters and Setters

Methods can provide controlled access (getters) or validated modification (setters) for fields, especially private ones.

pub struct Circle { // Assume this is in a library module
    radius: f64, // Private field
}

impl Circle {
    // Public constructor (associated function)
    pub fn new(radius: f64) -> Option<Self> {
        if radius >= 0.0 { Some(Circle { radius }) } else { None }
    }

    // Public getter
    pub fn radius(&self) -> f64 { self.radius }

    // Public setter with validation
    pub fn set_radius(&mut self, new_radius: f64) -> Result<(), &'static str> {
        if new_radius >= 0.0 {
            self.radius = new_radius; Ok(())
        } else {
            Err("Radius cannot be negative")
        }
    }

    // Calculated property (getter-like)
    pub fn diameter(&self) -> f64 { self.radius * 2.0 }
}

fn main() {
    let mut c = Circle::new(10.0).expect("Creation failed");
    println!("Radius: {}", c.radius());      // Use getter
    println!("Diameter: {}", c.diameter());

    if let Err(e) = c.set_radius(-5.0) {   // Use setter
        println!("Error setting radius: {}", e);
    }

    let _ = c.set_radius(15.0);
    println!("New radius: {}", c.radius());
}

While direct public field access is common within the same module for simple cases, getters/setters are crucial for enforcing invariants and defining stable public APIs across modules.