学习背景
面向对象编程呢就是学习编程为了找对象。en…我有很长一段时间都是这么觉得的,然而我还没找到,可能是还不够虔诚。
言归正传,学习面向对象对我们学习编程有着至关重要的作用,早期编程的时候都是以面向过程的思想完成程序编写。它是一种以过程为中心的编程思想,着重于程序运行的一个过程。比做一个数学计算、读写一个文件等,我们只要把这个过程做好便可以实现软件需求。但是随着软件功能越来越复杂,使用面向过程的编程方式就会很困难。所以面向对象的编程思想就很重要,它让我们不要只着重于过程,把程序中某些部分抽象成一个实体,然后单独考虑每个实体的功能与属性。让这些单独的实体共同协作实现软件功能。
面向对象的特征
-
1、封装
封装就是将事物的属性的行为(方法)包装起来,分成一类。这一类有着共同的属性和行为。比如,我们把动物封装成一个类别,大致定义位``` class 动物{ 属性:毛发 行为:吃 行为:睡觉 } ``` 那么我们定义的动物这一类有毛发,且有吃东西和睡觉的行为(当然自然界动物的属性与行为远远不止这些,通常我们只会封装程序中考虑到的属性及行为)。那么一个简单的动物类我们就封装好了。
-
2、继承
在我们封装的过程中发现一种属性和我们封装A类相同但是有点特殊的一类B。这一类呢拥有着共同的属性与行为,但是又拥有特殊的属性和行为。我们通常认为B类继承自A类。以上面动物这个分类中,我们新封装新的类别“狗”和“猫”
class 狗 extend 动物{
属性:对人类忠诚
行为:看家
}
class 猫 extend 动物{
属性:目空一切
行为:抓老鼠
}
我们新定义的狗这类继承于动物这一类,所以狗也属于动物,也有动物的属性毛发和动物的行为吃和睡觉,同时它也有其他动物没有的特点-对主人忠诚以及能看家的本领。猫同理也是继承于动物类,所以我们通过动物关系来理解继承的关系。
- 3、多态
子类从父类继承过来的属性和行为,在不同子类上有着不同的表现形式,这种不同表现形式我们称为多态。就拿我们上面这个猫狗举例吧,猫和狗都继承于动物类,都会吃饭,都有吃饭的行为,但是呢猫和狗吃的东西不一样。猫喜欢吃鱼而狗喜欢吃骨头,针对同一行为在不同子类下的不同表现形式,我们称为多态。 当然在同一类别下,不同实例的不同表现形式我们也称为多态,比如我家狗爱吃骨头,小明家的狗爱吃肉包子。
老生常谈 - 类与对象
为啥说这个是老生常谈呢,因为我们做编程的时候大多数都是在封装一个新的分类(class)实例化一个新的对象。那要搞清楚类与对象的区别那就要先搞明白“实例化”的含义。实例化通常是指根据封装的类来获取该类别里的实例,比如创建一个实例(new),也有时候由其他地方获取。这两点很关键,我们在协同工作中很多实例并不是我们自己创建的,我们要拿到别人创建的实例来完成对应的操作(比如我们后期常常会用到的服务器请求实例request和响应实例response)。所以类是抽象出来的一个群体类别,有着共同属性,比如我们创建的狗这一类。对象是该类别中特定的一个实例,比如我养的这条狗,张三养的那条都是。
nodejs 类
在早期我们常常通过原型的方式来创建类,如下面代码
function Animal(hairColor) {
this.hairColor = hairColor;
}
Animal.prototype.eat = function () {
console.log('我在吃饭饭')
};
var animal = new Animal('黑色');
animal.eat() // 打印“我在吃饭饭”
但是现在都2021年了,es6规范中已经有明确定义类的关键字class了,那我们今天就使用新的es6规范来创建类以及实例化我们类的对象。
我们要定一个动物类,定一个一个猫类和狗类。然后创建出一只猫和一条狗,分别让他们去介绍自己,并完成吃饭和睡觉行为。
代码实现
class Animal {
constructor(name, hairColor) { // 在创建动物这个实例的时候需要名字和毛发颜色属性
this.name = name; // 名字昵称属性,this代表的是实例本身
this.hairColor = hairColor; // 毛发属性
}
eat() { // 吃行为
console.log(`我叫${this.name},我正在吃饭饭`)
}
sleep() { // 睡觉行为
console.log(`我叫${this.name},我正在睡觉觉`)
}
}
class Dog extends Animal {
constructor(name, hairColor, masterName) { //在创建狗的时候需要主人名
super(name, hairColor)
this.masterName = masterName
}
eat(food) {
console.log(`我是${this.masterName}家的狗狗:`)
super.eat() // 遵守父类动物的吃行为
console.log(`我在吃${food}`)
}
protectHome() {
console.log('我在看家')
}
}
class Cat extends Animal {
constructor(name, hairColor, masterName) { //在创建狗的时候需要主人名
super(name, hairColor)
this.masterName = masterName
}
eat(food) {
console.log(`我是${this.masterName}家的猫咪:`)
super.eat()// 遵守父类动物的吃行为
console.log(`我在吃${food}`)
}
catchMouse() {
console.log('我去抓老鼠')
}
}
const xiaomingsCat = new Cat('小叮当', '黑色', '小明') //创建小猫实例
xiaomingsCat.eat('小鱼干') // 小猫去吃东西
xiaomingsCat.catchMouse() //小猫去抓老鼠
const xiaohongsDog = new Dog('豆豆', '灰色', '小红') // 创建小狗实例
xiaohongsDog.eat('肉包子') // 小狗去吃东西
xiaohongsDog.protectHome() //小狗去看家
运行结果
关键词说明
extends关键字
ES6中提供了extends关键字实现类的继承,用法是class A extends B,表示A继承于B
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ky123Mpr-1624675880369)(file:///Users/tristan/.config/joplin-desktop/resources/7d21e5a0c0ec4026aec45f0224fc5b07.png)]
super 关键字
super代表的是代表的父类对象,子类的构造函数constructor中super方法实现对父类构造函数的调用。使用super.eat()方法实现对父类实例对象的eat方法调用。在调用时需要注意下面几点:
-
1、子类构造函数中必须调用super方法,否则在新建对象时报错。
-
2、子类构造函数中必须在使用this前调用super,否则报错。
-
3、子类在继承父类方法是,如果需要准守父类的行为,就需要通过super.xxx()来调用父类行为。
最后
通过这章,我们应该掌握什么是面向对象,类于对象的区别以及在nodejs中如何实现定义类,如何实例化一个对象。万事开头难,了解面向对象并不是这几百字都能学完的,更多的需要在使用中去升华对它的感悟。
还有就是面向对象并不是比面向过程高级,它只是应用在不同场景中。简单原子化的东西更适合用面向过程思想去解决,而面向对象更像是对多个面向过程的一种分类管理。