Welcome! Today, we begin our exploration of an essential aspect of Dart's object-oriented programming pattern: Encapsulation. This concept forms a protective barrier around an object's data, preventing any external part of the program from accessing it directly. Let's dive into it!
Encapsulation serves three main purposes: it increases the robustness of the code, controls data modification, and provides a structured interface that other parts of the code can interact with. Take a smartphone as an example — you interact with a user-friendly interface without worrying about the complex electronics inside. Similarly, encapsulation hides the complex internals while providing a straightforward interface.
Now, let's move onto Private Data: In Dart, we make data private
by using an underscore _
before its name. This data cannot be accessed directly outside of the class. Let's illustrate this with a Car
class, introducing a private
attribute named _speed
:
Dart1class Car { 2 late int _speed; // private speed attribute 3 4 Car() { 5 this._speed = 0; // Initialize speed with 0 6 } 7}
This class has a private instance variable, _speed
, that's inaccessible directly outside the class. Here's what happens when we try to access _speed
directly from outside:
Dart1void main() { 2 var myCar = Car(); 3 print(myCar._speed); // This line will cause a compilation error 4}
Attempting to compile this code will result in an error similar to: "Error: The getter '_speed' isn't defined for the class 'Car'". Dart's privacy model prevents access to _speed
from outside Car
, enforcing encapsulation.
To safely interact with such private variables, Dart employs getters and setters, which we'll explore next.
Getters and Setters are used to manage access to private
data. In our Car
class, a getter retrieves the _speed
attribute, while a setter changes it as follows:
Dart1class Car { 2 late int _speed; // Private speed attribute 3 4 Car() { 5 this._speed = 0; // Initialize speed with 0 6 } 7 8 // Getter for speed 9 int get speed => _speed; 10 11 // Setter for speed 12 set speed(int value) => _speed = value; 13}
These methods enable us to safely access and modify the car's speed. Here's how we can use them:
Dart1void main() { 2 // Create a new Car instance 3 var myCar = Car(); 4 5 // Access the speed using getter 6 print(myCar.speed); // Outputs: 0, initial speed 7 8 // Set the car's speed using setter 9 myCar.speed = 100; 10 print(myCar.speed); // Outputs: 100 11}
In the code blocks above, we demonstrated how to define and use private attributes in a Car
class by employing getters and setters in Dart. We first created a Car
object, then used a getter to retrieve its speed, updated this speed with a setter, and observed how these operations maintain data encapsulation while allowing controlled access to the private _speed
attribute. This pattern enables us to protect the integrity of the object's state from unintended modifications.
Bravo! You've made it this far. This lesson equipped you with:
- An understanding of
private
data in Dart - The knowledge to employ getters and setters
Inscribe these lessons into your programming mind and continue your journey! We have prepared hands-on exercises for you that will provide practical experience and help cement your understanding of the concepts learned. Keep going — becoming proficient in Dart is a journey worth taking!