【继承、super、this、抽象类】

今日内容

  • 三大特性——继承
  • 方法重写
  • super关键字
  • this关键字
  • 抽象类

教学目标

  • 能够解释类名作为参数和返回值类型
  • 能够写出类的继承格式
  • 能够说出继承的特点
  • 能够说出子类调用父类的成员特点
  • 能够说出方法重写的概念
  • 能够说出super可以解决的问题
  • 描述抽象方法的概念
  • 写出抽象类的格式
  • 写出抽象方法的格式
  • 能够说出父类抽象方法的存在意义
  • 能够完成发红包案例的代码逻辑

第一章 继承

1.1 概述

由来

多个类中存在相同属性(成员变量)和行为(成员方法)时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些共同的属性和行为,只要继承那一个类即可,这样封装起来起到了重复使用的效果,方便统一修改。

其中,继承其他类的称为子类(或派生类),被继承的类称为父类超类(superclass)或者基类。

继承描述的是事物之间的所属关系,这种关系是:is-a 的关系(谁是谁的一种)。例如,图中兔子属于食草动物,食草动物属于动物。可见,父类更通用,子类更具体。我们通过继承,可以使多种事物之间形成一种关系体系。

定义

  • 继承:就是子类继承父类的属性行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性(成员变量)和行为(成员方法)。子类是父类的拓展。

好处

  1. 提高代码的复用性(少写了很多代码实现一样的功能)
  2. 类与类之间产生了耦合关系,继承多态的前提

弊端:类的耦合性加强了

开发中的原则:高内聚,低耦合,一般的,如果一个类能自己干的,就不要跟其他类发生过多的关系
内聚:就是类自己独立完成某件事情的能力
耦合:就是类与类之间的关系(万一其中一个类写坏了,其他类也坏了)

使用场景

基础框架的编写,某些共同的操作可以使用继承。

1.2 继承的格式

通过 extends 关键字,可以声明一个子类继承另外一个父类,定义格式如下:

class 父类 {...
}class 子类 extends 父类 {...
}

继承演示,代码如下:

/** 定义员工类Employee,做为父类*/
class Employee {String name; // 定义name属性// 定义员工的工作方法public void work() {System.out.println("尽心尽力地工作");}
}/** 定义讲师类Teacher 继承 员工类Employee*/
class Teacher extends Employee {// 定义一个打印name的方法public void printName() {System.out.println("name=" + name);}
}/** 定义测试类*/
public class ExtendDemo01 {public static void main(String[] args) {// 创建一个讲师类对象Teacher t = new Teacher();// 为该员工类的name属性进行赋值t.name = "小明"; // 调用该员工的printName()方法t.printName(); // name = 小明// 调用Teacher类继承来的work()方法t.work();  // 尽心尽力地工作}
}

1.3 继承后的特点——成员变量,就近原则,子类有就使用子类的,否则使用父类的

当类之间产生了关系后,其中各类中的成员变量,又产生了哪些影响呢?

成员变量不重名

如果子类父类中出现不重名的成员变量,这时的访问是没有影响的。代码如下:

class Fu {// Fu中的成员变量。int num = 5;
}class Zi extends Fu {// Zi中的成员变量int num2 = 6;// Zi中的成员方法public void show() {// 访问父类中的num,System.out.println("Fu num="+num); // 继承而来,所以直接访问。// 访问子类中的num2System.out.println("Zi num2="+num2);}
}class ExtendDemo02 {public static void main(String[] args) {// 创建子类对象Zi z = new Zi(); // 调用子类中的show方法z.show();  }
}
演示结果:
Fu num = 5
Zi num2 = 6

成员变量重名

如果子类父类中出现重名的成员变量,这时的访问是有影响的。代码如下:

class Fu {// Fu中的成员变量。int num = 5;
}class Zi extends Fu {// Zi中的成员变量int num = 6;public void show() {// 访问父类中的numSystem.out.println("Fu num=" + num);//就近原则,子类有就使用子类的,否则使用父类的// 访问子类中的numSystem.out.println("Zi num=" + num);}
}class ExtendsDemo03 {public static void main(String[] args) {// 创建子类对象Zi z = new Zi(); // 调用子类中的show方法z.show(); }
}
演示结果:
Fu num = 6
Zi num = 6

使用格式:

super.父类成员变量名

子类方法需要修改,代码如下:

class Zi extends Fu {// Zi中的成员变量int num = 6;public void show() {//访问父类中的numSystem.out.println("Fu num=" + super.num);//访问子类中的numSystem.out.println("Zi num=" + this.num);}
}
演示结果:
Fu num = 5
Zi num = 6

小贴士:Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢?对!可以在父类中提供公共的getXxx方法和setXxx方法。

1.4 继承后的特点——成员方法,就近原则,子类有就使用子类的,否则使用父类的

当类之间产生了关系,其中各类中的成员方法,又产生了哪些影响呢?

成员方法不重名

如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。代码如下:

class Fu{public void show(){System.out.println("Fu类中的show方法执行");}
}class Zi extends Fu{public void show2(){System.out.println("Zi类中的show2方法执行");}
}public  class ExtendsDemo04{public static void main(String[] args) {Zi z = new Zi();//子类中没有show方法,但是可以找到父类方法去执行z.show(); z.show2();}
}

成员方法重名——重写(Override)

如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。

  • 方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写(能够继承拿到然后在子类重写一遍)

代码如下:

class Fu {public void show() {System.out.println("Fu show");}
}class Zi extends Fu {//子类重写了父类的show方法public void show() {System.out.println("Zi show");}
}public class ExtendsDemo05{public static void main(String[] args) {Zi z = new Zi();// 子类中有show方法,只执行重写后的show方法z.show();  // Zi show}
}

重写的应用

子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。比如新的手机增加来电显示头像的功能,代码如下:

public class Test02 {public static void main(String[] args) {Zi z = new Zi();z.method();//就近原则,子类有就使用子类的,否则使用父类的//zi}
}class Fu {public static void method(){System.out.println("传家宝");
//        return;}
}class Zi extends Fu{//想使用父类的,又想有子类特有的,目的,为了让子类比父类更加强大,方法重写,应用场景//能够继承拿到然后在子类重写一遍public static void method(){//想在子类里面使用父类里面的东西,super,超类的,父类的//super.method();//表示调用使用父类里面的method方法//想使用父类的静态的东西,父类名.Fu.method();System.out.println("学好Java月薪过万");}
}//class Fu {//    public void method(){//        System.out.println("传家宝");
//    }
//}
//
//class Zi extends Fu{//想使用父类的,又想有子类特有的,目的,为了让子类比父类更加强大,方法重写,应用场景
//    //能够继承拿到然后在子类重写一遍
//    public void method(){//        //想在子类里面使用父类里面的东西,super,超类的,父类的
//        super.method();//表示调用使用父类里面的method方法
//
//
//        System.out.println("学好Java月薪过万");
//    }
//}

小贴士:这里重写时,用到super.父类成员方法,表示调用父类的成员方法。

注意事项

  1. 2.子类重写方法的访问权限要大于或者等于父类(子类要比父类更加强大,强大到访问权限都比父类强大,不能比父类弱)
  2. 子类方法覆盖父类方法,返回值类型(子父类关系,要求子类的返回值是父类返回值的子类)、函数名和参数列表都要一模一样。

提示:访问权限从小到大排序如下:private-默认修饰符-protected-public

    private(私有仅仅在本类中被访问)默认修饰符,默认是什么都不写(默认可以在同一个包下被访问)protected(受保护的,只能给子类去访问不管是否同包)public(公有在哪里都可以访问)

1.5 继承后的特点——构造方法

当类之间产生了关系,其中各类中的构造方法,又产生了哪些影响呢?

首先我们要回忆两个事情,构造方法的定义格式和作用。

  1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
  2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。代码如下:
public class Test04 {public static void main(String[] args) {Erzi z = new Erzi();System.out.println(z.i);//0,父类数据,子类创建对象的时候,才给它赋值}
}class Fuqin{int i;//0public Fuqin(){//        System.out.println("父类的构造方法");//做其他东西i = 666;//给成员变量赋值}public Fuqin(int j){//j = 888; //有参构造方法i = j;}
}class Erzi extends Fuqin{public Erzi(){//子类的构造方法中默认有一个super() ,表示调用父类的构造方法,不写也是写,系统给你写
//        super();//只要你写了,就按照你写的走super(888);//super()无参没有,手动调用父类有参构造方法,是int 变量
//        System.out.println(666);}
}
//子类的构造方法默认会通过super()访问父类的构造方法目的是让了创建子类对象的时候给父类数据进行初始化比如给成员变量赋值或者做其他东西

1.6 super和this

父类空间优先于子类对象产生

在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。

super和this的含义//记忆

  • super :代表父类的存储空间标识(可以理解为父类的引用,实际是个内存块)

  • this :代表当前对象的引用(谁调用就代表谁,存储的是地址值)

super和this的用法

  1. 访问成员
this.成员变量        --    本类的或者父类的,看就近原则就可以了
super.成员变量      --    父类的this.成员方法名()   --    本类的或者父类的,看就近原则就可以了
super.成员方法名()   --    父类的

用法演示,代码如下:

class Animal {public void eat() {System.out.println("animal : eat");}
}class Cat extends Animal {public void eat() {System.out.println("cat : eat");}public void eatTest() {this.eat();   // this  调用本类的方法super.eat();  // super 调用父类的方法}
}public class ExtendsDemo08 {public static void main(String[] args) {Animal a = new Animal();a.eat();Cat c = new Cat();c.eatTest();}
}输出结果为:
animal : eat
cat : eat
animal : eat
  1. 访问构造方法
this(...)        --    本类的构造方法
super(...)      --    父类的构造方法

子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super(),

super()默认不写也是写,系统给你写,但是只要你写了(this()或者super()),按照你写来,系统不再提供,

super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现

1.7 继承的特点

  1. Java只支持单继承,不支持多继承。
//一个类只能有一个父类,不可以有多个父类,即继承是亲生关系,一个孩子只能有一个亲爹
class C extends A{}     //ok
class C extends A,B...   //error,报错
  1. Java支持多层继承(继承体系)。
//相当于现实生活中的子父爷关系
class A{}
class A extends B{}
class B extends C{}
//A间接继承了C,可以使用C里面可以继承过来的东西,非私有成员变量和成员方法

第二章 抽象类

2.1 概述

由来

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体{},只有声明还有意义,而方法主体{}则没有存在的意义了。我们把没有方法主体{}的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类

定义

  • 抽象方法 : 没有方法体的方法。
  • 抽象类:包含抽象方法的类或者是用abstract修饰的类都是抽象类。抽象类不一定有抽象方法,只是使用了abstract修饰,是一个无意义的类。

2.2 abstract使用格式,抽象的

抽象方法

使用abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。

定义格式:

修饰符 abstract 返回值类型 方法名 (参数列表);

代码举例:

public abstract void run();

抽象类

如果一个类包含抽象方法,那么该类必须是抽象类。

定义格式:

abstract class 类名字 { }

代码举例:

public abstract class Animal {public abstract void run();
}

抽象的使用

继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义。

代码举例:

public class Test06 {public static void main(String[] args) {// Animal a = new Animal();//抽象类不能创建对象,抽象类,就是抽象的,不是具体的,没有具体的对象,不能创建对象//        Cat c = new Cat();//Cat抽象类不能创建对象
//        c.eat();
//
//        Sheep d = new Sheep();
//        d.eat();Cat c = new Cat();c.eat();//就近原则System.out.println(c.i);c.show();}
}//包含抽象方法的类,但是更准备的说法应该是用abstract修饰的类就是抽象类,抽象类不一定有抽象方法
abstract class Animal {//有抽象方法的类,是抽象类,加上标记abstract关键字//所有动物都吃鱼?不合理,所有都会吃饭的功能,但是具体怎么吃,我不知道,不太清楚,对于我来说就是抽象的,抽象方法public abstract void eat();//{}抽象方法{}去掉加上标记abstract关键字,未实现的方法
//    public abstract void eat2();//{}抽象方法{}去掉加上标记abstract关键字,未实现的方法int i = 666;public  void show(){System.out.println("show");}
}class Cat extends Animal {//想成为抽象类的子类,要么也是抽象类(没有意义),要么重写抽象类里面所有的抽象方法,alt enter@Overridepublic void eat() {//重写抽象方法eat,增加{}方法体,里面做事情System.out.println("吃鱼");}
}
//
//class Sheep extends Animal {//
//}

此时的方法重写,是子类对父类抽象方法的完成实现,我们将这种方法重写的操作,也叫做实现方法

2.3 注意事项

关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体{},做不了事情,没有意义。

  2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。

    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。

  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。

  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

小结:

比如实际项目中日志的收集就有使用到继承,抽取公共部分操作封装,子类继承日志父类实现日志落表。
还有就是基础框架编写过程中,使用到继承和抽象类,具体的有编写过一个简单的socketio的基础框架。

继承、super、this、抽象类相关推荐

  1. 12.面向对象(继承/super/接口/抽象类)

    面向对象 继承与派生 继承 继承顺序 继承原理 子类调用父类的方法(super) 组合 接口 接口的概念: 接口的概念解释和使用: python中的接口: 抽象类 面向对象 继承与派生 继承 什么是继 ...

  2. 初始Java Java SE 包,继承,组合,多态,抽象类,接口

    目录 包 1.静态导入 2.将类放到包中 3.包的访问权限控制 继承 基本语法: 注意事项: protected 关键字 final 关键字 组合 多态 向上转型: 动态绑定 方法重写 重写的规则 : ...

  3. 9继承进阶_抽象类_接口

    9继承进阶_抽象类_接口 导语: 想到在写 子父类中成员变量的特点 子父类中成员函数的特点.★★★★★ 子父类中构造函数的特点.★★★★★ final关键字的使用,重点在于常量的定义 抽象类的由来,犬 ...

  4. JAVA 继承基本类、抽象类、接口

    Java是一个面向对象的语言,java面向对象一般有三大特征:封装.继承.多态. 封装:就是把一些属性和方法封装到一个类里. 继承:就如子类继承父类的一些属性和方法. 多态:就如一个父类有多个不同特色 ...

  5. 继承 super的讲解

    继承 super注意点 super调用父类的构造方法,必须在构造方法的第一个 super必须只能出现在子类的方法或者构造方法中 super和this 不能同时调用构造方法 对比this ​ 代表的对象 ...

  6. Java基础--继承、this、super、抽象类

    抽象类

  7. java基础之继承补充和抽象类

    继承的补充和抽象类 1.子类和父类中出现了同名的变量该如何访问?(super) 使用super关键字可以直接指定父类空间 格式: super.成员变量 访问成员变量的时候特点: 如果所指定的空间找不到 ...

  8. 【java】 【接口】【继承】【抽象类】案例 运动员和教练

    [接口]可以认为是特殊的抽象类,但是接口只抽象方法,而抽象类抽象整个对象 只有抽象方法,不需要构造方法 一个类不能继承自多个类,但是一个接口可以被多个类实现,接口之间也可继承 接口中的所有成员变量都默 ...

  9. java培训记录Day18 2022/3/31星期四(super+多态+抽象类)

    目录 super关键字 super的使用,调用属性和方法 super调用构造器 多态性 多态的使用 为什么要使用多态 多态性只适用于方法不适用于属性 instanceof:向下转型 代码块 抽象类(a ...

  10. 第10章 接口、继承与多态----抽象类和接口

    一.抽象类 在解决实际问题时,一般将父类定义为抽象类,需要使用这个父类进行继承与多态处理.回想继承和多态原理,继承树中越是在上方的类越抽象,如:鸽子类继承鸟类.鸟类继承动物类等.在多态机制中,并不需要 ...

最新文章

  1. python结果输出到文件-python print输出到文件
  2. visual studio 64位汇编 listing列表文件
  3. 文件共享服务器第二部,第二章-构建Samba文件共享服务器.docx
  4. Python多线程--UDP聊天器
  5. javascript:history.go(-1)和javascript:history.back(-1)
  6. @JVM内存模型(运行时数据区)
  7. .net 创建属于自己的log类
  8. redis分布式锁学习总结
  9. visio图片插入word,Acrobat导出pdf格式错乱
  10. 京东商城架构峰值系统设计
  11. Ubuntu 安装永中Office2009个人版
  12. tl494cn逆变器电路图_tl494简单逆变器电路
  13. AndroidStudio报错Transform output file D:\android\RfidDemo\app\libs\RFID_lib.jar does not exist.
  14. deepin系统修改IP地址记录
  15. SAP中销售处理到期发票清单VF04功能的应用
  16. unity使用Sprite Editor图片切割功能减少性能损耗
  17. Oracle递归的实现
  18. 云速建站配置https证书
  19. [5] Word 手把手教你写毕业论文-2
  20. 解决ios手机vue H5页面输入键盘收起后页面回弹到顶部问题

热门文章

  1. 【ACPC2013】马里奥赛车(01背包)
  2. cocos creator 学习随笔 day03 节点和组件属性
  3. 程序员开发指南!金三银四Android面试的一些感受,这原因我服了
  4. 极速入门Gamemaker编程语言
  5. 猿创征文|后端开发工程师提升开发效率神器推荐
  6. 使用Blender导出多个动画的GLTF模型
  7. 日志模块、正则表达式、时间模块
  8. Sorry ,中产 -20160929
  9. html并排div可重叠,html – 并排堆叠div
  10. Excel如何利用函数删除数据中空格