Getters and Setters in Dart

Getters and setters in Dart are special methods that provide controlled access to an object's properties. They allow you to define how a property can be read (getter) or modified (setter), enabling encapsulation and validation of data.

Why Use Getters and Setters?

  1. Encapsulation: They help hide the internal representation of an object and expose only what is necessary.
  2. Validation: You can add validation logic in setters to ensure that only valid data is assigned to properties.
  3. Computed Properties: Getters can be used to compute values dynamically based on other properties.

Syntax

Getter Syntax

 

Type get propertyName {
  // Return a value }

Setter Syntax

set propertyName(Type value) {
  // Set the value with validation or logic }

Example: Using Getters and Setters

Basic Example

Here’s a simple example demonstrating how to use getters and setters in a Dart class.

 

class Rectangle {
  double _width;
  double _height;

  // Constructor   
  Rectangle(this._width, this._height);

  // Getter for width   
  double get width => _width;

  // Setter for width   
  set width(double value) {
    if (value > 0) {
      _width = value;
    } else {
      throw ArgumentError('Width must be positive');
    }
  }

  // Getter for height   
  double get height => _height;

  // Setter for height   
  set height(double value) {
    if (value > 0) {
      _height = value;
    } else {
      throw ArgumentError('Height must be positive');
    }
  }

  // Method to calculate area   
  double area() {
    return _width * _height;
  }
}

void main() {
  Rectangle rect = Rectangle(5, 10);
  print('Width: ${rect.width}'); // Output: Width: 5   
  print('Height: ${rect.height}'); // Output: Height: 10  
   print('Area: ${rect.area()}'); // Output: Area: 50 
  // Using setter to modify width   
  rect.width = 8;
  print('New Width: ${rect.width}'); // Output: New Width: 8 
  // Attempting to set a negative value   
  try {
    rect.height = -5; // Throws an error   
    } 
    catch (e) {
    print(e); // Output: Height must be positive   
    }
}

Explanation

  1. Private Properties: The _width and _height properties are private, indicated by the underscore (_), preventing direct access from outside the class.
  2. Getters: The get width and get height methods allow read access to the private properties.
  3. Setters: The set width and set height methods validate input before assigning values to the private properties. If an invalid value is provided, an exception is thrown.
  4. Area Calculation: The area() method calculates the area of the rectangle using the current width and height.

Example: Computed Properties

You can also use getters to create computed properties that derive their values from other properties.

 

class Circle {
  double _radius;

  Circle(this._radius);

  // Getter for radius   double get radius => _radius;

  // Setter for radius   set radius(double value) {
    if (value > 0) {
      _radius = value;
    } else {
      throw ArgumentError('Radius must be positive');
    }
  }

  // Computed property for diameter   
  double get diameter => _radius * 2;

  // Computed property for area   
  double get area => 3.14 * _radius * _radius;
}

void main() {
  Circle circle = Circle(5);
  print('Radius: ${circle.radius}'); // Output: Radius: 5   
  print('Diameter: ${circle.diameter}'); // Output: Diameter: 10   
  print('Area: ${circle.area}'); // Output: Area: 78.5 
  // Changing the radius   
  circle.radius = 10;
  print('New Radius: ${circle.radius}'); // Output: New Radius: 10   
  print('New Diameter: ${circle.diameter}'); // Output: New Diameter: 20   
  print('New Area: ${circle.area}'); // Output: New Area: 314.0 
  }

Explanation

  1. Computed Properties: The diameter and area properties are computed based on the radius. They dynamically calculate their values whenever accessed, providing a convenient way to get derived data without needing to call a method.
  2. Validation: The radius setter ensures that the radius is always a positive value.

Conclusion

Getters and setters are powerful features in Dart that enhance encapsulation and data validation. They allow you to control how properties are accessed and modified while enabling computed properties that can dynamically derive values. By using getters and setters effectively, you can create more robust and maintainable Dart applications.

PLAY QUIZ

What is the primary purpose of using getters and setters in Dart?

To create multiple instances of a class.

To provide controlled access to an object's properties and encapsulate data.

To define static methods within a class.

To automatically generate properties.