RUST / CHAPTER 05

Structs and invariant-preserving methods

Intermediate

Encapsulate valid state and make mutation requirements visible.

By the end of this chapter

  • Use self and borrowed receivers
  • Validate construction and updates
  • Distinguish field privacy from immutability

The idea

A struct groups named fields into a domain value. An impl block supplies associated functions and methods, and the receiver explains how the method uses its instance. &self borrows for inspection, &mut self permits mutation, and self consumes the value unless its type supports copying. Choose the receiver from the operation’s ownership contract instead of adding clones to satisfy the compiler blindly.

Private fields help keep invalid state from being constructed outside the defining module. A constructor can return Option or Result when validation fails, and modifying methods should reject invalid changes before mutation. Privacy alone does not validate values; every accepted transition must preserve the invariant. A small query method exposes needed information without granting callers unrestricted access to the internal representation.

Rust example
struct Stock { remaining: u32 }
impl Stock { fn take(&mut self,n:u32)->bool { if n>self.remaining{return false;} self.remaining-=n; true } }
fn main(){let mut s=Stock{remaining:4}; println!("{}",s.take(5)); println!("{}",s.remaining);}
Result
false
4

The guard returns before subtraction, preserving the count when a request is too large.

Try it yourself

Add a constructor and getter to a bounded counter, then reject updates beyond its capacity.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

Which receiver permits changing a numeric field without consuming the instance?