Getters and Setters are essential features in Dart that allow for controlled access to class properties, providing a safe way to read and modify private variables. In this post, we’ll explore how getters and setters work in Dart, their benefits, and how to use them effectively to encapsulate and protect data in your applications.
For further information on other topics of Dart, click here.
For an in-depth exploration of other OOP topics in Dart, such as inheritance, polymorphism, and encapsulation etc, click here.
What are Getters and Setters?
Getters and setters are methods that provide access to private properties of a class. In Dart, they are used to control how a variable is read and modified while maintaining the principle of encapsulation. This ensures that internal variables are not directly exposed and can be validated or transformed when accessed or updated.
Key Concepts of Getters and Setters in Dart:
- Getters: Methods used to retrieve or “get” the value of a private property.
- Setters: Methods used to assign or “set” the value of a private property with some validation or conditions.
-
Private Variables: Variables that are prefixed with an underscore (
_
) to make them private to the class or library.
Basic Example of Getters and Setters
In Dart, getters and setters allow controlled access to private variables. Private variables are defined using an underscore (_
), and the class provides public getters and setters for external access.
Example of Getters and Setters
class Rectangle {
double _width;
double _height;
Rectangle(this._width, this._height);
// Getter for area
double get area => _width * _height;
// Setter for width with validation
set width(double value) {
if (value > 0) {
_width = value;
} else {
print('Width must be greater than zero');
}
}
// Setter for height with validation
set height(double value) {
if (value > 0) {
_height = value;
} else {
print('Height must be greater than zero');
}
}
}
void main() {
var rect = Rectangle(5, 10);
print('Area: ${rect.area}'); // Output: Area: 50
rect.width = 7; // Setting new width
print('Updated Area: ${rect.area}'); // Output: Updated Area: 70
rect.height = -2; // Invalid height, triggers validation
// Output: Height must be greater than zero
}
Explanation:
-
Getters: The
get area
method calculates and returns the area of the rectangle. -
Setters: The
set width
andset height
methods update the width and height, with validation to ensure the values are greater than zero.
Private Variables and Encapsulation
Getters and setters play a crucial role in encapsulation, as they provide indirect access to private variables. Private variables are those that are prefixed with an underscore (_
) and cannot be accessed directly from outside the class.
Example of Private Variables with Getters and Setters
class BankAccount {
double _balance = 0.0; // Private variable
// Getter for balance
double get balance => _balance;
// Setter for balance with validation
set balance(double amount) {
if (amount >= 0) {
_balance = amount;
} else {
print('Invalid balance');
}
}
// Method to deposit money
void deposit(double amount) {
if (amount > 0) {
_balance += amount;
} else {
print('Deposit amount must be positive');
}
}
}
void main() {
var account = BankAccount();
account.deposit(500); // Deposit money
print('Current balance: \$${account.balance}'); // Output: Current balance: $500
account.balance = -100; // Invalid balance, triggers validation
// Output: Invalid balance
}
Explanation:
-
Private Variable: The
_balance
variable is private to theBankAccount
class. -
Getter: The
get balance
method retrieves the current balance. -
Setter: The
set balance
method validates that the balance cannot be negative.
Custom Getters and Setters
In Dart, you can create custom logic within getters and setters to add specific behavior when accessing or modifying variables.
Example of Custom Getters and Setters
class Temperature {
double _celsius;
Temperature(this._celsius);
// Getter for Fahrenheit
double get fahrenheit => _celsius * 9 / 5 + 32;
// Setter for Fahrenheit, updates Celsius value
set fahrenheit(double value) {
_celsius = (value - 32) * 5 / 9;
}
}
void main() {
var temp = Temperature(25);
print('Celsius: 25°C, Fahrenheit: ${temp.fahrenheit}°F'); // Output: Celsius: 25°C, Fahrenheit: 77°F
temp.fahrenheit = 86; // Set Fahrenheit
print('Updated Celsius: ${temp._celsius}°C'); // Output: Updated Celsius: 30°C
}
Explanation:
-
Getter: The
get fahrenheit
method converts the temperature from Celsius to Fahrenheit. -
Setter: The
set fahrenheit
method allows you to set the temperature in Fahrenheit, which is then converted back to Celsius.
Benefits of Getters and Setters
Using getters and setters in Dart provides several advantages:
- Data Validation: Setters allow you to validate the data before assigning it to a private variable, ensuring that only valid values are set.
- Encapsulation: By providing indirect access to private variables, getters and setters help maintain the integrity of the class’s internal state.
- Controlled Access: You can add custom logic in getters and setters to control how variables are accessed or modified.
- Flexibility: You can modify the internal implementation of a getter or setter without changing how external code interacts with the class.
Best Practices for Using Getters and Setters in Dart
- Use Getters for Read-Only Access: If a property should not be modified externally, provide only a getter without a corresponding setter.
- Add Validation in Setters: Always validate the values being set to ensure they meet certain criteria.
- Avoid Unnecessary Getters and Setters: Use getters and setters only when they add value to the design. If direct access to a variable is acceptable, then you may not need them.
- Use Getters for Calculated Values: If a property can be derived from other properties, use a getter to calculate and return the value dynamically.
Conclusion
Getters and Setters in Dart provide a powerful mechanism for accessing and modifying private class properties while maintaining the integrity of the class’s internal state. By using getters and setters, developers can ensure controlled access to data, implement validation, and protect the object from unintended modifications. Understanding how to use getters and setters effectively is crucial for writing clean and maintainable Dart code. For further exploration of Dart’s OOP principles, check out our detailed articles.
Happy Coding…!!!
Leave a Reply