Encapsulation is one of the core principles of object-oriented programming (OOP). It involves bundling data (variables) and methods that operate on that data into a single unit, usually a class, while restricting direct access to some of the object’s components. We prevent unauthorized access and enhance code maintainability and flexibility. In Dart, encapsulation uses private variables, getters, setters, and access control mechanisms. In this post, we will explore these topics in detail with practical examples.
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 is Encapsulation?
Encapsulation in Dart, on the other hand, refers to protecting an object’s internal state from unintended interference and misuse by external code. To achieve this, class properties are made private, while public methods are provided to access and update these properties safely.
Key Concepts of Encapsulation in Dart:
-
Private Variables: To begin with, data within a class can be made private by using the underscore (
_
) prefix. - Getters and Setters: Additionally, getters and setters are utilized to access and modify private data.
-
Access Modifiers: Unlike other languages, Dart does not have
public
,protected
, orprivate
keywords. Instead, it uses underscores (_
) to define private access within libraries.
Private Variables
In Dart, any variable or method prefixed with an underscore (_
) is considered private to its library. Consequently, this approach effectively hides the internal state of a class from other parts of the code.
Example of Private Variables
class Employee {
String _name; // Private variable
int _age; // Private variable
Employee(this._name, this._age);
void displayInfo() {
print('Name: $_name, Age: $_age');
}
}
void main() {
var emp = Employee('Alice', 30);
emp.displayInfo(); // Output: Name: Alice, Age: 30
// emp._name = 'Bob'; // Error: '_name' is private
}
In the above example, _name
and _age
are private variables, and they cannot be accessed directly from outside the class.
Getters and Setters
Example of Getters and Setters
class BankAccount {
double _balance; // Private variable
BankAccount(this._balance);
// Getter for balance
double get balance => _balance;
// Setter for balance
set balance(double amount) {
if (amount >= 0) {
_balance = amount;
} else {
print('Invalid amount');
}
}
}
void main() {
var account = BankAccount(1000);
print('Current balance: \$${account.balance}'); // Output: Current balance: $1000
account.balance = 1500; // Using setter
print('Updated balance: \$${account.balance}'); // Output: Updated balance: $1500
account.balance = -500; // Output: Invalid amount
}
Explanation:
-
Getter: Allows reading the value of
_balance
. -
Setter: Allows modifying the value of
_balance
with validation logic.
Benefits of Encapsulation
Encapsulation offers several benefits, including:
- Data Protection: Prevents unauthorized access to data by restricting access to private members. Consequently, this enhances the overall security of the system.
- Code Maintainability: Changes to a class’s implementation do not affect the external code that uses the class. Therefore, this results in a more manageable and adaptable codebase.
- Flexibility and Reusability: Internal implementation can be modified without affecting the code that uses the object, which in turn enhances both flexibility and reusability. Thus, it allows for easier updates and integration with other components.
- Improved Security: Sensitive data is hidden and protected, reducing the risk of unintended interference. As a result, this boosts the overall security of the system.
Encapsulation with Immutable Objects
Dart allows the creation of immutable objects using final
variables. This ensures that once an object is created, its state cannot be changed.
Example of Encapsulation with Immutable Objects
class Student {
final String _name;
final int _age;
const Student(this._name, this._age);
String get name => _name; // Getter
int get age => _age; // Getter
}
void main() {
var student = Student('Bob', 20);
print('Name: ${student.name}, Age: ${student.age}'); // Output: Name: Bob, Age: 20
// student.name = 'Alice'; // Error: The setter 'name' isn't defined
}
Explanation:
-
Immutable Objects: The
Student
class is immutable because its properties arefinal
and do not have setters.
Encapsulation in Libraries
In Dart, the underscore (_
) makes a variable or method private to its library. As a result, this allows encapsulation to extend beyond a single class and apply to an entire library.
Example of Library-Level Encapsulation
File: library1.dart
// library1.dart
class LibraryClass {
String _secret = "This is private to the library";
void showSecret() {
print(_secret);
}
}
File: main.dart
// main.dart
import 'library1.dart';
void main() {
var lib = LibraryClass();
lib.showSecret(); // Output: This is private to the library
// print(lib._secret); // Error: '_secret' isn't accessible from outside the library
}
Explanation:
-
Library-Level Encapsulation: The
_secret
variable is private tolibrary1.dart
and cannot be accessed inmain.dart
.
Best Practices for Encapsulation
-
Use Private Variables for Sensitive Data: Always mark sensitive data as private using an underscore (
_
). - Use Getters and Setters: Instead of providing direct access to class fields, use getters and setters to control and validate data access.
- Minimize the Exposure of Internal State: Only expose what is necessary for the external use of the class.
- Follow the Principle of Least Privilege: Give access to data and methods only to the extent necessary for a class to perform its function.
Conclusion
Encapsulation is a powerful feature in Dart that, moreover, helps in protecting the internal state of an object and ensuring data integrity. By utilizing private variables, getters, setters, and library-level encapsulation, developers can create secure and maintainable codebases. Therefore, understanding and applying encapsulation effectively is crucial for writing robust object-oriented programs.
Happy Coding…!!!
Leave a Reply