Hello! Today's journey ventures into the cornerstone of TypeScript's object-oriented fundamentals: Encapsulation. This concept establishes a protective barrier around an object's data, thereby preventing it from being accessed by the external code ecosystem. Let's dive in.
Encapsulation serves three main purposes: it maintains integrity, controls data modification, and provides data abstraction — interfaces that are accessible to users. Think of using a cell phone; you interact with an interface without interfering with its circuits. Following this logic, encapsulation safeguards the internal implementation while exposing safe interfaces.
Now, let's discuss Private Data: In TypeScript, we can specify private
data using the keyword private
. These data fields cannot be accessed outside the class. We will illustrate this with a Car
class, introducing a private
attribute called _speed
:
TypeScript1class Car { 2 private _speed: number; // private speed attribute 3 4 constructor() { 5 this._speed = 0; // Initialize speed with 0 6 } 7}
This class has a private member, _speed
, which cannot be accessed directly outside the class. The underscore _
before speed
is a naming convention that indicates it is a private attribute.
Getters and Setters are tools used to control access to private
data. In our Car
class, a getter function retrieves the _speed
attribute, while a setter function modifies it as follows:
TypeScript1class Car { 2 private _speed: number; // Private speed attribute 3 4 constructor() { 5 this._speed = 0; // Initialize speed with 0 6 } 7 8 get speed(): number { // Get current speed 9 return this._speed; 10 } 11 12 set speed(value: number) { // Update speed 13 // Speed should stay in the range 0 to 150 14 if (value < 0) { 15 this._speed = 0; 16 } else if (value > 150) { 17 this._speed = 150; 18 } else { 19 this._speed = value; 20 } 21 } 22}
These methods allow us to retrieve or change the car's speed in a safe manner.
Armed with these concepts, we can construct a Car
class that showcases encapsulation:
TypeScript1class Car { 2 private _model: string; // private model attribute 3 private _speed: number; 4 5 constructor(model: string) { 6 this._model = model; // Initialize model 7 this._speed = 0; // Initialize speed with 0 8 } 9 10 get model(): string { // Getter for model 11 return this._model; 12 } 13 14 get speed(): number { // Getter for speed 15 return this._speed; 16 } 17 18 set speed(value: number) { // Setter for speed 19 // Speed should be between 0 and 150 20 this._speed = value < 0 ? 0 : (value > 150 ? 150 : value); 21 } 22}
And, here is how we will use this class (keep in mind that when using get
/set
methods, we don't use parentheses):
TypeScript1// Create a new Car instance 2let myCar = new Car("Toyota"); 3 4// `myCar.model` and `myCar.speed` implicitly call the corresponding getter methods 5console.log(myCar.model); // Outputs: "Toyota" 6console.log(myCar.speed); // Outputs: 0 7 8// Attempt to set speed beyond its limit 9// `myCar.speed = ...` implicitly calls the setter method 10myCar.speed = 200; 11console.log(myCar.speed); // Outputs: 150, because the speed limit is 150 12 13// Attempt to set a negative speed 14myCar.speed = -10; 15console.log(myCar.speed); // Outputs: 0, because the speed cannot be negative
These codes demonstrate private
attributes in action, employing getters and setters and encapsulating the inner workings of the Car
class.
Great job getting this far. As a result of this lesson, your toolbelt now includes:
- An understanding of
private
data - Knowledge about the roles of getters and setters
Inscribe these lessons into your programming mind and continue your journey! There are hands-on exercises in store for you — they offer practical experience and help bond your understanding of the concepts learned. Keep following the path to becoming a TypeScript pro — the journey is worth it!