Dart 'Getters & Setters' in detail(Flutter)

Dart 'Getters & Setters' in detail(Flutter)

Getters and setters are special methods that provide explicit read and write access to an object's properties.

Let’s consider the following example:

First, define a class Circle in the circle.dart library:

class Circle {
  double _radius = 0;
  Circle(double radius) {
    if (radius >= 0) {
      _radius = radius;
    }
  }
}Code language: Dart (dart)

The Circle class has a private field called _radius. In the constructor, we check the radius before assigning it to the _radius private field.

Second, use the Circle class in the main.dart file:

import 'circle.dart';

void main() {
  var circle = Circle(10);
}Code language: Dart (dart)

An issue with the Circle class is that you cannot access or modify the _radius private field from the outside of the class.

To fix this, you can make the _radius a property. However, to do so, the caller of the class may do this:

import 'circle.dart';

void main() {
  var circle = Circle(radius: 10);
  circle.radius = -10;
}Code language: Dart (dart)

This is invalid because the radius should not be negative. To resolve this, Dart offers a special method called setter.

Setters

A setter starts with the set keyword and takes a parameter that you can assign to the private field. For example, the following defines a setter that assigns a value to the _radius field:

set radius(double value) {
  if (value >= 0) {
    _radius = value;
  }
  print('Setter was called');
}Code language: Dart (dart)

The radius setter checks if the value is greater than or equal to zero before assigning it to the _radius private field. The print() statement is for illustration purposes.

The following shows the updated version of the Circle class:

class Circle {
  double _radius = 0;
  Circle(double radius) {
    if (radius >= 0) {
      _radius = radius;
    }
  }
  set radius(double value) {
    print('Setter was called.');
    if (value >= 0) {
      _radius = value;
      print('The _radius is $_radius.');
    }
  }
}Code language: Dart (dart)

When you assign a value to the radius, Dart will automatically call the radius setter. For example:

import 'circle.dart';

void main() {
  var circle = Circle(10);
  circle.radius = 100;
}Code language: Dart (dart)

Output:

Setter was called.
The _radius is 100.0.Code language: Dart (dart)

The following code calls the setter that assigns 100 to the _radius field:

circle.radius = 100;Code language: Dart (dart)

Since the setter has a validation logic check, you can reuse it in the constructor of the class as follows:

class Circle {
  double _radius = 0;

  Circle(double radius) {
    this.radius = radius;
  }
  set radius(double value) {
    if (value >= 0) {
      _radius = value;
    }
  }
}Code language: Dart (dart)

Getters

Now, you can use the radius setter to check and set a value for the _radius private field. But you cannot read from it.

The following will result in an error:

import 'circle.dart';

void main() {
  var circle = Circle(10);
  circle.radius = 100;
  // error
  print(circle.radius);
}Code language: Dart (dart)

To access the radius like above, you need to use a getter.

As a setter, a getter is a special method. A getter uses the get keyword before a property name and returns a value.

For example, the following defines the radius getter:

double get radius {
  return _radius;
}Code language: Dart (dart)

Since this getter has only one line of code, you can use the arrow syntax to make it more concise:

double get radius => _radius;Code language: Dart (dart)

The following shows the updated version of the Circle class with a getter and setter:

class Circle {
  double _radius = 0;

  Circle(double radius) {
    this.radius = radius;
  }

  set radius(double value) {
    if (value >= 0) {
      _radius = value;
    }
  }

  double get radius => _radius;
}Code language: Dart (dart)

Now, the main.dart will run successfully:

import 'circle.dart';

void main() {
  var circle = Circle(10);
  circle.radius = 100;
  // success
  print(circle.radius);
}Code language: Dart (dart)

Computed property

By using a getter, you can define a computed property. A computed property is not backed by a dedicated field but instead is computed when called.

The following example uses a getter to define the area as the computed property of the Circle class:

get area => radius * radius * 3.14;Code language: Dart (dart)

By doing this, you can get the area of the circle using this syntax:

circle.area;Code language: Dart (dart)

The following shows the complete Circle class:

class Circle {
  double _radius = 0;

  Circle(double radius) {
    this.radius = radius;
  }

  set radius(double value) {
    if (value >= 0) {
      _radius = value;
    }
  }

  double get radius => _radius;

  get area => radius * radius * 3.14;
}Code language: Dart (dart)

And main.dart file:

import 'circle.dart';

void main() {
  var circle = Circle(10);
  circle.radius = 100;
  print('The area is ${circle.area}');
}Code language: Dart (dart)

Output:

The area is 31400.0

Summary

  • Use getter/setter to provide access to a private field.

  • A computed property is not based on a dedicated field but is computed when called.

THANK YOU!