Encapsulation in Dart

Encapsulation is a fundamental principle of object-oriented programming (OOP) that restricts access to certain components of an object and ensures that the internal representation of the object is shielded from outside interference and misuse. In Dart, encapsulation is achieved through the use of access modifiers, primarily by defining properties and methods as private or public.

Key Concepts of Encapsulation

  1. Data Hiding: Encapsulation allows you to hide the internal state of an object from the outside world. This is typically done by making properties private.
  2. Public Interface: You expose a controlled interface for interacting with the object's state through public methods or properties.
  3. Control Over Data: By using getters and setters, you can control how properties are accessed and modified, allowing for validation and encapsulation of logic.

Access Modifiers in Dart

Dart provides two main access levels:

  • Public: Members (properties and methods) are accessible from any part of the program. By default, all members are public unless specified otherwise.
  • Private: Members are accessible only within the file where they are declared. Private members are indicated by a leading underscore (_).

Example of Encapsulation

Here’s an example demonstrating encapsulation in Dart:

Example: Bank Account Class

class BankAccount {
  String _accountNumber; // Private property   
  double _balance; // Private property 
  // Constructor   
  BankAccount(this._accountNumber, this._balance);

  // Public method to get the account number   
  String get accountNumber => _accountNumber;

  // Public method to get the current balance   
  double get balance => _balance;

  // Public method to deposit money   
  void deposit(double amount) {
    if (amount > 0) {
      _balance += amount;
      print('Deposited: \$${amount}');
    } else {
      print('Deposit amount must be positive.');
    }
  }

  // Public method to withdraw money   
  void withdraw(double amount) {
    if (amount > 0 && amount <= _balance) {
      _balance -= amount;
      print('Withdrawn: \$${amount}');
    } else {
      print('Insufficient funds or invalid amount.');
    }
  }
}

void main() {
  // Creating an instance of BankAccount   
  BankAccount account = BankAccount('123456789', 1000.0);

  // Accessing public methods   
  print('Account Number: ${account.accountNumber}'); // Output: Account Number: 123456789   
  print('Initial Balance: \$${account.balance}'); // Output: Initial Balance: $1000.0 
  // Depositing money   
  account.deposit(500); // Output: Deposited: $500   
  print('New Balance: \$${account.balance}'); // Output: New Balance: $1500.0 
  // Withdrawing money   
  account.withdraw(200); // Output: Withdrawn: $200   
  print('Balance after withdrawal: \$${account.balance}'); // Output: Balance after withdrawal: $1300.0 
  // Attempting to withdraw more than the balance   
  account.withdraw(2000); // Output: Insufficient funds or invalid amount. 
  }

Explanation

  1. Private Properties: The properties _accountNumber and _balance are private, meaning they cannot be accessed directly from outside the BankAccount class.
  2. Public Interface: The methods deposit(), withdraw(), and getters for accountNumber and balance serve as the public interface for interacting with the account.
  3. Control Over Data: The deposit() and withdraw() methods include validation logic to ensure that only valid transactions are made. This protects the internal state of the account from invalid operations.

Benefits of Encapsulation

  1. Improved Code Maintenance: Changes to the internal implementation of a class do not affect external code that uses the class, as long as the public interface remains unchanged.
  2. Enhanced Data Integrity: By controlling access and providing validation, encapsulation helps maintain the integrity of the data.
  3. Ease of Use: The public interface simplifies the interaction with complex data structures, making it easier for developers to use the class without needing to understand its internal workings.

Conclusion

Encapsulation is a powerful concept in Dart that enhances the security and integrity of your code by hiding the internal state of objects and exposing a controlled interface for interaction. By using private properties and public methods, you can manage how data is accessed and modified, ensuring that your objects remain robust and maintainable. Understanding and applying encapsulation will help you write cleaner and more effective Dart applications.

PLAY QUIZ

What is encapsulation in object-oriented programming?

A method for creating multiple instances of a class.

A principle that restricts access to certain components of an object.

A technique for defining global variables.

A way to increase the speed of a program.