Skip to content

封装、继承、多态

封装、继承和多态是面向对象编程(OOP)的三大基本特性。这些概念在 JavaScript 中也有相应的实现方式,尽管 JavaScript 的面向对象机制与传统的类基语言(如 Java 或 C++)有所不同。下面详细介绍这三大特性在 JavaScript 中的应用。

1. 封装 (Encapsulation)

定义:封装是指将数据(属性)和操作数据的方法绑定在一起,形成一个独立的单元(即对象),并且尽可能隐藏对象内部的实现细节,只暴露必要的接口给外部使用。

目的

  • 提高模块化程度。
  • 保护数据不被外部直接访问或修改。
  • 降低代码之间的耦合度。

JavaScript 实现

  • 使用构造函数和闭包来实现封装。
  • 使用 private 变量和方法(通过立即执行函数表达式 IIFE)。

示例

javascript
function Person(name) {
  let _name = name; // 私有变量

  function getName() {
    // 私有方法
    return _name;
  }

  function setName(newName) {
    // 私有方法
    _name = newName;
  }

  this.getName = function () {
    // 公共方法
    return getName();
  };

  this.setName = function (newName) {
    // 公共方法
    setName(newName);
  };
}

const alice = new Person("Alice");
console.log(alice.getName()); // 输出: Alice
alice.setName("Alicia");
console.log(alice.getName()); // 输出: Alicia

2. 继承 (Inheritance)

定义:继承是指一个对象(子类)可以继承另一个对象(父类)的属性和方法,从而实现代码重用和扩展。

目的

  • 代码重用。
  • 扩展功能而不改变现有代码。

JavaScript 实现

  • 原型链继承。
  • 构造函数继承。
  • 组合继承。
  • 寄生组合继承。
  • ES6 类的继承。

示例(使用 ES6 类的继承):

javascript
class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, I'm ${this.name}`);
  }
}

class Student extends Person {
  constructor(name, grade) {
    super(name); // 调用父类构造函数
    this.grade = grade;
  }

  study() {
    console.log(`I'm studying in grade ${this.grade}`);
  }
}

const alice = new Student("Alice", 10);
alice.greet(); // 输出: Hello, I'm Alice
alice.study(); // 输出: I'm studying in grade 10

3. 多态 (Polymorphism)

定义:多态是指同一个接口可以有不同的实现方式。在运行时,根据对象的实际类型来决定调用哪个方法。

目的

  • 提高代码的灵活性和可扩展性。
  • 使代码更加通用和易于维护。

JavaScript 实现

  • 通过方法重写(覆盖)实现多态。
  • 通过鸭子类型(Duck Typing)实现多态。

示例(方法重写):

javascript
class Animal {
  speak() {
    console.log("Some generic animal sound");
  }
}

class Dog extends Animal {
  speak() {
    console.log("Woof woof!");
  }
}

class Cat extends Animal {
  speak() {
    console.log("Meow meow!");
  }
}

function makeSound(animal) {
  animal.speak();
}

const dog = new Dog();
const cat = new Cat();

makeSound(dog); // 输出: Woof woof!
makeSound(cat); // 输出: Meow meow!

示例(鸭子类型):

javascript
function makeSound(animal) {
  if (animal && typeof animal.speak === "function") {
    animal.speak();
  } else {
    console.log("This is not an animal!");
  }
}

const dog = {
  speak: function () {
    console.log("Woof woof!");
  },
};

const cat = {
  speak: function () {
    console.log("Meow meow!");
  },
};

const nonAnimal = {};

makeSound(dog); // 输出: Woof woof!
makeSound(cat); // 输出: Meow meow!
makeSound(nonAnimal); // 输出: This is not an animal!

总结

  • 封装:通过构造函数和闭包实现,隐藏内部实现细节,只暴露必要的接口。
  • 继承:通过原型链、构造函数、组合继承、寄生组合继承以及 ES6 类的继承实现。
  • 多态:通过方法重写和鸭子类型实现,提高代码的灵活性和可扩展性。

理解并正确使用这些面向对象的基本特性,可以帮助你编写出更清晰、更灵活且易于维护的 JavaScript 代码。如果你有更多关于封装、继承和多态的具体问题或需要进一步的例子,请告诉我!

Released under the MIT License.