抽象类(Abstract Class)
抽象类
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法
我们这样定义抽象类:
Employee.java
public abstract class Employee {
private String name;
private String address;
private int number;
public Employee(String name, String address, int number) {
System.out.println("构造一个雇员");
this.name = name;
this.address = address;
this.number = number;
}
public void oneAddress() {
System.out.println("名字为:" + this.name + ",地址为:" + this.address);
}
public void testMethod() {
System.out.println("这是抽象类中的一个测试方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
上述抽象类中构造一个Employee对象,给出了一个someOne()方法,剩下的都是get和set方法,与普通类构造没太大区别。由于抽象类不能被不能直接实例化,所以我们通过构造其子类来操作,下面是其子类代码:
InheritanceEmployee.java
public class InheritanceEmployee extends Employee{
public InheritanceEmployee(String name, String address, int number) {
super(name, address, number);
}
public void oneAddress(){
System.out.println("你的名字是:" + getName());
System.out.println("你的地址是:" + getAddress());
System.out.println("你的数字是:" + getNumber());
}
}
调用方法:
AbstractTest.java
public class AbstractTest {
public static void main(String[] args) {
// 通过子类实例化抽象类
Employee employee = new InheritanceEmployee("小明", "北京", 10010110);
employee.oneAddress();
//调用抽象类中的测试方法
employee.testMethod();
}
}
运行结果:
构造一个雇员
你的名字是:小明
你的地址是:北京
你的数字是:10010110
这是抽象类中的一个测试方法
Process finished with exit code 0
抽象方法
如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
Abstract关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
AbstractA.java
public abstract class AbstractA {
private int a;
public abstract void testA();
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
class SubclassB extends AbstractA {
@Override
public void testA() {
System.out.println("这是抽象父类中的方法");
}
}
在抽象类中的方法只能定义,不能包含方法体。下面是调用方法:
ClassTest.java
public class ClassTest {
public static void main(String []args){
AbstractA abstractA = new SubclassB();
abstractA.testA();
}
}
运行结果:
这是抽象父类中的方法
Process finished with exit code 0
相关习题
1. 定义一个抽象的"Role"类,有姓名,年龄,性别等成员变量。
1)要求尽可能隐藏所有变量(能够私有就私有,能够保护就不要公有),再通过getXXX()和setXXX()方法对各变量进行读写。具有一个抽象的play()方法,该方法不返回任何值,同时至少定义两个构造方法。Role类中要体现出this的几种用法。
2)从Role类派生出一个"Employee"类,该类具有Role类的所有成员(构造方法除外),并扩展salary成员变量,同时增加一个静态成员变量“职工编号(ID)”。同样要有至少两个构造方法,要体现出this和super的几种用法,还要求覆盖play()方法,并提供一个final sing()方法。
3)"Manager"类继承"Employee"类,有一个final成员变量"vehicle",在main()方法中制造Manager和Employee对象,并测试这些对象的方法。
PracticeOne.java
abstract class Role {
private String name;
private int age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public abstract void play(); // 抽象方法
public Role() {
System.out.println("这是抽象类Role中蛋疼的方法");
}
public Role(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
}
class EmployeeOne extends Role {
private double salary;
private static String ID;
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public static String getID() {
return ID;
}
public static void setID(String iD) {
ID = iD;
}
public EmployeeOne() {
System.out.println("这是EmployeeOne中蛋疼的方法");
}
public EmployeeOne(String name, int age, String sex, double salary, String ID) {
super(name, age, sex);
this.salary = salary;
this.ID = ID;
}
@Override
public void play() {
// 重写抽象类中的play()方法
System.out.println("员工编号:" + this.getID());
}
final void employeeInfo() {
System.out.println("员工姓名:" + this.getName() + "员工性别:" + this.getSex() + "员工年龄:" + this.getAge() + "员工工资:" + this.getSalary());
}
}
class Manager extends EmployeeOne {
final String vehicle;
public Manager(String name, int age, String sex, double salary, String ID, String vehicle) {
super(name, age, sex, salary, ID);
this.vehicle = "保时捷";
}
}
public class PracticeOne {
public static void main(String[] args) {
// 构造EmployeeOne
EmployeeOne employeeOne = new EmployeeOne("张三", 18, "男", 5000, "123456");
employeeOne.play();
employeeOne.employeeInfo();
// 构造Manager
Manager manager = new Manager("李四", 20, "男", 4500, "123457", "");
manager.play();
manager.employeeInfo();
System.out.println("座驾是:" + manager.vehicle);
}
}
运行结果:
员工编号:123456
员工姓名:张三员工性别:男员工年龄:18员工工资:5000.0
员工编号:123457
员工姓名:李四员工性别:男员工年龄:20员工工资:4500.0
座驾是:保时捷
Process finished with exit code 0
2. 编写一个Java应用程序,要求实现如下类之间的继承关系:
1)编写一个抽象类Shape,该类具有两个属性:周长length和面积area,具有两个抽象的方法:计算周长getLength()和计算面积getArea()。
2)编写非抽象类矩形Rectangle和圆形Circle继承类Shape。
3)编写一个锥体类Cone,里面包含两个成员变量Shape类型的底面bottom和double类型的高height。
4)定义一个公共的主类TestShape,包含一个静态的方法void compute(Shape e),通过该方法能够计算并输出一切图形的周长和面积;在主方法中调用compute方法,计算并输出某矩形和圆形的周长和面积,并测试锥体类Cone。
TestShape.java
interface ConstantValue {
double PI = 3.1415926; // 设置定值PI
}
abstract class Shape {
double length;
double area;
abstract double getLength(); // 构造虚方法
abstract double getArea(); // 构造虚方法
}
class Circle extends Shape {
double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
double getLength() {
length = 2 * ConstantValue.PI * radius;
return length;
}
@Override
double getArea() {
area = ConstantValue.PI * radius * radius;
return area;
}
}
class Rectangle extends Shape{
double width,height;
Rectangle(double width,double height){
this.width = width;
this.height = height;
}
@Override
double getLength() {
length = (width + height) * 2;
return length;
}
@Override
double getArea() {
area = width * height;
return area;
}
}
class Cone {
Shape bottom;
double height;
public Cone(Shape bottom, double height) {
super();
this.bottom = bottom;
this.height = height;
}
double getVolume() {
return bottom.getArea() * height / 3;
}
}
public class TestShape {
public static void compute(Shape shape){
System.out.println(shape.getClass());
System.out.println("周长为:" + shape.getLength());
System.out.println("面积为:" + shape.getArea());
}
public static void main(String []args){
Circle circle = new Circle(5);
Rectangle rectangle = new Rectangle(3,5);
System.out.println("创建一个底面为圆形的椎体");
Cone cone = new Cone(circle,10);
compute(circle);
System.out.println("体积为:" + cone.getVolume());
System.out.println("------------这是华丽的分割线-------------");
System.out.println("创建一个底面为矩形的椎体");
cone = new Cone(rectangle,10);
compute(rectangle);
System.out.println("体积为:" + cone.getVolume());
}
}
运行结果:
创建一个底面为圆形的椎体
class Circle
周长为:31.415926
面积为:78.539815
体积为:261.7993833333333
------------这是华丽的分割线-------------
创建一个底面为矩形的椎体
class Rectangle
周长为:16.0
面积为:15.0
体积为:50.0
Process finished with exit code 0
抽象类的规则 :
注意:
抽象类不能被实例化;
其包含的抽象方法必须在其子类中被实现,否则该子类只能声 明为abstract;
抽象方法不能为static;
在下列情况下,一个类必须声明为抽象类:
当一个类的一个或多个方法是抽象方法时;
当类是一个抽象类的子类,并且没有实现父类的所有抽象方法, 即只实现部分;
当一个类实现一个接口,并且不能为全部抽象方法都提供实现 时;
网友评论