OOP Three Principles
面向对象的三大特性:封装、继承、多态
问题
什么是面向对象的三大特性?用 JavaScript 如何实现?
解答
面向对象编程(OOP)的三大特性是:封装、继承、多态。
1. 封装 (Encapsulation)
将数据和操作数据的方法绑定在一起,隐藏内部实现细节。
class BankAccount {
// 私有属性(ES2022+)
#balance = 0;
constructor(initialBalance) {
this.#balance = initialBalance;
}
// 公开方法访问私有数据
deposit(amount) {
if (amount > 0) {
this.#balance += amount;
}
}
withdraw(amount) {
if (amount > 0 && amount <= this.#balance) {
this.#balance -= amount;
return amount;
}
return 0;
}
getBalance() {
return this.#balance;
}
}
const account = new BankAccount(100);
account.deposit(50);
console.log(account.getBalance()); // 150
// console.log(account.#balance); // SyntaxError: 无法直接访问私有属性
2. 继承 (Inheritance)
子类继承父类的属性和方法,实现代码复用。
// 父类
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound`);
}
}
// 子类继承父类
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类构造函数
this.breed = breed;
}
// 子类特有方法
fetch() {
console.log(`${this.name} is fetching`);
}
}
const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak(); // Buddy makes a sound(继承自父类)
dog.fetch(); // Buddy is fetching
3. 多态 (Polymorphism)
不同对象对同一方法有不同的实现。
class Animal {
speak() {
console.log('Animal speaks');
}
}
class Dog extends Animal {
speak() {
console.log('Woof!');
}
}
class Cat extends Animal {
speak() {
console.log('Meow!');
}
}
// 多态:同一方法,不同行为
function makeAnimalSpeak(animal) {
animal.speak();
}
const animals = [new Dog(), new Cat(), new Animal()];
animals.forEach(animal => makeAnimalSpeak(animal));
// Woof!
// Meow!
// Animal speaks
组合示例
// 形状基类
class Shape {
getArea() {
throw new Error('Must implement getArea');
}
}
class Rectangle extends Shape {
#width;
#height;
constructor(width, height) {
super();
this.#width = width;
this.#height = height;
}
getArea() {
return this.#width * this.#height;
}
}
class Circle extends Shape {
#radius;
constructor(radius) {
super();
this.#radius = radius;
}
getArea() {
return Math.PI * this.#radius ** 2;
}
}
// 多态计算总面积
function totalArea(shapes) {
return shapes.reduce((sum, shape) => sum + shape.getArea(), 0);
}
const shapes = [new Rectangle(10, 5), new Circle(3)];
console.log(totalArea(shapes)); // 50 + 28.27... ≈ 78.27
关键点
- 封装:用
#声明私有属性,通过公开方法访问,保护内部状态 - 继承:
extends继承父类,super()调用父类构造函数 - 多态:子类重写父类方法,同一接口不同实现
- JavaScript 通过原型链实现继承,ES6 class 是语法糖
- 优先使用组合而非继承(Composition over Inheritance)
目录