Start learning free

LESSON 412 OF 414 · PROJECTS: OBJECT-ORIENTED

Shopping Cart in Rust in Rust

Practice

A shop keeps its orders in a cart. Build two types that work together: a LineItem is one row of the cart (a product, its price and how many were bought), and a Cart holds many rows and adds them up. The cart has line items (composition), it is not one.

LineItem

  • A struct LineItem with fields name: String, price: f64, quantity: i32.
  • fn new(name: &str, price: f64, quantity: i32) -> LineItem builds one (use name.to_string()).
  • fn subtotal(&self) -> f64 returns self.price * self.quantity as f64.

Cart

  • A struct Cart with one field items: Vec<LineItem>.
  • fn new() -> Cart returns a cart with an empty vector.
  • fn add(&mut self, item: LineItem) pushes the item (&mut self because it changes the cart).
  • fn total(&self) -> f64 returns the sum of the subtotals of all items: start let mut sum = 0.0, loop with for item in &self.items, end with sum (no semicolon).

Rules:

  • The total is worked out every time it is asked for, from the items in the cart at that moment. Adding an item later changes the next total.
  • An empty cart has a total of 0.
  • An item with price 5 and quantity 3 has a subtotal of 15.
  • Prices in the driver are whole numbers.

Rust has structs and impl blocks instead of classes. The driver mainFunction() is already in the starter code and prints with as i32 to show whole numbers.

The driver (already in the starter code, don't change it) creates an empty cart, checks one subtotal, then fills a cart and prints the total twice:

fn mainFunction() {
    let empty = Cart::new();
    println!("Empty: {}", empty.total() as i32);
    let apple = LineItem::new("Apple", 5.0, 3);
    println!("Subtotal: {}", apple.subtotal() as i32);
    let mut cart = Cart::new();
    cart.add(apple);
    cart.add(LineItem::new("Bread", 20.0, 3));
    println!("Total: {}", cart.total() as i32);
    cart.add(LineItem::new("Milk", 10.0, 2));
    println!("Total: {}", cart.total() as i32);
}

Expected output:

Empty: 0
Subtotal: 15
Total: 75
Total: 95

Write struct LineItem and its impl first, then struct Cart and its impl.

for item in &self.items { sum += item.subtotal(); }

struct LineItem {
    name: String,
    price: f64,
    quantity: i32,
}
impl LineItem {
    fn new(name: &str, price: f64, quantity: i32) -> LineItem {
        LineItem {
            name: name.to_string(),
            price,
            quantity,
        }
    }
    fn subtotal(&self) -> f64 {
        self.price * self.quantity as f64
    }
}
struct Cart {
    items: Vec<LineItem>,
}
impl Cart {
    fn new() -> Cart {
        Cart { items: Vec::new() }
    }
    fn add(&mut self, item: LineItem) {
        self.items.push(item);
    }
    fn total(&self) -> f64 {
        let mut sum = 0.0;
        for item in &self.items {
            sum += item.subtotal();
        }
        sum
    }
}
fn mainFunction() {
    let empty = Cart::new();
    println!("Empty: {}", empty.total() as i32);
    let apple = LineItem::new("Apple", 5.0, 3);
    println!("Subtotal: {}", apple.subtotal() as i32);
    let mut cart = Cart::new();
    cart.add(apple);
    cart.add(LineItem::new("Bread", 20.0, 3));
    println!("Total: {}", cart.total() as i32);
    cart.add(LineItem::new("Milk", 10.0, 2));
    println!("Total: {}", cart.total() as i32);
}

STEP 1 OF 23
    Ctrl + Enter to check

    Shopping Cart in Rust

    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free