1、类的属性和方法(函数)︰类可以有属性也没有没有属性,可以有方法也可以没有方法
2、类的属性是放在构造方法中初始化的,若 类 没有属性,可以不显式定义构造方法,此时,系统会自动生成一个无参的空的构造方法
1、基本概念:
(1)父类(基类):可以派生子类的类
(2)子类(派生类):由父类派生而来的类
2、面向对象的三大特性
(1)封装性:对象是属性和行为的封装体 --- 数据安全
(2)继承性:子类可以继承父类已有的属性和方法 --- 代码复用
(3)多态性:同一个消息传递给不同的对象,出现的效果不同 --- 应用灵活 、可以适应不同的需求
3、继承的实现
(1)ES5中继承的实现:没有类的概念
a、构造函数:构造函数名就是类名,在ES5中类的继承实际上就是构造函数的继承
b、实现:通过call、apply、bind来实现构造函数的继承
-
- //1.定义构造函数:基类
- function Father(name) {
- this.name = name;
- this.age = 45
- }
- //2.定义构造函数:子类
- function Son(name) {
- console.log(this);
- /*this代表上层对象(window),name参数传递Father构造函数。等于在Son函数中调用了Father函数:Son就具有了name和age属性(相当于从Father继承了name和age)*/
- Father.call(this, name); //函数劫持,在Son中通过call调用Father构造函数,将参数name传递给Father构造函数
- this.height = '187cm' //height是Son自己的属性
-
- this.show = function () {
- console.log('姓名:', this.name);
- console.log('年龄:', this.age);
- console.log('身高:', this.height);
- }
- }
- let son = new Son('赵四');
- son.show();
-
(2)ES6中的继承:通过关键字enextds实现
- //1.定义父类Fatcher
- class Fatcher {
- constructor(name, age) {
- this.name = name;
- this.age = age;
- }
- fun() {
- console.log('我是父类中的方法.........');
- }
- }
- //2.定义子类Son,继承来自Father类
- class Son extends Fatcher {
- constructor(name, age) {
- super(name, age); //调用父类的构造函数
- }
- hobby() {
- console.log('我喜欢打篮球');
- }
- show() {
- console.log('姓名:', this.name);
- console.log('年龄:', this.age);
- }
- }
- let s1 = new Son('张三', 25);
- s1.hobby();
- s1.show();
- s1.fun();
A、super:指向父类。super([参数])表示调用弗雷德构造函数
B、如果在子类的构造函数中调用父类的构造函数,那么super()必须作为子类构造函数中的第一条语句
在执行子类的构造函数之前必须先执行父类的构造函数(先有父,后有子)
C、方法覆盖(Overwrite):在继承过程中,若父类的某个方法与子类的某个方法同名,则子类方法覆盖父类的同名方法
D、在子类的方法中可以使用super调用父类中的某个方法
E、不允许多继承,只能单继承
多继承:类的直接父类有多个
单继承:类的直接父类只有一个父类
练习1:
(1)定义一个点类(Point),具有x,y两个属性(表示坐标),显示本类信息的show()方法;
(2)定义一个圆类(Circle)由点派生,增加一个新的属性半径(radiu),一个计算圆面积的area()方法,和一个同样显示本类信息的show()方法
(3)定义一个圆柱体类(Cylinder)由圆类派生,增加一个属性高度(height)一个计算圆柱形体积的方法vol(),一个计算圆柱形表面积的area1()方法,和一个同样显示本类信息的show()方法。
(4)测试: Circle类、Cylinder类的方法
- //1.定义Point类
- class Point {
- constructor(x, y) {
- this.x = x;
- this.y = y;
- }
- show() {
- console.log(`圆心坐标:${this.x},${this.y}`);
- // console.log('x坐标:', this.x);
- // console.log('y坐标:', this.y);
- }
- }
-
- //2.定义Circle类,继承自Point
- class Circle extends Point {
- constructor(x, y, radiu) {
- super(x, y);
- this.radiu = radiu;
- }
- area() { //圆面积
- return (Math.PI * this.radiu * this.radiu);//this.radiu**2
- }
- circumference() { //圆周长
- return (Math.PI * (this.radiu * 2));
- }
-
- show() {
- super.show(); //调用父类的show方法
- console.log('半径:', this.radiu);
- console.log('⚪的面积是:', this.area());
- console.log('⚪的周长是:', this.circumference());
- }
- }
-
- //3.定义Cylinder类,继承自Circle
- class Cylinder extends Circle {
- constructor(x, y, radiu, height) {
- super(x, y, radiu);
- this.height = height;
- }
- vol() { //求圆柱体体积
- return super.area() * this.height;
- }
- area1() { //求圆柱体表面积
- return (super.area() * 2) + (super.circumference() * this.height);
- }
- show() { //调用父类的show方法
- super.show();
- console.log('圆柱体的高是:', this.height)
- console.log('圆柱体体积是:', this.vol());
- console.log('圆柱体表面积是:', this.area1());
- }
- }
-
- //4.测试
- let circle = new Circle(1, 1, 3);
- circle.show();
-
- console.log('-------------------');
-
- let cylinder = new Cylinder(5, 1, 4, 5);
- cylinder.show();
1、继承的好处:在父类中定义的属性和方法,子类继承后就可以直接使用。
2、类继承过程中的向上转型:子类的对象的类型一定是父类的类型,父类对象的类型不能是子类的类型
(1)typeof:用于判断一个变量的数据类型(基本数据类型)
typeof 变量名 == '数据类型'
(2)instanceof:用于判断变量的数据类型(类类型)
对象名 instanceof 类名
判断‘对象’是否是给定的类的对象