在之前的文章我们介绍了一下 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、定义有抽象方法,子类虽然有不同的实现,但该方法的定义是一致的。

最新文章

  1. knockoutJS学习笔记01:从拼接字符串到编写模板引擎
  2. oracle,mysql,SqlServer三种数据库的分页查询的实例。
  3. Windows Store App JavaScript 开发:小球运动示例
  4. 在浏览器中输入URL后执行的全部过程的个人总结
  5. MySQL SELECT执行顺序
  6. Swift随记
  7. ES5和ES6中对于继承的实现方法
  8. Gson解析Json格式数据
  9. WordPress主题制作教程10:添加文章类型插件Custom Post Type UI
  10. zoj 3088 Easter Holidays(最长路+最短路+打印路径)
  11. destoon实现商铺管理主页设置增加新菜单的方法
  12. 【转】JAVA 网络编程
  13. POJ 2411 Mondriaan&#39;s Dream/[二进制状压DP]
  14. linux内核——1.概述
  15. effective java 第2章-创建和销毁对象 读书笔记
  16. python---统计列表中数字出现的次数
  17. Vasya and Basketball CodeForces - 493C
  18. MyLog
  19. whereis命令详解
  20. Confluence 6 手动备份

热门文章

  1. [spark程序]统计人口平均年龄(本地文件)(详细过程)
  2. requests模拟登陆的三种方式
  3. MyBatis 数值类型 where 条件配置的坑
  4. Docker (一) 安装 Oracle18c
  5. 2019-10-23:渗透测试,基础学习,DVWA,Medium和Hight级别sql注入
  6. 请求https前缀的网站验证SSL证书的解决方案之一
  7. SpringCloud Alibaba微服务实战三 - 服务调用
  8. Win8.1系统蓝屏提示Wpprecorder.sys文件故障解决方法
  9. Android Native Binder,在Native层与App交互数据
  10. Linux常用基本命令 (逐步添加)