一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情。
抛出问题: 现在统计一个学校里每个班级学生的信息,会有很多不同类型班级的学生,比如艺术班和普通班。
普通班的一个class对象:
class NormalCass{
constructor(numberPeople,className,bookName){
//班级人数
this.numberPeople:numberPeople,
//班级名
this.className:className,
//书本名
this.bookName:bookName
}
//NormalCass原型对象中的方法
//口号的一个方法
say(){...}
//文化课一个方法
culturalLessons(){...}
}
var normalCass1=new normalCass(40,'普通班1班','数学');
normalCass1.say();
normalCass1.culturalLessons();
numberPeople:40,className:'普通班1班',bookName:'数学'是通过_ _proto_ _继承的class的NormalCass对象。
艺术班的一个class对象:
class ArtCass{
constructor(numberPeople,className,instrumentName){
//班级人数
this.numberPeople:numberPeople,
//班级名
this.className:className,
//乐器名
this.instrumentName:instrumentName
}
//ArtCass原型对象中的方法
//口号的一个方法
say(){...}
//艺术课的一个方法
ArtLessons(){...}
}
var artCass1=new ArtCass(45,'艺术班1班','吉他');
artCass1.say();
artCass1.ArtLessons();
numberPeople:40,className:'普通班1班',instrumentName:'吉他'是通过_ _proto_ _继承的class的ArtCass对象。
问题:几种class包含相同的属性结构和方法定义。
解决:几种class类型间继承
几种class类型间继承
如何继承与extends和super的透析
2步:
- 额外创建一个父级class
父级class的构造函数中包含子类型的class中相同部分的属性结构定义,父级calss的原型对象中包含子类型class中相同部分的方法定义,既然父级class中保存了相同属性结构和方法定义,则子类class中,就可以删除所有重复的属性结构和方法定义。
一句大白话总结:就是把多个class类型的子对象里面有相同的属性和方法,抽离出来到父级的class对象中。
class students{
constructor(numberPeople,className){
//班级人数
this.numberPeople:numberPeople,
//班级名
this.className:className,
}
//父类型Cass的原型对象
say(){...}
}
问题:子类型class的子对象缺少必要的属性,而且有些共有方法也无法使用了。
- 让子类型class继承父类型的class
设置子类型的原型对象继承父类型的原型对象,class子类型extends父类型{...}
原理:只是设置子类型的原型对象继承父类型的原型对象,只能保证孙子对象可以使用爷爷类型原型对象共有的方法,暂时无法为孙子对象补全缺少的属性。
class students{
constructor(numberPeople,className){
//班级人数
this.numberPeople:numberPeople,
//班级名
this.className:className,
}
//父类型Cass的原型对象
say(){...}
}
//文化班
class NormalCass extends Students{
constructor(numberPeople,className,bookName){
//书本名
this.bookName:bookName
}
//NormalCass原型对象中的方法
culturalLessons(){...}
}
var normalCass1=new normalCass(40,'普通班1班','数学');
normalCass1.say(); //来自爷爷,可用
normalCass1.culturalLessons(); //来自爸爸,也可用
//艺术班
class ArtCass extends Students{
constructor(numberPeople,className,instrumentName){
//乐器名
this.instrumentName:instrumentName
}
//ArtCass原型对象中的方法
ArtLessons(){...}
}
var artCass1=new ArtCass(45,'艺术班1班','吉他');
artCass1.say(); //来自爷爷,可用
artCass1.ArtLessons();//来自爸爸,也可用
上面我们抽离出一个父类型的class,Students,里面保存了多个子类型的class,normalCass,ArtCass共有的方法和属性。其中方法在父类型Class的原型对象中保存着,属性则在父类型Class的构造函数中保存着,子类型class继承父类型class时,使用extends,可以调用的class父类型的原型对象,这样,子类型class自己以及自己的子对象,就可以使用父class,Students的原型对象中的方法。
extends底层相当于Object.setPrototypeOf(子类型的class的原型对象,父类型的原型对象)
问题:孙子对象依然缺少numberPeople和className属性?
解决:调用爷爷类型的构造函数,使用super关键字,super是专门指向父类型的关键字,调用super(),等于调用爷爷类型的构造函数,调用爷爷类型的构造函数,等效于执行爷爷类型的构造函数中共有的'this.xxx=xxx'语句,可为孙子对象弥补缺少的共有的属性结构。
代码如下:
class students{
constructor(numberPeople,className){
//班级人数
this.numberPeople:numberPeople,
//班级名
this.className:className,
}
//父类型Cass的原型对象
say(){...}
}
//文化班
class NormalCass extends Students{
constructor(numberPeople,className,bookName){
//继承父class类型的构造函数
super(numberPeople,className);
//书本名
this.bookName:bookName
}
//NormalCass原型对象中的方法
culturalLessons(){...}
}
var normalCass1=new normalCass(40,'普通班1班','数学');
//numberPeople:40, 来自奶奶
//className:'普通班1班', 来自奶奶
//bookName:'数学' 来自妈妈
normalCass1.say(); //来自爷爷,可用
normalCass1.culturalLessons(); //来自爸爸,也可用
//艺术班
class ArtCass extends Students{
constructor(numberPeople,className,instrumentName){
//继承父class类型的构造函数
super(numberPeople,className);
//乐器名
this.instrumentName:instrumentName
}
//ArtCass原型对象中的方法
ArtLessons(){...}
}
var artCass1=new ArtCass(45,'艺术班1班','吉他');
//numberPeople:40, 来自奶奶
//className:'普通班1班', 来自奶奶
//instrumentName:'吉他' 来自妈妈
artCass1.say(); //来自爷爷,可用
artCass1.ArtLessons();//来自爸爸,也可用
最后,normalCass1中的numberPeople:40,className:'普通班1班',bookName:'数学'是通过_ _proto_ _继承的父类,其中numberPeople和className来自奶奶,instrumentName来自妈妈。
结果:
- 孙子对象可使用3处保存方法:自己的,父级class的,爷爷class的
- 孙子对象中拥有两处规定的属性:父类构造函数+爷爷类构造函数
为什么叫extends?
问题:inherit是继承的意思,但是为什么用extends表示继承?
因为:继承是为了更好的扩展。
程序中的继承,都是为了在继承现有成员的基础上,进一步扩展出自己个性化的新成员。
所以,程序中的继承,都要用extends(扩展)
为什么叫super?
问题:为什么指向父类型构造函数的关键字,叫super?
因为:super在数学中指超集
所有的普通班是一个集合,所有艺术班也是一个集合,但是我们还可以用更大的集合“学生”,来包含普通班集合和艺术班集合。
这个可以包含普通班和艺术班的更大集合“学生”,就成为超集,英文名为:super。
总结
- extends底层和Object.setPrototypeOf(子类型的class的原型对象,父类型的原型对象)类似。
- extends只能继承父,爷爷的原型(方法),不能继承父类构造函数里的属性,这时候就用super来继承父类爷爷构造函数里的属性。
- 有了super和extends的配合,就会让子对象有完整的属性和方法了。因此父类,爷爷构造函数内的值子对象都有。
- extends(扩展)继承,只除了继承还有拓展,所以用这个字段名。super,超大集合的意思(超级)