在 Java 中,抽象类(Abstract Class) 是一种被abstract关键字修饰的特殊类,它不能被直接实例化(无法创建对象),主要用于作为其他类的父类,定义通用的属性和方法,同时声明一些必须由子类实现的抽象方法。
抽象方法只有方法签名(包括方法名、参数列表和返回值类型),没有方法体。简单来说,就是没有大括号:{ },一会我们来看项目中的抽象类来加深影响
我来带大家一步步认识抽象类
比如,老师布置了一篇作文,要求同学们开头和结尾依照范文不变,只修改中间部分,大家想,如何实现呢?
public class Artical {
//一个写作方法
public void write(){
//通用开头
System.out.println("《我的周末》");
System.out.println("当闹钟在周六的清晨第一次响起时," +
"我伸手按掉开关 —— 属于周末的松弛感,便从这片刻的静默里开始蔓延。");
//自己写周末的一天
System.out.println("请写出自己周末的一天,老师的一天是批改作业,备课和写教案");
//通用结尾
System.out.println("周末的尾声总带着一点微妙的不舍," +
"但那些被阳光晒暖的瞬间、被笑声填满的片段,早已悄悄变成了心底的能量。");
System.out.println("或许没有轰轰烈烈的计划," +
"或许只是重复着平凡的日常,但周末的珍贵之处正在于此:" +
"它让我们在熟悉的生活里,重新找到热爱的痕迹。");
}
}
我们学习了继承的方法(不知道的同学可以看小编之前的作品),自然当我们自己写的时候,应该去继承这个文章类,而不是把所有的代码复制到自己的代码中,比如现在有个叫小明的人:
public class Xiaoming extends Artical{}
小明同学继承了文章类,但是有一个问题,这样写出来的文章是不是把我们不想要的中间段也写出来了:
所以我们应该把中间段作为一个方法(Myweek),以便于子类调用时可以对这个中间段进行重写,我们修改一下文章代码:
public class Artical {
//一个写作方法
public void write(){
//通用开头
System.out.println("《我的周末》");
System.out.println("当闹钟在周六的清晨第一次响起时," +
"我伸手按掉开关 —— 属于周末的松弛感,便从这片刻的静默里开始蔓延。");
Myweek();
//通用结尾
System.out.println("周末的尾声总带着一点微妙的不舍," +
"但那些被阳光晒暖的瞬间、被笑声填满的片段,早已悄悄变成了心底的能量。");
System.out.println("或许没有轰轰烈烈的计划," +
"或许只是重复着平凡的日常,但周末的珍贵之处正在于此:" +
"它让我们在熟悉的生活里,重新找到热爱的痕迹。");
}
public void Myweek(){
//自己写周末的一天
System.out.println("请写出自己周末的一天,老师的一天是批改作业,备课和写教案");
}
}
重写小明的Myweek方法:
public class Xiaoming extends Artical{
@Override
public void Myweek(){
System.out.println("我周末和家人去了超市,买了好多好吃的");
}
}
此时小明再写文章,就可以将自己的周末内容写在中间段了:
此时我们就完成了周末作业写作文的这个模拟,诶?你说的抽象类抽象方法呢?别急,这不就来了
纵观我们的这个小项目,有人就提出了:既然别人只是继承你的开头和结尾,不去用你父类中的Myweek方法,那你在方法里写的那么多东西有什么意义呢?删掉吧,反正没人用,行,那我删掉
public class Artical {
//一个写作方法
public void write(){
//通用开头
System.out.println("《我的周末》");
System.out.println("当闹钟在周六的清晨第一次响起时," +
"我伸手按掉开关 —— 属于周末的松弛感,便从这片刻的静默里开始蔓延。");
Myweek();
//通用结尾
System.out.println("周末的尾声总带着一点微妙的不舍," +
"但那些被阳光晒暖的瞬间、被笑声填满的片段,早已悄悄变成了心底的能量。");
System.out.println("或许没有轰轰烈烈的计划," +
"或许只是重复着平凡的日常,但周末的珍贵之处正在于此:" +
"它让我们在熟悉的生活里,重新找到热爱的痕迹。");
}
public void Myweek(){
}
}
又有人说了,你这删掉括号里啥都没有,怪怪的,不美观,咋办?那么此时,抽象方法它带着音响走来了:抽象方法只有方法签名,没有方法体(也就是{ })我们来看:
当用abstract声明我们的抽象方法后,是不允许出现{ }的,同时,抽象有一个原则:抽象类不一定有抽象方法,但是有抽象方法的一定是抽象类
所以当我们在把父类的Myweek方法定义为抽象方法时,必须把父类定义为抽象类,否则会报错:
那么,我们的最终父类方法就出现了:
public abstract class Artical {
//一个写作方法
public void write(){
//通用开头
System.out.println("《我的周末》");
System.out.println("当闹钟在周六的清晨第一次响起时," +
"我伸手按掉开关 —— 属于周末的松弛感,便从这片刻的静默里开始蔓延。");
Myweek();
//通用结尾
System.out.println("周末的尾声总带着一点微妙的不舍," +
"但那些被阳光晒暖的瞬间、被笑声填满的片段,早已悄悄变成了心底的能量。");
System.out.println("或许没有轰轰烈烈的计划," +
"或许只是重复着平凡的日常,但周末的珍贵之处正在于此:" +
"它让我们在熟悉的生活里,重新找到热爱的痕迹。");
}
public abstract void Myweek();
}
大家想一个问题,父类是抽象类,含有抽象方法,而我们子类在继承的时候,是不是会把抽象方法也继承下来?所以在java中,如果父类是抽象类的话,子类继承时只有两个选择,要么将子类也定义成抽象类,要么把继承下来的所有抽象方法进行重写。大多数情况下,子类会选择重写父类所有抽象方法,成为可实例化的具体类。这也更符合常见的一些需求
比如我们这里的写作文,强制子类重写Myweek方法,保留开头和结尾,中间部分去自由发挥,更符合我们的期望。
专业的讲,我们把作为共有的继承方法write类成为模板方法,通常我们不期望别人可以修改我们定义出来的模板方法,所以会在模板方法前加上final关键字(不知道final关键字的同学可以去看小编之前的作品),这样显得我们更加专业
今天的你长知识了吗?喜欢小编的可以点点赞,加个关注~,持续更新java相关知识,后续会有一些简单的项目和大项目
您的点赞和关注是我更新的动力,感谢支持~