Menu
Coddy logo textTech

Getters & Setters Depth

Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 33 of 110.

Getters and setters become powerful tools for encapsulation when combined with private fields. They let you expose a clean public interface while keeping full control over how data is accessed and modified.

A common pattern is pairing a private field with a public getter and a setter that includes validation:

class Temperature {
  double _celsius = 0;
  
  double get celsius => _celsius;
  
  set celsius(double value) {
    if (value < -273.15) {
      _celsius = -273.15;  // Absolute zero minimum
    } else {
      _celsius = value;
    }
  }
}

Setters can enforce business rules, ensuring your object never enters an invalid state.

You can also create computed getters that derive values from private data:

class Rectangle {
  double _width;
  double _height;
  
  Rectangle(this._width, this._height);
  
  double get area => _width * _height;      // Computed
  double get perimeter => 2 * (_width + _height);
  
  double get width => _width;
  set width(double value) {
    if (value > 0) _width = value;
  }
}

Sometimes you want read-only access. Simply provide a getter without a setter:

class Order {
  final DateTime _createdAt = DateTime.now();
  
  DateTime get createdAt => _createdAt;  // Read-only
}

This pattern gives external code visibility into the data while preventing any modifications - the private field combined with only a getter creates true read-only access.

challenge icon

Challenge

Easy

Let's build a product inventory system that showcases the power of getters and setters for controlling data access. You'll create a class that protects its internal data while providing computed properties and validation.

You'll organize your code into two files:

  • product.dart: Define a Product class that manages inventory with proper encapsulation. Your product should have:
    • A public String name
    • A private double _price
    • A private int _quantity
    • A constructor that takes all three values
    • A getter price that returns the private price
    • A setter price that only accepts values greater than 0 (ignore invalid values)
    • A getter quantity that returns the private quantity
    • A setter quantity that only accepts values of 0 or greater (ignore negative values)
    • A computed getter totalValue that returns _price * _quantity
    • A computed getter isInStock that returns true if quantity is greater than 0
    • A read-only getter sku that generates a simple SKU by returning the first 3 characters of the name in uppercase followed by the quantity (e.g., LAP25 for "Laptop" with quantity 25)
    • A method displayProduct() that shows the product details
  • main.dart: Import your product class and demonstrate how getters and setters control access:
    • Create a product named 'Laptop' with price 999.99 and quantity 25
    • Call displayProduct()
    • Print In stock: [isInStock]
    • Print SKU: [sku]
    • Attempt to set the price to -50.0 (should be ignored)
    • Set the price to 899.99 (valid change)
    • Attempt to set the quantity to -10 (should be ignored)
    • Set the quantity to 0 (valid change)
    • Call displayProduct()
    • Print In stock: [isInStock]
    • Print SKU: [sku]

The displayProduct() method should print in this format:

--- Product Info ---
Name: [name]
Price: $[price]
Quantity: [quantity]
Total Value: $[totalValue]

Expected output:

--- Product Info ---
Name: Laptop
Price: $999.99
Quantity: 25
Total Value: $24999.75
In stock: true
SKU: LAP25
--- Product Info ---
Name: Laptop
Price: $899.99
Quantity: 0
Total Value: $0.0
In stock: false
SKU: LAP0

Cheat sheet

Getters and setters combined with private fields provide encapsulation and control over data access.

Private Field with Getter and Setter

class Temperature {
  double _celsius = 0;
  
  double get celsius => _celsius;
  
  set celsius(double value) {
    if (value < -273.15) {
      _celsius = -273.15;
    } else {
      _celsius = value;
    }
  }
}

Computed Getters

Getters can derive values from private data:

class Rectangle {
  double _width;
  double _height;
  
  Rectangle(this._width, this._height);
  
  double get area => _width * _height;
  double get perimeter => 2 * (_width + _height);
  
  double get width => _width;
  set width(double value) {
    if (value > 0) _width = value;
  }
}

Read-Only Access

Provide a getter without a setter for read-only properties:

class Order {
  final DateTime _createdAt = DateTime.now();
  
  DateTime get createdAt => _createdAt;
}

Try it yourself

import 'product.dart';

void main() {
  // TODO: Create a product named 'Laptop' with price 999.99 and quantity 25

  // TODO: Call displayProduct()

  // TODO: Print "In stock: [isInStock]"

  // TODO: Print "SKU: [sku]"

  // TODO: Attempt to set price to -50.0 (should be ignored)

  // TODO: Set price to 899.99 (valid change)

  // TODO: Attempt to set quantity to -10 (should be ignored)

  // TODO: Set quantity to 0 (valid change)

  // TODO: Call displayProduct()

  // TODO: Print "In stock: [isInStock]"

  // TODO: Print "SKU: [sku]"
}
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