Java开发笔记(五十七)因抽象方法而产生的抽象类
前面介绍了类的常见用法,令人感叹面向对象的强大,几乎日常生活中的所有事物,都可以抽象成Java的基类及其子类。然而抽象操作也有副作用,就是某个抽象而来的行为可能是不确定的,比如半夜鸡叫,如果是公鸡则必定“喔喔喔”地叫,如果是母鸡则必定“咯咯咯”地叫,可要是不能确定这只鸡是公鸡还是母鸡抑或小鸡,系统怎么知道它会怎么叫?落实到鸡类Chicken的定义代码中,它的call方法便无法给出具体的叫声了,尽管鸡类能够派生出公鸡类和母鸡类,再在公鸡类和母鸡类重写call方法,但是外部仍然可以创建鸡类的实例,接着调用鸡类实例的call方法,此时该期望这只鸡发出什么叫声呢?不管是让鸡类胡言乱语、语无伦次,还是让鸡类默不作声、噤若寒蝉,显然都与真实情况有很大出入。
由此可见,某些类其实并不能拿来直接使用,充其量只能算半成品,必须经过进一步的加工,形成最终的成品方能给外部调用。鉴于前述的鸡类存在叫唤这个不确定的方法,故而理应将它归入半成品之列;至于由鸡类派生而来的公鸡类与母鸡类,因为包括叫唤在内的每个方法都是明确的,所以它们才成为机能鉴权的完整类。在Java编程中,功能不确定的方法被称作抽象方法,而包含抽象方法的类受到牵连就变成了抽象类。在类的定义代码里面,通过关键字abstract来标识抽象方法及抽象类;凡是被abstract修饰的抽象方法,由于方法的具体实现并不明确,因此抽象方法没有花括号所包裹着的方法体;凡是被abstract修饰的抽象类,由于包含了至少一个抽象方法,因此不允许外部创建抽象类的实例,否则就会出现鸡类实例不知如何叫唤的尴尬。除此之外,抽象类还有下列两点需要注意:
1、abstract只能用来修饰抽象方法和抽象类,不可用于修饰成员属性,因为属性值本身就允许通过赋值来改变,无所谓抽象不抽象。
2、虽然抽象类依旧可以拥有构造方法,但它的构造方法并不能被外部直接调用,因为外部不允许通过构造方法来创建抽象类的实例,抽象类的构造方法只能提供给它的子类调用。
絮絮叨叨了这么多抽象概念,接着尝试把之前的鸡类改写成抽象类,修改后的抽象鸡类定义代码示例如下:
//演示抽象类的定义
abstract public class Chicken { // 定义一个名称属性
public String name;
// 定义一个性别属性
public int sex; // 定义一个抽象的叫唤方法。注意后面没有花括号,并且以分号结尾
abstract public void call(); // 即使抽象类定义了构造方法,外部也无法创建它的实例
public Chicken() {
} // Java只有抽象类和抽象方法,没有抽象属性的说法
//abstract public String cry;
}
然后分别编写继承自鸡类的公鸡类和母鸡类,其中鸡类的抽象方法call是必须在子类中重写的,只有这样,派生而来的子类才具备所有完善的行为动作;否则的话,这个子类仍旧是个尚未完工的半成品,依然属于抽象类的行列。下面是重写了call方法的公鸡类代码例子:
//定义一个继承自抽象鸡类的公鸡类
public class Cock extends Chicken { public Cock() {
// 公鸡的性别固定为雄性
sex = 0;
} // 重写了公鸡的叫唤方法。如果不重写父类的抽象方法,那么该子类仍旧为抽象类
public void call() {
System.out.println("喔喔喔");
}
}
同样重写了call方法的母鸡类代码如下所示:
//定义一个继承自抽象鸡类的母鸡类
public class Hen extends Chicken { public Hen() {
// 母鸡的性别固定为雌性
sex = 1;
} // 重写了母鸡的叫唤方法。如果不重写父类的抽象方法,那么该子类仍旧为抽象类
public void call() {
System.out.println("咯咯咯");
}
}
最后轮到外部调用各种鸡类了,对于外部而言,唯一的区别是外部不能创建抽象类的实例,其它子类的调用则跟从前一样没有变化。具体的外部调用代码见下:
// 不能创建抽象类的实例,因为抽象类是个尚未完工的类
//Chicken chicken = new Chicken();
// 创建一个公鸡实例,公鸡类继承自抽象类Chicken
Cock cock = new Cock();
cock.call(); // 调用公鸡实例的叫唤方法
// 创建一个母鸡实例,母鸡类继承自抽象类Chicken
Hen hen = new Hen();
hen.call(); // 调用母鸡实例的叫唤方法
运行上面的调用代码,得到以下的日志结果,可见子类重写后的call方法正常工作。
喔喔喔
咯咯咯
更多Java技术文章参见《Java开发笔记(序)章节目录》
Java开发笔记(五十七)因抽象方法而产生的抽象类的更多相关文章
- Java开发笔记(十七)各得其所的多路分支
前面提到条件语句的标准格式为“if (条件) { /* 条件成立时的操作代码 */ } else { /* 条件不成立时的操作代码 */ }”,乍看之下仿佛只有两个分支,一个是条件成立时的分支,另一个 ...
- Java开发笔记(序)章节目录
现将本博客的Java学习文章整理成以下笔记目录,方便查阅. 第一章 初识JavaJava开发笔记(一)第一个Java程序Java开发笔记(二)Java工程的帝国区划Java开发笔记(三)Java帝国的 ...
- Java开发笔记(三十七)利用正则串分割字符串
前面介绍了处理字符串的常用方法,还有一种分割字符串的场景也很常见,也就是按照某个规则将字符串切割为若干子串.分割规则通常是指定某个分隔符,根据字符串内部的分隔符将字符串进行分割,例如逗号.空格等等都可 ...
- Java开发笔记(五十八)简单接口及其实现
前面介绍了抽象方法及抽象类的用法,看似解决了不确定行为的方法定义,既然叫唤动作允许声明为抽象方法,那么飞翔.游泳也能声明为抽象方法,并且鸡类涵盖的物种不够多,最好把这些行为动作扩展到鸟类这个群体,于是 ...
- Java开发笔记(五十九)Java8之后的扩展接口
前面介绍了接口的基本用法,有心的朋友可能注意到这么一句话“在Java8以前,接口内部的所有方法都必须是抽象方法”,如此说来,在Java8之后,接口的内部方法也可能不是抽象方法了吗?之所以Java8对接 ...
- Java开发笔记(六十五)集合:HashSet和TreeSet
对于相同类型的一组数据,虽然Java已经提供了数组加以表达,但是数组的结构实在太简单了,第一它无法直接添加新元素,第二它只能按照线性排列,故而数组用于基本的操作倒还凑合,若要用于复杂的处理就无法胜任了 ...
- Java开发笔记(六十七)清单:ArrayList和LinkedList
前面介绍了集合与映射两类容器,它们的共同特点是每个元素都是唯一的,并且采用二叉树方式的类型还自带有序性.然而这两个特点也存在弊端:其一,为啥内部元素必须是唯一的呢?像手机店卖出了两部Mate20,虽然 ...
- Java开发笔记(九十五)NIO配套的文件工具Files
NIO不但引进了高效的文件通道,而且新增了更加好用的文件工具家族,包括路径组工具Paths.路径工具Path.文件组工具Files.先看路径组工具Paths,该工具提供了静态方法get,输入某个文件的 ...
- Java开发笔记(八十七)随机访问文件的读写
前面介绍了字符流读写文件的两种方式,包括文件字符流和缓存字符流,但是它们的写操作都存在一个问题:不管是write方法还是append方法,都只能从文件开头写入,而不能追加到文件末尾或者在文件中间某个位 ...
随机推荐
- Vue 学习笔记 — 无法避免的dom操作
简书 使用Vue了一段时间,感觉确实不错,"数据驱动视图"非常好用,大部分情况下都不需要关心dom,但是凡事都有例外,总有一些时候我们必须要直接对dom进行操作,比如下面这个例子: ...
- 解决idea导入项目后依赖报错问题
1.在idea首页 Confige-->setting-->build,execution,deployment-->buildTool-->maven-->work o ...
- 【安富莱专题教程第5期】工程调试利器RTT实时数据传输组件,替代串口调试,速度飞快,可以在中断和多任务中随意调用
说明:1.串口作为经典的调试方式已经存在好多年了,缺点是需要一个专门的硬件接口.现在有了SEGGER的RTT(已经发布有几年了),无需占用系统额外的硬件资源,而且速度超快,是替代串口调试的绝佳方式.2 ...
- Pycharm中配置鼠标悬停快速提示方法参数
第一步: 第二步: 演示:
- [Swift]LeetCode267.回文全排列 II $ Palindrome Permutation II
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...
- [Swift]LeetCode315. 计算右侧小于当前元素的个数 | Count of Smaller Numbers After Self
You are given an integer array nums and you have to return a new countsarray. The counts array has t ...
- [Swift]LeetCode401. 二进制手表 | Binary Watch
A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom ...
- Ubuntu12.04中的虚拟机安装Ubuntu16.04,并实现远程控制16.04
目录 1.设置网络连接 1.1 VMware虚拟机网络地址设置 1.2 设置虚拟机内Ubuntu16.04的网络模式 未开机状态下 开机状态下 1.3 查看虚拟机中Ubuntu16.04的IP 2.进 ...
- springboot中实现多数据源
springboot中实现多数据源 1.什么场景需要多数据源 业务读写分离 业务分库 业务功能模块拆分多库 2.常见的多数据源的方案 按照数据源分别把mapper和entity放到不同的package ...
- Kubernetes 笔记 07 豌豆荚之旅(二)
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. Hi,大家好, ...