Getters and Setters
Getters and setters are special methods that allow you to control how properties of a class are accessed and modified. Think of them as gatekeepers - they decide what happens when someone tries to read or write to your object's properties.
What are Getters?
A getter is a method that retrieves the value of a property. It's called automatically when you access a property. Getters are defined using the get keyword.
class Circle {
double _radius = 0; // Private property
// Getter for radius
double get radius => _radius;
// Getter for area (calculated property)
double get area => 3.14159 * _radius * _radius;
}
void main() {
Circle circle = Circle();
circle._radius = 5; // Direct access (not recommended)
print('Radius: ${circle.radius}'); // Using getter
print('Area: ${circle.area}'); // Using calculated getter
}
What are Setters?
A setter is a method that sets the value of a property. It's called automatically when you assign a value to a property. Setters are defined using the set keyword.
class Temperature {
double _celsius = 0;
// Getter for celsius
double get celsius => _celsius;
// Setter for celsius with validation
set celsius(double value) {
if (value < -273.15) {
throw ArgumentError('Temperature cannot be below absolute zero');
}
_celsius = value;
}
// Getter for fahrenheit (calculated)
double get fahrenheit => (_celsius * 9/5) + 32;
// Setter for fahrenheit
set fahrenheit(double value) {
_celsius = (value - 32) * 5/9;
}
}
void main() {
Temperature temp = Temperature();
temp.celsius = 25; // Using setter
print('${temp.celsius}°C = ${temp.fahrenheit}°F');
temp.fahrenheit = 100; // Using fahrenheit setter
print('${temp.celsius}°C = ${temp.fahrenheit}°F');
}
Why Use Getters and Setters?
| Benefit | Description | Example Use Case |
|---|---|---|
| Validation | Check if the input is valid before setting | Age cannot be negative |
| Calculated Properties | Compute values on-the-fly | Area from width and height |
| Data Transformation | Convert data format when getting/setting | Convert temperature units |
| Encapsulation | Hide internal implementation details | Protect sensitive data |
| Logging/Debugging | Track when properties are accessed/modified | Monitor property changes |
Practical Example: Bank Account
Here's a real-world example that demonstrates the power of getters and setters:
class BankAccount {
double _balance = 0;
String _accountNumber;
BankAccount(this._accountNumber);
// Getter for balance
double get balance => _balance;
// Getter for account number (read-only)
String get accountNumber => _accountNumber;
// Setter for balance with validation
set balance(double amount) {
if (amount < 0) {
throw ArgumentError('Balance cannot be negative');
}
_balance = amount;
}
// Calculated getter for account status
String get accountStatus {
if (_balance > 10000) return 'Premium';
if (_balance > 1000) return 'Standard';
return 'Basic';
}
void deposit(double amount) {
if (amount > 0) {
_balance += amount;
}
}
void withdraw(double amount) {
if (amount > 0 && amount <= _balance) {
_balance -= amount;
}
}
}
void main() {
BankAccount account = BankAccount('ACC123456');
account.deposit(5000);
print('Balance: \$${account.balance}');
print('Status: ${account.accountStatus}');
print('Account: ${account.accountNumber}');
}
Key Points to Remember
- Use private properties (starting with
_) with getters and setters for better encapsulation - Getters can return calculated values without storing them
- Setters can validate input before assigning values
- You can have a getter without a setter (read-only property)
- You can have a setter without a getter (write-only property, though rare)
- Getters and setters make your code more maintainable and flexible
Getters and setters are like having a smart doorman for your class properties - they control who gets in, what they can see, and ensure everything stays organized and secure! 🏠🔐