Question #51EasyFlutter Basics

Difference between flutter getter and flutter setter

#flutter

Answer

Overview

Getters and Setters are special methods that provide controlled access to class properties. They allow you to read (get) and write (set) private fields with custom logic.


Getter

Definition: A method that retrieves (reads) the value of a property.

Syntax

dart
class Person {
  String _name = 'Alice'; // Private field

  // Getter - read-only access
  String get name => _name;

  // Getter with logic
  String get greeting => 'Hello, $_name!';
}

void main() {
  final person = Person();
  print(person.name);      // Alice (calls getter)
  print(person.greeting);  // Hello, Alice!
}

Key Features

  • Read-only access to private fields
  • Can include custom logic
  • Called like a property (no parentheses)
  • Cannot take parameters
  • Must return a value

Setter

Definition: A method that updates (writes) the value of a property with validation or side effects.

Syntax

dart
class Person {
  String _name = 'Alice';

  // Getter
  String get name => _name;

  // Setter - controlled write access
  set name(String value) {
    if (value.isNotEmpty) {
      _name = value;
    }
  }
}

void main() {
  final person = Person();
  print(person.name);    // Alice

  person.name = 'Bob';   // Calls setter
  print(person.name);    // Bob

  person.name = '';      // Invalid - setter ignores
  print(person.name);    // Bob (unchanged)
}

Key Features

  • Write access with validation
  • Can include business logic
  • Called like a property assignment
  • Takes exactly one parameter
  • No return value

Getter vs Setter Comparison

FeatureGetterSetter
PurposeRead property valueWrite property value
Syntax
text
Type get name => value;
text
set name(Type value) { }
ParametersNoneExactly one
Return typeAny typevoid (no return)
AccessRead-onlyWrite-only
Usage
text
obj.property
text
obj.property = value
Can validateNoYes

Real-World Examples

Example 1: Validation

dart
class User {
  String _email = '';
  int _age = 0;

  // Getter for email
  String get email => _email;

  // Setter with validation
  set email(String value) {
    if (value.contains('@')) {
      _email = value;
    } else {
      throw ArgumentError('Invalid email format');
    }
  }

  // Getter for age
  int get age => _age;

  // Setter with validation
  set age(int value) {
    if (value >= 0 && value <= 150) {
      _age = value;
    }
  }
}

void main() {
  final user = User();

  user.email = 'test@example.com'; // ✅ Valid
  print(user.email);               // test@example.com

  // user.email = 'invalid';       // ❌ Throws ArgumentError

  user.age = 25;                   // ✅ Valid
  print(user.age);                 // 25

  user.age = 200;                  // ❌ Invalid - ignored
  print(user.age);                 // 25 (unchanged)
}

Example 2: Computed Properties

dart
class Rectangle {
  double width;
  double height;

  Rectangle(this.width, this.height);

  // Computed getter (no backing field)
  double get area => width * height;

  double get perimeter => 2 * (width + height);

  // Setter for area updates dimensions proportionally
  set area(double newArea) {
    double scaleFactor = sqrt(newArea / area);
    width *= scaleFactor;
    height *= scaleFactor;
  }
}

void main() {
  final rect = Rectangle(5, 10);

  print(rect.area);       // 50.0 (computed)
  print(rect.perimeter);  // 30.0 (computed)

  rect.area = 100;        // Set new area
  print(rect.width);      // ~7.07
  print(rect.height);     // ~14.14
}

Example 3: Side Effects

dart
class Counter {
  int _count = 0;

  int get count => _count;

  set count(int value) {
    _count = value;
    print('Count updated to $_count'); // Side effect: logging
    _notifyListeners();                 // Side effect: notify observers
  }

  void _notifyListeners() {
    // Notify UI or listeners
  }
}

Example 4: Flutter Widget State

dart
class SliderWidget extends StatefulWidget {
  
  _SliderWidgetState createState() => _SliderWidgetState();
}

class _SliderWidgetState extends State<SliderWidget> {
  double _sliderValue = 0.5;

  // Getter
  double get sliderValue => _sliderValue;

  // Setter with setState
  set sliderValue(double value) {
    setState(() {
      _sliderValue = value.clamp(0.0, 1.0); // Validate range
    });
  }

  
  Widget build(BuildContext context) {
    return Slider(
      value: sliderValue,
      onChanged: (value) {
        sliderValue = value; // Calls setter
      },
    );
  }
}

Read-Only vs Write-Only Properties

Read-Only (Getter Only)

dart
class Circle {
  final double radius;

  Circle(this.radius);

  // Read-only computed property
  double get area => 3.14159 * radius * radius;

  double get circumference => 2 * 3.14159 * radius;
}

void main() {
  final circle = Circle(5);
  print(circle.area);          // 78.54 (can read)
  // circle.area = 100;        // ❌ Error - no setter
}

Write-Only (Setter Only)

dart
class Logger {
  // No getter - write-only
  set logMessage(String message) {
    print('[LOG] $message');
    // Could write to file, send to server, etc.
  }
}

void main() {
  final logger = Logger();
  logger.logMessage = 'User logged in'; // ✅ Can write
  // print(logger.logMessage);          // ❌ Error - no getter
}

Getter/Setter vs Public Fields

Public Field (No Control)

dart
class User {
  String name; // Anyone can read/write

  User(this.name);
}

void main() {
  final user = User('Alice');
  user.name = ''; // ❌ No validation - allows empty name
}

Getter/Setter (Controlled)

dart
class User {
  String _name;

  User(this._name);

  String get name => _name;

  set name(String value) {
    if (value.isNotEmpty) { // ✅ Validation
      _name = value;
    }
  }
}

void main() {
  final user = User('Alice');
  user.name = ''; // Ignored - validation prevents empty name
}

Common Use Cases

Use CaseExample
ValidationEmail format, age range
Computed valuesArea from width/height
LoggingTrack property changes
State updatesTrigger
text
setState()
in Flutter
Data transformationConvert units, format strings
EncapsulationHide internal implementation

Best Practices

✅ DO:

dart
// Use getters for computed properties
double get fullName => '$firstName $lastName';

// Use setters for validation
set age(int value) {
  if (value >= 0) _age = value;
}

// Use private fields with getters/setters
String _email;
String get email => _email;
set email(String value) { _email = value; }

❌ DON'T:

dart
// Don't use getters for expensive operations
double get calculateComplexValue {
  // ❌ Bad - expensive computation
  for (int i = 0; i < 1000000; i++) { ... }
}

// Don't use setters with side effects users don't expect
set name(String value) {
  _name = value;
  saveToDatabase(); // ❌ Unexpected side effect
}

// Don't make everything private
String _publicData; // ❌ If no validation needed, use public field

Getter/Setter in Flutter State Management

GetX

dart
class CounterController extends GetxController {
  int _count = 0;

  int get count => _count;

  set count(int value) {
    _count = value;
    update(); // Notify listeners
  }
}

BLoC

dart
class CounterBloc extends Bloc<CounterEvent, CounterState> {
  int _count = 0;

  int get count => _count; // Getter

  // No setter - use events instead
  void increment() {
    _count++;
    emit(CounterState(_count));
  }
}

Key Takeaways

Getter: Read property with

text
obj.property
(no parentheses)

Setter: Write property with

text
obj.property = value

Use when: You need validation, computed values, or controlled access

Avoid when: Simple public fields suffice (no validation needed)


Resources