概述
抽象类和抽象方法
Java 语言提供了两种类,分别为具体类和抽象类。前面学习接触的类都是具体类。这一节介绍一下抽象类。
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,那么这样的类称为抽象类,抽象类、抽象方法使用 abstract 修饰。
格式
在 Java 中抽象类的语法格式如下:
1 2 3
| <abstract>class<class_name> { <abstract><type><method_name>(parameter-iist); }
|
其中,abstract 表示该类或该方法是抽象的;class_name 表示抽象类的名称;method_name 表示抽象方法名称,parameter-list 表示方法参数列表。
如果一个方法使用 abstract 来修饰,则说明该方法是抽象方法,抽象方法只有声明没有实现。需要注意的是 abstract 关键字只能用于普通方法,不能用于 static 方法或者构造方法中。
抽象方法
抽象方法的 3 个特征如下:
- 抽象方法只有方法的声明,没有方法体
- 抽象方法必须存在于抽象类中
- 子类重写父类时,必须重写父类所有的抽象方法
注意:在使用 abstract 关键字修饰抽象方法时不能使用 private 修饰,因为抽象方法必须被子类重写,而如果使用了 private 声明,则子类是无法重写的。
抽象类
抽象类的定义和使用规则如下:
- 抽象类和抽象方法都要使用 abstract 关键字声明。
- 如果一个方法被声明为抽象的,那么这个类也必须声明为抽象的。而一个抽象类中,可以有 0
n 个抽象方法,以及 0n 个具体方法。 - 抽象类不能实例化,也就是不能使用 new 关键字创建对象。
举例说明
不同几何图形的面积计算公式是不同的,但是它们具有的特性是相同的,都具有长和宽这两个属性,也都具有面积计算的方法。那么可以定义一个抽象类,在该抽象类中含有两个属性(width 和 height)和一个抽象方法 area( ),具体步骤如下。
1)首先创建一个表示图形的抽象类 Shape,代码如下所示:
1 2 3 4 5 6 7 8 9 10 11
| public abstract class Shape { public int width; public int height;
public Shape(int width, int height) { this.width = width; this.height = height; }
public abstract double area(); }
|
2)定义一个正方形类,该类继承自形状类 Shape,并重写了 area( ) 抽象方法。正方形类的代码如下:
1 2 3 4 5 6 7 8 9 10
| public class Square extends Shape { public Square(int width, int height) { super(width, height); }
@Override public double area() { return width * height; } }
|
3)定义一个三角形类,该类与正方形类一样,需要继承形状类 Shape,并重写父类中的抽象方法 area()。三角形类的代码实现如下:
1 2 3 4 5 6 7 8 9 10
| public class Triangle extends Shape { public Triangle(int width, int height) { super(width, height); }
@Override public double area() { return 0.5 * width * height; } }
|
4)最后创建一个测试类,分别创建正方形类和三角形类的对象,并调用各类中的 area() 方法,打印出不同形状的几何图形的面积。测试类的代码如下:
1 2 3 4 5 6 7 8 9 10
| public class AbstractTest { public static void main(String[] args) { Square square = new Square(5, 4); System.out.println("正方形面积为:" + square.area());
Triangle triangle = new Triangle(2, 5); System.out.println("三角形面积为:" + triangle.area()); } }
|
补充知识点
示例代码:匿名子类、匿名子类的匿名对象,并重写了父类中的 eat() 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| package com.base.learn;
public class AnonymityTest { public static void main(String[] args) { Person p = new Person(); method(p);
method(new Person());
Person p1 = new Person() { @Override public void eat() { System.out.println("吃东西 -- 匿名子类对象创建"); } }; method(p1);
method(new Person() { @Override public void eat() { System.out.println("吃东西 -- 匿名子类的匿名对象创建"); } }); }
public static void method(Person person) { person.eat(); } }
class Person { String name; int age;
public Person() { }
public Person(String name, int age) { this.name = name; this.age = age; }
public void eat() { System.out.println("人吃饭"); }
public void breath() { System.out.println("人呼吸"); } }
|
结合本节抽象类 abstract 的使用方法,由于 Person1 是抽象类,子类必须重写父类的抽象方法,如果不重写就报错了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.base.learn;
public class AnonymityTest2 { public static void main(String[] args) { Person1 p1 = new Person1() { @Override public void eat() { System.out.println("创建了一个匿名子类的对象p1,由于 Person1 是抽象类,子类必须重写父类的抽象方法"); } }; method(p1);
System.out.println("----------------------");
method(new Person1() { @Override public void eat() { System.out.println("创建了匿名子类的匿名对象,由于 Person1 是抽象类,子类必须重写父类的抽象方法"); } }); }
public static void method(Person1 person1){ person1.eat(); } }
abstract class Person1 { public Person1() { } public abstract void eat(); }
|