Dart Encapsulation


Encapsulation in Dart

Encapsulation is one of the core concepts of Object-Oriented Programming (OOP). It refers to the bundling of data (fields) and methods that operate on that data within a single unit, i.e., a class. It also restricts direct access to some of the object's components and only exposes a controlled interface. This helps protect the integrity of the object's state by ensuring that its fields are accessed or modified only in specific ways.

In Dart, encapsulation is achieved by:

  • Private fields: Fields that are prefixed with an underscore (_) to make them private to the class.
  • Public methods (getters and setters): These methods provide controlled access to the private fields.

Benefits of Encapsulation:

  1. Data Hiding: Keeps the internal state of the object hidden from the outside world and only allows controlled access via methods.
  2. Control Over Data: You can validate or transform data before it is set or retrieved.
  3. Increased Security: Prevents unauthorized or unintended modification of an object's state.

Example: Encapsulation in Dart

Let’s create a Person class that demonstrates encapsulation. The class will have a private field _age, and we will provide public methods to get and set the age, but with validation to ensure the age is always a positive value.

class Person { // Private field String _name; int _age; // Constructor to initialize the fields Person(this._name, this._age); // Getter for name String get name => _name; // Setter for name set name(String value) { if (value.isNotEmpty) { _name = value; } else { print('Name cannot be empty'); } } // Getter for age int get age => _age; // Setter for age with validation set age(int value) { if (value >= 0) { _age = value; } else { print('Age cannot be negative'); } } // Method to display person information void displayInfo() { print('Name: $_name, Age: $_age'); } } void main() { // Create an object of Person var person = Person('John', 25); // Access the fields using getter methods print(person.name); // Output: John print(person.age); // Output: 25 // Modify the fields using setter methods person.name = 'Doe'; // Valid change person.age = 30; // Valid change person.age = -5; // Invalid change // Display updated information person.displayInfo(); // Output: Name: Doe, Age: 30 }

Explanation:

  • Private fields: The _name and _age fields are private to the Person class because they are prefixed with an underscore (_).

  • Getters and Setters:

    • The getter methods (name and age) provide read access to the private fields.
    • The setter methods (name and age) allow controlled modification of the private fields. The setter for age ensures that the value is non-negative, and the setter for name ensures it’s not empty.
  • Encapsulation ensures that the Person object’s internal state is protected, and its data is only modified or accessed in a controlled way through the provided methods.

Output:

John 25 Age cannot be negative Name: Doe, Age: 30

Key Points:

  1. The _name and _age fields are encapsulated within the Person class. They cannot be accessed directly from outside the class.
  2. The getter and setter methods control access to these private fields, ensuring that invalid data is not set.
  3. Encapsulation allows for greater flexibility in the future. For example, if you later decide to change how the age field works (e.g., adding additional validation), you can do so without changing the rest of your codebase, as the external code interacts only with the getter and setter methods.

Encapsulation is a powerful mechanism to control and protect data, ensuring that the internal state of objects remains consistent and valid.