概念
很多程序员工作好几年,竟然不知道什么是面向对象编程。
面向对象编程的核心就是类,面向类的设计模式:实例化(instantiation)、继承(inheritance)和(相对)多态(polymorphism)。这些名词我们会全都解释清楚。
类理论
面向对象编程强调的是数据和操作数据的行为本质上是互相关联的(当然,不同的数据有不同的行为),因此好的设计就是把数据以及和它相关的行为打包(或者说封装)起来。
例子:把“交通工具”当作一个广泛的类Vehicle,飞机、火车和汽车都可当作一个类。Vehicle的定义可能包含推进器(比如引擎)、载10人的能力等,飞机、火车和汽车在拥有Vehicle的能力的同时,又都拥有自己的独特能力:飞机在天上、火车在轨道上、汽车在公路上。又可以生产出很多的飞机、火车和汽车。
- 类:Vehicle是父类,飞机、火车和汽车都是子类;
- 继承:Vehicle拥有的能力,飞机、火车和汽车都有;
- 多态:Vehicle默认能载10人,飞机载80人、火车载1000人、汽车载4人,每个子类从父类继承来的能力得到了改变;
- 实例化:飞机、火车和汽车功能固定后,可以生产出大量独立的飞机、火车和汽车;
重点:当飞机、火车和汽车功能固定后,就形成了模型。可以根据模型量产出无限个相同的产品,不需要每次生产时再确定它的功能。这种操作简直太棒了。
这种基于固定模块实现量产的方式就是:面向对象编程;
“类”设计模式
你可能听过‘设计模式’这个词,比如迭代器模式、观察者模式、工厂模式、单例模式等等。它们都是在(低级)面向对象类的基础上实现了所有(高级)设计模式,似乎面向对象是优秀代码的基础。
JavaScript中的“类”
JavaScript中实际上有类呢?简单来说:不是。
类是一种设计模式,js其实是通过原型链模拟,实现类的功能。为了满足对于类设计模式的最普遍需求,JavaScript提供了一些近似类的语法。
代码实现例子
为方便实现,使用ES6的class写法。
定义父类Vehicle
Vehicle有引擎、载10人的能力;
class Vehicle{
engine() {
return '我是引擎';
}
load() {
return '我能载10人';
}
}
飞机、火车和汽车继承Vehicle
飞机、火车和汽车都继承了engine功能,又都同时扩展了自己的way功能。
class Car extends Vehicle {
way() {
return '我在公路上';
}
}
class Plane extends Vehicle {
way() {
return '我在天上';
}
}
class Train extends Vehicle {
way() {
return '我在轨道上';
}
}
const car = new Car();
console.log(car.engine()) // 我是引擎
console.log(car.way()) // 我在公路上
const plane = new Plane();
console.log(plane.engine()) // 我是引擎
console.log(plane.way()) // 我在天上
const train = new Train();
console.log(train.engine()) // 我是引擎
console.log(train.way()) // 我在轨道上
多态
每个子类都重新定义了load功能。如果没有定义,就会继续使用父类的load。
class Car extends Vehicle {
load() {
return '我能载4人';
}
way() {
return '我在公路上';
}
}
class Plane extends Vehicle {
load() {
return '我能载80人';
}
way() {
return '我在天上';
}
}
class Train extends Vehicle {
load() {
return '我能载1000人';
}
way() {
return '我在轨道上';
}
}
const car = new Car();
console.log(car.load()) // 我能载4人
const plane = new Plane();
console.log(plane.load()) // 我能载80人
const train = new Train();
console.log(train.load()) // 我能载1000人
实例化
使用Car举例,此时拥有Car的模型,我们可以量产了。
- 需要传参数时,要用constructor接收,如果是子类需要执行super,super的参数会传进父类的constructor函数。
- 看结果,多个car相互独立。既有相同的engine、way,还有自己独特的名字。
class Car extends Vehicle {
constructor(name) {
super();
this.name = name;
}
load() {
return '我能载4人';
}
way() {
return '我在公路上';
}
}
const car1 = new Car('保时捷');
console.log(car1.name) // 保时捷
console.log(car1.engine()) // 我是引擎
console.log(car1.way()) // 我在公路上
const car2 = new Car('长城');
console.log(car2.name) // 长城
console.log(car2.engine()) // 我是引擎
console.log(car2.way()) // 我在公路上
const car3 = new Car('奔驰');
console.log(car3.name) // 奔驰
console.log(car3.engine()) // 我是引擎
console.log(car3.way()) // 我在公路上
继承和实例化
必须理解原型才能明白继承和实例化。讲完原型后,再写两篇文章讲解吧。本文懂得怎么用就可以了。