在之前的文章我们介绍了一下 Java 类的 private,static,final,本章我们来看一下 Java 中的抽象类和抽象方法。

我们先来看下面一段代码:

 // 根据周长求面积
class Square { // 方形类
double c; double area() { // 方形面积
return 0.0625 * c * c;
}
} class Circle { // 圆形类
double c; double area() { // 圆形面积
return 0.0796 * c * c;
}
}

在上面的代码中我们分别定义了一个方形类和圆形类,然后根据周长计算出各自的面积。咋上面的代码中可以看出这两段代码都有相同的地方,我们第一感觉就是将相同的部分单独封装成一个父类,然后通过集成的方式完成,如下:

 class Shape { // 图形
double c; double area() { // 如果不 return 的话会编译错误
return 系数 * c * c; // 不同形状系数不同
} void area() { // 不会出现编译错误,但是这样写这个方法没有任何意义 }
} // 根据周长求面积
class Square extends Shape { // 方形类 } class Circle extends Shape { // 圆形类 }

在上面的代码中我们单独封装了一个 Shape 类,但是有一个问题,周长 c 是公共的没问题,但是面积 area() 方法却由于不同图形的面积系数不同,没法解决,此时就需要利用抽象方法来解决了,即在方法体前面加 abstract 关键字,如下:

 class Shape { // 图形
double c; abstract double area(); // 抽象方法 --不完整 }

抽象方法的定义:

1、由 abstract 修饰;

2、只有方法的定义,没有方法的实现(大括号都没有);

但是抽象方法是不完整的,所以我们需要将类也变成抽象类,如下:

 abstract class Shape { // 图形 --不完整
double c; abstract double area(); // 抽象方法 --不完整 }

抽象类的定义:

1、由 abstract 修饰;

2、包含抽象方法的类必须是抽象类;

3、抽象类不能被实例化;

4、抽象类是需要被继承的,所以子类需要:

  1)重写所有抽象方法 --- 常用

  2)也声明未抽象类 ---不常用

在第 4 点钟抽象类是需要被继承的,如下代码:

 abstract class Shape { // 图形 --不完整
double c; abstract double area(); // 抽象方法 --不完整 } class Square extends Shape { // 编译错误,因为继承了 Shape 类,Shape 类中包含 抽象方法 } // 改进
abstract class Square extends Shape { // 不报错误,但是 Square 类也变成了抽象类 } // 改进
class Square extends Shape { // 不报错误,将 Square 类中的抽象类重写为非抽象类
double area() {
return 0.0625 * c * c;
}
}

在上面的代码中我们实现了抽象类和抽象方法,但是貌似看上去多此一举,如下:

 class Shape { // 图形 只提取公共变量 c
double c;
} abstract class Shape { // 图形 --不完整
double c; abstract double area(); // 抽象方法 --不完整
}

在上面的代码中,我们完全可以只提取公共变量 周长c 就可以了,因为 area() 方法反正是要重写的,何必多此一举呢。

接下来我们看下面的需求,就是分别以 周长 c = 1,2,3 来创建三个 Square 和 Circle 类,然后找出这 6 个图形中面积最大的一个。我们首先想到的方法应该是这样:

 public class HelloWorld {
public static void main(String[] args) {
Square[] squares = new Square[3];
squares[0] = new Square(1);
squares[1] = new Square(2);
squares[2] = new Square(3); Circle[] circles = new Circle[3];
circles[0] = new Circle(1);
circles[1] = new Circle(2);
circles[2] = new Circle(3); /**
* 1、找到 squares 中最大面积 sMax
* 2、找到 circles 中最大面积 cMax
* 3、比较 sMax 与 cMax 的最大值
*/ }
} class Shape {
double c;
} class Square extends Shape {
Square(double c) {
this.c = c;
} double area() {
return 0.0625 * c * c;
}
} class Circle extends Shape {
Circle(double c) {
this.c = c;
} double area() {
return 0.0796 * c * c;
}
}

在上面的代码中,我们先定义一个数组,里面存数三个周长 c = 1,2,3 的 Square,再定义一个数组,里面存放三个周长 c = 1,2,3 的 Circle,然后我们分别计算出两个数组中面积的最大值再比较出面积最大的一个,这个可以解决我们的问题,但是如果再价格六边形,就需要再定义一个数组,那么我们上面写的代码就出现了 代码重复,扩展性差,维护性差 的问题。

接下来我们用抽象类的方法来写一下:

 public class HelloWorld {
public static void main(String[] args) {
Shape[] shapes = new Shape[6]; // 向上造型
shapes[0] = new Square(1);
shapes[1] = new Square(2);
shapes[2] = new Square(3);
shapes[3] = new Circle(1);
shapes[4] = new Circle(2);
shapes[5] = new Circle(3); double max = shapes[0].area(); // 先假设第一个为最大值
for(int i=1;i<shapes.length;i++){
double area = shapes[i].area();
if(area > max){
max = area;
}
}
System.out.println(max);
}
} abstract class Shape {
double c;
abstract double area();
} class Square extends Shape {
Square(double c) {
this.c = c;
} double area() {
return 0.0625 * c * c;
}
} class Circle extends Shape {
Circle(double c) {
this.c = c;
} double area() {
return 0.0796 * c * c;
}
}

在上面的代码中我们先定义了一个 Shape[] 数组,然后通过向上造型的方式向数组中分别添加 Square 和 Circle,这样就只在一个数组中比较最大值就可以了,当再添加五边形,六边形时只需要扩充 Shape[] 数组就可以了。

抽象类的意义:

1、为其子类提供一个公共的类型 -- 向上造型;

2、封装子类中的重复内容(成员变量和方法);

3、定义有抽象方法,子类虽然有不同的实现,但该方法的定义是一致的。

Java 从入门到进阶之路(十三)的更多相关文章

  1. Java 从入门到进阶之路(二十三)

    在之前的文章我们介绍了一下 Java 中的  集合框架中的Collection 的迭代器 Iterator,本章我们来看一下 Java 集合框架中的Collection 的泛型. 在讲泛型之前我们先来 ...

  2. Java 从入门到进阶之路(一)

    写在前面:从本片文章开始,将记录自己学习 Java 的点滴路程,目标定的并不是让自己成为一个 Java 高手,而是让自己多掌握一门语言,使自己的知识面更广一些,在学习 Java 的过程中如有不对的地方 ...

  3. Java 从入门到进阶之路(二)

    之前的文章我们介绍了一下用 IDEA 编辑器创建一个 Java 项目并输出 HelloWorld,本章我们来看一下 Java 中的变量和基本数据类型. 在这之前我们先来看一下 Java 中的关键字,这 ...

  4. Java 从入门到进阶之路(三)

    之前的文章我们介绍了 Java 中的变量和基本数据类型,本章我们来看一下 Java 的运算符和表达式. 计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富的运算符来操 ...

  5. Java 从入门到进阶之路(四)

    之前的文章我们介绍了 Java 的运算符和表达式,本章我们来看一下 Java 的循环结构. 循环是程序设计语言中反复执行某些代码的一种计算机处理过程,是一组相同或相似语句被有规律的重复性进行. 循环的 ...

  6. Java 从入门到进阶之路(五)

    之前的文章我们介绍了 Java 的循环结构,本章我们来看一下 Java 的数组 数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同. 数组 - 相同数据类型的元 ...

  7. Java 从入门到进阶之路(六)

    之前的文章我们介绍了 Java 的数组,本章我们来看一下 Java 的对象和类. Java 是一种面向对象语言,那什么是对象呢,对象在编程语言中属于一个很宽泛的概念,我们可以认为万事万物都是对象,每个 ...

  8. Java 从入门到进阶之路(七)

    在之前的文章中我们介绍了一下 java 中的对象和类,接下来我们来看一下 Java 中的方法重载. 在显示生活中,我们肯定会遇到这样一个问题,那就是我们再商场买东西的时候在付账时的选择.如下 A:在收 ...

  9. Java 从入门到进阶之路(八)

    在之前的文章我们介绍了一下 Java 中的重载,接下来我们看一下 Java 中的构造方法. 我们之前说过,我们在定义一个变量的时候,java 会为我们提供一个默认的值,字符串为 null,数字为 0. ...

随机推荐

  1. ESP8266 智能配网 断电重连

    ESP8266 智能配网 断电重连 #include <ESP8266WiFi.h> bool autoConfig() { WiFi.begin(); for (int i = 0; i ...

  2. 【python测试开发栈】带你彻底搞明白python3编码原理

    在之前的文章中,我们介绍过编码格式的发展史:[文章传送门-todo].今天我们通过几个例子,来彻底搞清楚python3中的编码格式原理,这样你之后写python脚本时碰到编码问题,才能有章可循. 我们 ...

  3. opencv随笔1

    图像处理技术一般包括图像压缩,增强和复原,匹配 描述和l识别 3 个部分. 图像处理一般指数字图像处理 ( Digitallmage Processing). 其中,数字图像是指用工业相机.摄像机.扫 ...

  4. 用例建模Use Case Modeling

    我的工程实践选题为ESP32低功耗的实现,本项目基于ESP32嵌入式开发平台. 以此题为例,在理解项目需求的基础上进行用例建模,抽取Abstract use case,画出用例图,并确定每一个用例的范 ...

  5. GitHub注册失败,卡在第一步

    同事说他无法注册GitHub,我一开始以为GitHub又无法登录进去,我就登录了自己的GitHub账号,没有问题,可以登录啊,见第一个标签页.同一局域网,不可能我能登录,你无法完成注册啊.于是,我就在 ...

  6. vue-cli从2升级到3报错error 404 Not Found: @wry/context@^0.4.0

    vue3出来了,想尝尝鲜. 于是按官方的方法卸载2安装3. npm uninstall vue-cli -g npm install -g @vue/cli 但是报错了 error 404 Not F ...

  7. 稀疏数组 python描述

    什么是稀疏矩阵? 在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵. 作用: 在这种情况下,很多0值无疑是很浪费空间的,当我们要把数组存储在磁盘中 ...

  8. 《Java基础教程》第一章学习笔记

    Java 是什么呀! 计算机语言总的来说分成机器语言,汇编语言,高级语言.其中Java一种高级计算机语言,它是一种可以编写跨平台应用软件,完全面向对象的程序设计语言. Java划分为三个技术平台,Ja ...

  9. [ch02-03] 梯度下降

    系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI, 点击star加星不要吝啬,星越多笔者越努力. 2.3 梯度下降 2.3.1 从自然现象中理解梯度下降 ...

  10. iOS开发tips-PhotoKit

    概述 PhotoKit应该是iOS 8 开始引入为了替代之前ALAssetsLibrary的相册资源访问的标准库,后者在iOS 9开始被弃用.当然相对于ALAssetsLibrary其扩展性更高,ap ...