抽象类

抽象类是为了方法覆写而提供的类结构,因为其无法自身直接进行对象实例化操作,所以在实际应用中,抽象类主要目的是进行过程操作使用,当你要使用抽象类进行开发的时候,往往都是在你设计中需要解决类继承问题时所带来的的代码重复处理。

普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的结构里面增加抽象方法的组成部分。

在这里小编建了一个前端学习交流扣扣群:1093794329,我自己整理的最新的前端资料和高级开发教程,如果有想需要的,可以加群一起学习交流

那么什么叫抽象方法呢?所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。而拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。

抽象类已经实现的方法是为了代码复用,待实现的方法是为了限制子类的功能。

定义一个抽象类

/*定义一个抽象类*/

abstract class AbstractMessage{

/*提供setter getter*/

private String infoString ;

/*构造方法*/

public AbstractMessage(String info) {

this.infoString = info;

}

/*普通方法*/

public String getInfo() {

return this.infoString;

}

/*抽象方法,没有方法体,有abstract关键字做修饰*/

public abstract void send() ;

}

使用抽象类

首先,我们直接实例化抽象类的对象,看下是否可以直接进行实例化抽象类,代码示例如下。

abstract class AbstractMessage{

/*提供setter getter*/

private String infoString ;

/*构造方法*/

public AbstractMessage(String info) {

this.infoString = info;

}

/*普通方法*/

public String getInfo() {

return this.infoString;

}

/*抽象方法,没有方法体,有abstract关键字做修饰*/

public abstract void send() ;

}

public class Students {

public static void main(String[] args) {

System.out.println();

AbstractMessage messageInfo = new AbstractMessage("芝兰生于深谷,不以无人而不芳\r\n" + "君子修身养德,不以穷困而改志") ;

messageInfo.send();

}

}

运行上述代码,通过如下结果可知,AbstractMessage抽象类是无法直接进行实例化操作。

Error:(21, 39) java: abstractMessage是抽象的; 无法实例化

那么为什么无法被直接实例化呢,试想当一个类实例化之后,那么可以通过对象调用类的属性或方法,但由于抽象方法并没有方法体,因此无法进行调用。既然无法进行方法调用的话,又怎么去产生实例化对象呢。

抽象类的使用约束:

抽象类不能直接实例化,抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类,需要依靠子类采用向上转型的方式处理;

抽象方法必须为public或者protected,因为如果为private,则不能被子类继承,子类便无法实现该方法,当缺省情况下默认为public;

子类(不是抽象类)必须覆写抽象类之中的全部抽象方法;

代码示例如下:

public class Lian {

public static void main(String[] args) {

System.out.println();

/*向上转型*/

AbstractMessage messageInfo = new message("芝兰生于深谷,不以无人而不芳\r\n" + "君子修身养德,不以穷困而改志") ;

messageInfo.send();

}

}

abstract class AbstractMessage{

/*提供setter getter*/

private String infoString ;

/*构造方法*/

public AbstractMessage(String info) {

this.infoString = info;

}

/*普通方法*/

public String getInfo() {

return this.infoString;

}

/*抽象方法,没有方法体,有abstract关键字做修饰*/

public abstract void send() ;

}

/*message类是抽象类的子类,是普通类*/

class message extends AbstractMessage {

public message(String info) {

super(info); //抽象类存在有参构造方法,子类必须明确调用有参构造。

}

/*强制要求覆写*/

@Override

public void send() {

System.out.println("发送信息\n"+super.getInfo());

}

}

运行结果如下:

发送信息

芝兰生于深谷,不以无人而不芳

君子修身养德,不以穷困而改志

通过如上运行结果,可以发现:

继承抽象类的子类必须覆写抽象方法,而继承普通类的子类可以选择性的覆写其中方法;

抽象类较普通类而言,多了抽象方法,其他组成部分和普通类一样,普通类对象可以直接进行实例化,但抽象类的对象必须通过子类向上转型进行实例化。

抽象类中允许有构造方法?

由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。 并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。

范例如下:

public class Lian {

public static void main(String[] args) {

System.out.println();

/*向上转型*/

AbstractMessage messageInfo = new message("芝兰生于深谷,不以无人而不芳\r\n" + "君子修身养德,不以穷困而改志") ;

messageInfo.send();

}

}

abstract class AbstractMessage{

/*提供setter getter*/

private String infoString ;

/*构造方法*/

public AbstractMessage(String info) {

this.infoString = info;

System.out.println("abstractMessage 构造方法");

}

/*普通方法*/

public String getInfo() {

return this.infoString;

}

/*抽象方法,没有方法体,有abstract关键字做修饰*/

public abstract void send() ;

}

/*message类是抽象类的子类,是普通类*/

class message extends AbstractMessage {

/*抽象类存在有参构造方法,子类必须明确调用有参构造。*/

public message(String info) {

super(info);

System.out.println("message 构造方法");

}

/*强制要求覆写*/

@Override

public void send() {

System.out.println("发送信息\n"+super.getInfo());

}

}

执行结果:

abstractMessage 构造方法

message 构造方法

发送信息

芝兰生于深谷,不以无人而不芳

君子修身养德,不以穷困而改志

抽象类允许使用final声明?

因为抽象类必须有子类,而final定义的类不能有子类,因此抽象类运行不能final声明。

抽象类允许使用static声明?

如下一个外部抽象类的示例:

public class Lian {

public static void main(String[] args) {

System.out.println();

/*向上转型*/

AbstractMessage messageInfo = new message("芝兰生于深谷,不以无人而不芳\r\n" + "君子修身养德,不以穷困而改志") ;

messageInfo.send();

}

}

static  abstract class AbstractMessage{

/*提供setter getter*/

private String infoString ;

/*构造方法*/

public AbstractMessage(String info) {

this.infoString = info;

System.out.println("abstractMessage 构造方法");

}

/*普通方法*/

public String getInfo() {

return this.infoString;

}

/*抽象方法,没有方法体,有abstract关键字做修饰*/

public abstract void send() ;

}

/*message类是抽象类的子类,是普通类*/

class message extends abstractMessage {

/*抽象类存在有参构造方法,子类必须明确调用有参构造。*/

public message(String info) {

super(info);

System.out.println("message 构造方法");

}

/*强制要求覆写*/

@Override

public void send() {

System.out.println("发送信息\n"+super.getInfo());

}

}

Error:(12, 18) java: 此处不允许使用修饰符static

再看一个关于内部抽象类:

public class Lain {

public static void main(String[] args) {

System.out.println();

/*向上转型*/

AbstractMessage.AbstractMessageChild messageInfo = new message("芝兰生于深谷,不以无人而不芳\r\n" + "君子修身养德,不以穷困而改志") ;

messageInfo.send();

}

}

abstract class AbstractMessage{

static abstract class AbstractMessageChild{//static定义的内部类属于外部类

/*提供setter getter*/

private String infoString ;

/*构造方法*/

public AbstractMessageChild(String info) {

this.infoString = info;

System.out.println("abstractMessageChild 构造方法");

}

/*普通方法*/

public String getInfo() {

return this.infoString;

}

/*抽象方法,没有方法体,有abstract关键字做修饰*/

public abstract void send() ;

}

}

/*message类是抽象类的子类,是普通类*/

class message extends AbstractMessage.AbstractMessageChild {

/*抽象类存在有参构造方法,子类必须明确调用有参构造。*/

public message(String info) {

super(info);

System.out.println("message 构造方法");

}

/*强制要求覆写*/

@Override

public void send() {

System.out.println("发送信息\n"+super.getInfo());

}

}

执行结果如下:

abstractMessageChild 构造方法

message 构造方法

发送信息

芝兰生于深谷,不以无人而不芳

君子修身养德,不以穷困而改志

由此可见,外部抽象类不允许使用static声明,而内部的抽象类运行使用static声明。使用static声明的内部抽象类相当于一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类名称。

可以直接调用抽象类中用static声明的方法么? 任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。 范例如下:

public class Lain {

public static void main(String[] args) {

abstractMessage.getInfo();

}

}

abstract class AbstractMessage{

/*静态方法*/

public static void getInfo() {

System.out.println("芝兰生于深谷,不以无人而不芳\r\n君子修身养德,不以穷困而改志");

}

/*抽象方法,没有方法体,有abstract关键字做修饰*/

public abstract void send() ;

}

/*message类是抽象类的子类,是普通类*/

class message extends AbstractMessage {

/*强制要求覆写*/

@Override

public void send() {

System.out.println("发送信息\n");

}

}

运行结果:

芝兰生于深谷,不以无人而不芳

君子修身养德,不以穷困而改志

(5)有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略掉外部子类。这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。 范例如下:

public class Lain {

public static void main(String[] args) {

AbstractMessage abstractMessage = AbstractMessage.getInstance();

abstractMessage.send();

}

}

abstract class AbstractMessage{

/*抽象方法,没有方法体,有abstract关键字做修饰*/

public abstract void send() ;

/*静态方法*/

public static void getInfo() {

System.out.println("芝兰生于深谷,不以无人而不芳\r\n君子修身养德,不以穷困而改志");

}

/*内部抽象类子类*/

private static class AbstractMessageChild extends AbstractMessage{//内部抽象类子类

public void send(){//覆写抽象类的方法

System.out.println("发送信息 !");

}

}

/*静态方法*/

public static AbstractMessage getInstance(){

return new AbstractMessageChild();

}

}

运行结果:

发送信息 !

抽象类之模板设计模式

模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。模板方法模式是基于继承的代码复用基本技术,模板方法模式的结构和用法也是面向对象设计的核心之一。在模板方法模式中,可以将相同的代码放在父类中,而将不同的方法实现放在不同的子类中。

在模板方法模式中,我们需要准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来让子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板方法模式的用意。模板方法模式体现了面向对象的诸多重要思想,是一种使用频率较高的模式。

例如,现在有如下三类事务:

机器人:充电、工作;

人:吃饭、工作、睡觉;

猪:吃饭、睡觉;

现要求实现一个程序, 通过抽象类定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现可以实现三种不同事物的行为。

abstract class AbstractAction{

public static final int EAT = 1 ;

public static final int SLEEP = 3 ;

public static final int WORK = 5 ;

public abstract void eat();

public abstract void sleep();

public abstract void work();

public void commond(int flags){

switch(flags){

case EAT:

this.eat();

break;

case SLEEP:

this.sleep();

break;

case WORK:

this.work();

break;

default:

break;

}

}

}

定义一个机器人的类,如下:

class Robot extends AbstractAction{

@Override

public void eat() {

System.out.println("机器人充电");

}

@Override

public void sleep() {

}

@Override

public void work() {

System.out.println("机器人工作");

}

}

定义一个人的类,如下:

class Person extends AbstractAction{

@Override

public void eat() {

System.out.println("人吃饭");

}

@Override

public void sleep() {

System.out.println("人睡觉");

}

@Override

public void work() {

System.out.println("人工作");

}

}

定义一个猪的类,如下:

class Pig extends AbstractAction{

@Override

public void eat() {

System.out.println("猪吃饭");

}

@Override

public void sleep() {

System.out.println("猪睡觉");

}

@Override

public void work() {

}

}

主类如下:

public class Students {

public static void main(String[] args) {

run(new Robot());

run(new Person());

run(new Pig());

}

public static void run(AbstractAction abstractAction){

abstractAction.commond(AbstractAction.EAT);

abstractAction.commond(AbstractAction.SLEEP);

abstractAction.commond(AbstractAction.WORK);

}

}

运行结果:

机器人充电

机器人工作

人吃饭

人睡觉

人工作

猪吃饭

猪睡觉

所有的子类如果要想正常的完成操作,必须按照指定的方法进行覆写才可以,而这个时候抽象类所起的功能就是一个类定义模板的功能。

模板设计模式的优缺点

模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。 2.)缺点 每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。 3.)适用场景 在某些类的算法中,用了相同的方法,造成代码的重复。控制子类扩展,子类必须遵守算法规则。

java 抽象属性 设计_Java 抽象类与模板设计模式详解相关推荐

  1. 【26天高效学完Java编程】Day11:继承、抽象类、模板设计模式详解

    本专栏将从基础开始,循序渐进,由浅入深讲解Java的基本使用,希望大家都能够从中有所收获,也请大家多多支持. 专栏地址:26天高效学习Java编程 相关软件地址:软件地址 所有代码地址:代码地址 如果 ...

  2. java闰年判断原理_java 面试题闰年判断详解及实例

    java 面试题闰年判断详解及实例 java 闰年判断 前言: 给定一个年份,判断这一年是不是闰年. 当以下情况之一满足时,这一年是闰年: 1. 年份是4的倍数而不是100的倍数: 2. 年份是400 ...

  3. java读取本地文件_java 读取本地文件实例详解

    java 读取本地文件实例详解 用javax.xml.w3c解析 实例代码: package cn.com.xinli.monitor.utils; import org.w3c.dom.Docume ...

  4. java做jsp问题_java/jsp中 中文问题详解

    java/jsp中 中文问题详解 更新时间:2006年10月13日 00:00:00   作者: 预备知识: 1.字节和unicode Java内核是unicode的,就连class文件也是,但是很多 ...

  5. java 读取本地文件_java 读取本地文件实例详解

    java 读取本地文件实例详解 用javax.xml.w3c解析 实例代码: package cn.com.xinli.monitor.utils; import org.w3c.dom.Docume ...

  6. java语言数据库编程_JAVA语言数据库编程实例详解

    本文主要向大家介绍了JAVA语言数据库编程实例详解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. DOS命令登录MySQL数据库:mysql -h 127.0.0.1 -u root ...

  7. java编程50实例_java编程实例大全及详解谜底(50例).doc

    java编程实例大全及详解谜底(50例).doc 还剩 33页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保! 内容要点: 谓 ...

  8. java list 移除_java 中List删除实例详解

    java 中List删除实例详解 1.循环删除List中的元素 public static void main(String[] args) { List t=new ArrayList(); for ...

  9. java中throws用法_java中throws实例用法详解

    在程序出现异常时,会有一个抛出异常的throw出现,这里我们要跟今天所讲的throws区分开.throws的作用是声明抛出,在名称上也跟throw有所不同.下面我们就throws对策概念.语法.实例带 ...

最新文章

  1. java全能速查宝典.chm_Java API 快速速查宝典
  2. react中使用create-react-app创建项目执行函数两次
  3. windows核心编程-第二章 Unicode
  4. 2019年工程造价表_2019年工程造价咨询统计公报
  5. 在.NET Core中使用Exceptionless分布式日志收集框架
  6. text 两端对齐 小程序_leetcode 68 文本左右对齐
  7. linux之抓包神器tcpdump
  8. github可以刷星吗_GitHub 没有 star,该写进简历里吗?
  9. matlab多折线图,MATLAB画出堆叠折线图
  10. 第四节:EasyUI的一些操作
  11. 软件类配置(五)【强化学习算法框架-Ubuntu16.04安装谷歌Dopamine及初步测试】
  12. 手机组态软件_安卓平板组态软件​_移动端组态
  13. Gesture-Recognition
  14. python交易是什么意思_py交易什么梗?起源及流行原因
  15. 原始混合合成器:Arturia Analog Lab for Mac
  16. 苹果youtube无法连接网络_解决苹果手机Apple ID被禁止下载或无法连接到AppStore等问题...
  17. HC05主从一体化蓝牙模块配置
  18. 背景图片填满整个Div
  19. 1D Barcode图片组件,支持线性和邮政符号
  20. GMTUTC,UNIX时间戳,时区

热门文章

  1. ConcurrentLInkedQueue队列
  2. Thymeleaf循环遍历
  3. Java 应用性能调优,可视化工具
  4. 重磅!!面试季--最新面试题总结出厂,附题解,后期持续分享!
  5. 重温java web过滤器filter
  6. shiro教程(1)-基于url权限管理
  7. a标签的四种链接状态
  8. Java事件处理机制和适配器
  9. Eclipse导入项目常见问题----服务器版本问题02
  10. java 编译引入库_eclipse编译cpp文件,并且引用其他预编译的库