Java中的抽象类

快来打我* 2023-10-02 21:22 22阅读 0赞

一、抽象类定义

Java语言提供了两种类:具体类和抽象类

在Java中,abstract是抽象的意思,可以修饰类,成员方法

abstract修饰类,就是抽象类,abstract修饰方法,就是抽象方法

格式如下

修饰符 abstract class 类名{

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

}

注意:一个类中有抽象方法的话,该类也要被abstract修饰,否则会报错

示例:

  1. //abstract修饰的抽象类
  2. public abstract class People {
  3. //abstract修饰的抽象方法
  4. public abstract void eat();
  5. }

特点:

  • 修饰符必须为public或者protected,不能为private,因为创建了抽象类,就要被其他类继承,设为private就无法被继承
  • 抽象类不能被实例化,只能通过普通子类来实现实例化
  • 如果一个普通子类继承于抽象父类,则该类一定要重写实现该父类的抽象方法,如果子类仍然的hi一个抽象类,也是允许的,就不必冲写父类的抽象方法,但必须用abstract修饰
  • 抽象级别:抽象类是对整体类的抽象,包括属性和方法
  • 抽象类是现有子类,将子类的共同属性和方法提取出来放在抽象类中,是一种从下往上的构建法则
  • 父类包含了子类集合的常见方法,但由于父类本身是抽象的,不能使用这些方法

二、抽象方法

抽象方法特点:

  • 抽象方法中没有方法体
  • 抽象方法必须存在于抽象类中
  • 子类重写父类时,必须重写父类的所有抽象方法
  • 抽象方法不能使用private final static 来修饰,因为这些关键字都是和重写违背的

抽象方法代码示例如下:

  1. //abstract修饰的抽象类
  2. public abstract class People {
  3. //普通方法,带 {} 方法体
  4. public void fun(){
  5. System.out.println("存在方法体的普通方法");
  6. }
  7. //abstract修饰的抽象方法,没有方法体 {},被abstract修饰
  8. public abstract void eat();
  9. }

三、抽象类举例

首先声明一点:为什么要使用抽象类

答:当父类知道子类要完成某种行为,但每个子类的实现方式又不一样的时候,于是该父类就把行为定义成抽象方法的形式,具体实现交给子类去完成,此时这个类就可以声明为抽象类,下面举三个例子来说明抽象类的使用,

3.1、抽象类例子1

先声明一个Cat类,类中有睡觉这一行为

  1. public class Cat {
  2. public void sleep(){
  3. System.out.println("我在睡觉");
  4. }
  5. }

再声明一个Dog类,类中也有睡觉这一行为

  1. public class Dog {
  2. public void sleep(){
  3. System.out.println("我在睡觉");
  4. }
  5. }

这里的Dog和Cat都有共同的行为sleep();

但这时给Dog和Cat添加一个eat()的行为,不同的是,Dog吃的是骨头,Cat吃的是鱼,相同点是都是eat()这个行为,不同点是吃的食物不同,就可以将Dog和Cat作为子类,抽象出eat()这个行为作为抽象方法放在父类中,再在子类重写父类方法来调用实现吃不同的食物。

父类Animal:定义共同行为sleep(),对于子类来说sleep()行为没有差别,不需要作为抽象方法,

但是对于吃这个行为,Cat和Dog两者都有这个属性,具体的内容确是有区别的,因此作为抽象方法,需要注意的是抽象方法由abstract修饰,没有方法体。

  1. //定义一个abstract修饰的抽象类
  2. public abstract class Animal {
  3. //通用的行为sleep也放在父类中
  4. public void sleep(){
  5. System.out.println("我在睡觉");
  6. }
  7. //定义抽象方法
  8. //抽象方法没有方法体{}
  9. public abstract void eat();
  10. }

子类Cat:引入@Override注解是为了重写父类的方法,共同行为sleep()可以不用写,对于两个子类来说没有区别,只在抽象类中定义一次即可。

  1. public class Cat extends Animal{
  2. //@Override注解是重写父类的方法
  3. @Override
  4. public void eat(){
  5. System.out.println("我在吃鱼");
  6. }
  7. }

子类Dog:引入@Override注解是为了重写父类的方法,共同行为sleep()可以不用写,对于两个子类来说没有区别,只在抽象类中定义一次即可。

  1. public class Dog extends Animal{
  2. //@Override注解是重写父类方法需要引入的注解
  3. @Override
  4. public void eat(){
  5. System.out.println("我在吃骨头");
  6. }
  7. }

在启动项中:由于父类Animal是抽象类,无法实例化成对象,因此只能通过对子类的实例化,对象来调用父类Animal中对于两个子类没有区别的sleep()方法,和分别调用从父类中重写的方法eat()

  1. public class DemoApplication {
  2. public static void main(String[] args) {
  3. System.out.println("狗的行为--------------------------------");
  4. //在启动项中New一个对象
  5. Dog dog = new Dog();
  6. //利用对象调用抽象类中的sleep()方法
  7. dog.sleep();
  8. //利用对象调用子类中重写的方法eat()
  9. dog.eat();
  10. System.out.println("猫的行为--------------------------------");
  11. //在启动项中New一个对象
  12. Cat cat = new Cat();
  13. //利用对象调用抽象类中的sleep()方法
  14. cat.sleep();
  15. //利用对象调用抽象类中的eat()方法
  16. cat.eat();
  17. }
  18. }

控制台打印输出:

  1. 狗的行为--------------------------------
  2. 我在睡觉
  3. 我在吃骨头
  4. 猫的行为--------------------------------
  5. 我在睡觉
  6. 我在吃鱼

这样每个对象都没有重写公用方法eat(),而是直接调用了,如果是接口来实现的话,则需要实现类来重写一下eat(),就会又很多重复代码

区别:这里对于Cat吃鱼和Dog吃骨头,可以用接口去实现他们的行为吗,当然可以,但是这种利用接口方式会产生很多重复性的代码,这样的话就得每一个每个实现类都写一遍睡觉的这个逻辑,因为接口的设计只能满足多态(之后的内容会介绍什么是多态),像我们这种既有多态(Cat吃鱼Dog吃骨头),又有复用(都有sleep()行为),最佳设计就是优先考虑使用抽象类了,集成以后调用一次即可。

3.2、抽象类例子2

每个人的吃饭前的准备和吃饭后的处理都是一样的,吃饭前:“饭前勤洗手”,吃饭后:“饭后勤洗碗”,只有吃饭的过程不同,跟例1一样,公共行为是吃饭前和吃饭后的行为,不同的是中间吃饭的过程,那么就可以把吃饭的过程变成一个抽象方法,而吃饭前和吃饭后的行为作为普通方法一起放在抽象类中

首先,在只有学生一类人的时候,吃饭的过程是一样的,不需要抽象类和抽象方法

  1. public class Student {
  2. public void eat(){
  3. System.out.println("饭前洗手");
  4. System.out.println("我是学生,我要吃的健康且有营养");
  5. System.out.println("饭前洗碗");
  6. }
  7. }

启动类New一个对象,调用eat()方法

  1. public class DemoApplication {
  2. public static void main(String[] args) {
  3. //new一个对象出来调用eat()方法
  4. Student student = new Student();
  5. student.eat();
  6. }
  7. }

控制台打印输出为:

  1. 饭前洗手
  2. 我是学生,我要吃的健康且有营养
  3. 饭前洗碗

此时增加一类人为运动员,吃饭的过程为“我是运动员,要吃的多一些”,这个时候就需要构建一个抽象类People作为父类,定义抽象方法process(),其他的作为普通方法

  1. //abstract修饰的抽象类
  2. public abstract class People {
  3. //设置公共的不同人也无差异的饭前和饭后行为
  4. public void eat() {
  5. System.out.println("饭前洗手");
  6. //调用本类的抽象方法
  7. this.process();
  8. System.out.println("饭后洗碗");
  9. }
  10. //抽象方法:吃饭的过程,abstract修饰,无方法体,无具体的方法实现
  11. public abstract void process();
  12. }

子类Student,继承父类People,引入注解@Override再进行重写父类的抽象方法process()

  1. //子类Student继承父类People
  2. public class Student extends People{
  3. //@Override注解是为了重写父类夫人方法引进的注解
  4. @Override
  5. //重写父类的方法
  6. public void process(){
  7. System.out.println("我是学生,我要吃的健康且营养");
  8. }
  9. }

子类Player,继承父类People,引入注解@Override再进行重写父类的抽象方法process()

  1. //子类Player继承父类People
  2. public class Player extends People{
  3. //@Override注解是为了重写父类方法引进的注解
  4. @Override
  5. //重写父类的方法
  6. public void process(){
  7. System.out.println("我是运动员,我要吃的健康一点");
  8. }
  9. }

启动项,通过new关键字分别创建子类Player和子类Student的对象 (因为父类是抽象类无法实例化),再通过对象调用父类People的普通方法eat()

  1. public class DemoApplication {
  2. public static void main(String[] args) {
  3. System.out.println("学生行为-----------------------");
  4. //new关键字创建对象
  5. Student student = new Student();
  6. //调用父类中的普通方法
  7. student.eat();
  8. System.out.println("运动员行为---------------------");
  9. //new关键字创建对象
  10. Player player = new Player();
  11. //调用父类中的普通方法
  12. player.eat();
  13. }
  14. }

控制台打印输出为:

  1. 学生行为-----------------------
  2. 饭前洗手
  3. 我是学生,我要吃的健康且营养
  4. 饭后洗碗
  5. 运动员行为---------------------
  6. 饭前洗手
  7. 我是运动员,我要吃的多一点
  8. 饭后洗碗

这个例子也说明了通过使用模板,我们只需要改变一部分,其他的直接拿过来用即可

3.3、抽象类例子3

不同的几何体,面积计算公式是不一样的,但他们具有的特性是一样的,都有长和宽的属性,也有面积计算方法,那么就可以定义成一个抽象类,抽象类的有两个属性width和height,还有面积计算方法area()

首先创建一个图形抽象类Shape,类中定义属性和抽象方法、

  1. //抽象类Shape,用abstract修饰
  2. public abstract class Shape {
  3. public int width; //几何图形的长
  4. public int height; //几何图形的宽
  5. //有属性就使用有参构造器
  6. public Shape(int width, int height) {
  7. this.width = width;
  8. this.height = height;
  9. }
  10. //抽象方法,abstract修饰,没有方法体{}
  11. public abstract void area();
  12. }

子类正方形类Square,继承父类Shape,通过引入@Override注解进行父类方法的重写

  1. //子类Square继承父类Shape
  2. public class Square extends Shape{
  3. //利用super访问父类的属性width和height
  4. public Square(int width, int height) {
  5. super(width, height);
  6. }
  7. //通过注解@Override的引入实现父类方法的重写
  8. @Override
  9. //重写父类方法,方法体中写入具体的实现
  10. public double area(){
  11. double y = width * height;
  12. return y;
  13. }
  14. }

子类三角形类Triangle,继承父类Shape,通过引入@Override注解进行父类方法的重写

  1. public class Triangle extends Shape{
  2. //通过右键选择Generate快捷生成,利用super访问父类的属性
  3. public Triangle(int width, int height) {
  4. super(width, height);
  5. }
  6. //通过注解@Override的引入实现父类方法的重写
  7. @Override
  8. //重写父类方法
  9. public double area(){
  10. double x = (width * height )/2;
  11. return x;
  12. }
  13. }

在启动项中,通过对两个子类的实例化,调用各自类中的重写方法,注意因为是调用了有参构造器,所以可以在实例化的时候直接赋值

  1. public class DemoApplication {
  2. public static void main(String[] args) {
  3. System.out.println("三角形-----------------------");
  4. //new关键字创建对象
  5. Triangle triangle = new Triangle(3,4);//调用了有参构造器,直接赋值即可
  6. //调用子类中重写的方法
  7. triangle.area();
  8. System.out.println("三角形的面积为"+triangle.area());
  9. System.out.println("长方形---------------------");
  10. //new关键字创建对象
  11. Square square = new Square(5,6);//调用了有参构造器,直接赋值即可
  12. //调用子类中重写的方法
  13. square.area();
  14. System.out.println("长方形的面积为"+square.area());
  15. }
  16. }

控制台打印输出为:

  1. 三角形-----------------------
  2. 三角形的面积为6.0
  3. 长方形---------------------
  4. 长方形的面积为30.0

四、抽象类使用注意事项

  1. 一个类如果定义为抽象类,那里面可以没有抽象方法
  2. 一个类中如果有抽象方法,那所在类必为抽象类
  3. 抽象类不能被实例化,可以实例化这个抽象类的非抽象子类,
  4. 抽象类中的所有非抽象子类必须重写抽象类中的抽象方法
  5. 抽象类中,可以有构造方法,是供给子类创建对象时,初始化父类成员使用的
  6. 抽象类中的抽象方法只是声明,不包含方法体,也就是不给出具体的实现细节

发表评论

表情:
评论列表 (有 0 条评论,22人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JAVA抽象

    一、介绍 Java中提供了两种类:具体类和抽象类。 1、abstract意思为“抽象的”,用abstract关键字来修饰一个类时,这个类就叫做抽象类。 语法:访问修饰

    相关 Java抽象

    一、抽象类定义 Java语言提供了两种类:具体类和抽象类 在Java中,abstract是抽象的意思,可以修饰类,成员方法 abstract修饰类,就是抽象类,abs

    相关 Java抽象方法抽象

    1、 普通方法和抽象方法的区别 (1)在Java中,当一个类的方法被abstract关键字修饰时,该方法称为抽象方法。 (2)抽象方法所在的类必须定义为抽象类。 (3

    相关 java 抽象

    在自上而下的继承层次结构中,位于上层的类更具有通用性,甚至可能更加抽象。从某种角度看,祖先类更加通用,它只包含一些最基本的成员,人们只将它作为派生其他类的基类,而不会用来创建对

    相关 java抽象抽象方法

    使用关键字abstract定义的类叫做抽象类,在抽象类中可以包含抽象方法也可以不包含抽象方法,这意味着你在抽象类里边可以有具体的方法(有实现体)也可以有抽象方法(没有实现,没有

    相关 Java抽象

    抽象类的基本概念 普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的

    相关 java抽象

    java中的抽象类 1.什么是抽象类? 类--通过class关键字创建的java元素。描述具有公共性质的一组事物的自定义复合数据类型。 /\\ \ 普通的java