Overview
TypeScript, an extension of JavaScript, offers access modifiers to control the visibility of class members. This tutorial dives into the use of public and private keywords to enhance encapsulation in your object-oriented code.
Introduction to Access Modifiers
Access modifiers in TypeScript are keywords that set the accessibility of properties and methods within a class. TypeScript provides three main access modifiers:
- Public: This is the default modifier; members are accessible everywhere.
- Private: Members are only accessible within the class they’re declared in.
- Protected: Members are accessible within the declaring class and any subclass.
Let’s start with public and private modifiers, which are crucial for encapsulation.
Basic Usage of Public and Private
class Animal {
public name: string;
private species: string;
constructor(name: string, species: string) {
this.name = name;
this.species = species;
}
public describe(): string {
return `${this.name} is a ${this.species}`;
}
private logSpecies(): void {
console.log(this.species);
}
}
const dog = new Animal('Rex', 'Canine');
console.log(dog.describe()); // Rex is a Canine
dog.logSpecies(); // Error: 'logSpecies' is a private method.
In the example above, name
is public and accessible anywhere, whereas species
and logSpecies
are private and we get an error trying to access logSpecies
from outside the class.
Advanced Utilization of Private Modifiers
Private access can also be used to safeguard against method overriding and to encapsulate complex logic that shouldn’t be exposed:
class Bird extends Animal {
constructor(name: string) {
super(name, 'Aves');
}
describe(): string {
// We can still call describe() from the parent class as it's public
return `${super.describe()} and loves to fly.`;
}
// We cannot override logSpecies here, as it's private in Animal
}
const parrot = new Bird('Rio');
console.log(parrot.describe()); // Rio is a Aves and loves to fly.
Notice the logSpecies()
method from the Animal
class cannot be overridden as it is private.
Using Access Modifiers in Constructors
One powerful feature in TypeScript is the ability to define class member accessibility directly within the constructor parameters:
class Plant {
constructor(public name: string, private species: string) {}
public display(): void {
console.log(`${this.name} is part of the ${this.species} species.`);
}
}
const sunflower = new Plant('Sunflower', 'Helianthus');
sunflower.display(); // Sunflower is part of the Helianthus species.
This syntax not only defines the access level but also automatically assigns the parameter to a class member.
Encapsulation in Action
Now let’s put our knowledge to work and create a class that uses both public and private access modifiers to manipulate and store data securely:
class BankAccount {
public readonly accountNumber: string;
private balance: number;
constructor(accountNumber: string, initialBalance: number) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
public deposit(amount: number): void {
this.balance += amount;
console.log(`Deposit successful. New balance: ${this.balance}`);
}
private deductFees(feeAmount: number): void {
this.balance -= feeAmount;
console.log(`Fees applied. New balance: ${this.balance}`);
}
public withdraw(amount: number): void {
if (amount + 30 > this.balance) { // assuming a flat fee of 30 for simplicity
console.log('Insufficient funds.');
return;
}
this.deductFees(30);
this.balance -= amount;
console.log(`Withdrawal successful. New balance: ${this.balance}`);
}
}
const account = new BankAccount('12345', 500);
account.deposit(100); // Deposit successful. New balance: 600
account.withdraw(200); // Withdrawal successful. New balance: 370
This example demonstrates encapsulation via private methods to handle internal processes while exposing only the necessary functionality to the user.
Conclusion
Understanding and correctly implementing public and private access modifiers in TypeScript is critical for creating robust, encapsulated, and maintainable code. Through the examples provided, we’ve seen the control these modifiers grant us, enforcing a strong contract for other parts of the code that interact with our classes.