抽象类(Abstract Class)抽象类 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。 父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法
我们这样定义抽象类:
Employee.javapublic abstract classEmployee {
privateString name;privateString address;private intnumber;publicEmployee(String name,String address, intnumber) {
System.out.println("构造一个雇员");this.name= name;this.address= address;this.number= number;}
public voidoneAddress() {
System.out.println("名字为:"+ this.name+ ",地址为:"+ this.address);}
public voidtestMethod() {
System.out.println("这是抽象类中的一个测试方法");}
publicString getName() {
returnname;}
public voidsetName(String name) {
this.name= name;}
publicString getAddress() {
returnaddress;}
public voidsetAddress(String address) {
this.address= address;}
public intgetNumber() {
returnnumber;}
public voidsetNumber(intnumber) {
this.number= number;}
}
上述抽象类中构造一个Employee对象,给出了一个someOne()方法,剩下的都是get和set方法,与普通类构造没太大区别。由于抽象类不能被不能直接实例化,所以我们通过构造其子类来操作,下面是其子类代码:
InheritanceEmployee.javapublic classInheritanceEmployee extendsEmployee{
publicInheritanceEmployee(String name,String address, intnumber) {
super(name,address,number);}
public voidoneAddress(){
System.out.println("你的名字是:"+ getName());System.out.println("你的地址是:"+ getAddress());System.out.println("你的数字是:"+ getNumber());}
}
调用方法:
AbstractTest.javapublic classAbstractTest {
public static voidmain(String[] args) {
//通过子类实例化抽象类Employee employee = newInheritanceEmployee("小明","北京",10010110);employee.oneAddress();//调用抽象类中的测试方法employee.testMethod();}
}
运行结果:
构造一个雇员
你的名字是:小明
你的地址是:北京
你的数字是:10010110
这是抽象类中的一个测试方法
Process finished with exit code 0
抽象方法
如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
Abstract关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
AbstractA.javapublic abstract classAbstractA {
private inta;public abstract voidtestA();public intgetA() {
returna;}
public voidsetA(inta) {
this.a= a;}
}
classSubclassB extendsAbstractA {
@Overridepublic voidtestA() {
System.out.println("这是抽象父类中的方法");}
}
在抽象类中的方法只能定义,不能包含方法体。下面是调用方法:
ClassTest.javapublic classClassTest {
public static voidmain(String []args){
AbstractA abstractA = newSubclassB();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.javaabstract classRole {
privateString name;private intage;privateString sex;publicString getName() {
returnname;}
public voidsetName(String name) {
this.name= name;}
public intgetAge() {
returnage;}
public voidsetAge(intage) {
this.age= age;}
publicString getSex() {
returnsex;}
public voidsetSex(String sex) {
this.sex= sex;}
public abstract voidplay();//抽象方法publicRole() {
System.out.println("这是抽象类Role中蛋疼的方法");}
publicRole(String name, intage,String sex) {
this.name= name;this.age= age;this.sex= sex;}
}
classEmployeeOne extendsRole {
private doublesalary;private staticString ID;public doublegetSalary() {
returnsalary;}
public voidsetSalary(doublesalary) {
this.salary= salary;}
public staticString getID() {
returnID;}
public static voidsetID(String iD) {
ID= iD;}
publicEmployeeOne() {
System.out.println("这是EmployeeOne中蛋疼的方法");}
publicEmployeeOne(String name, intage,String sex, doublesalary,String ID) {
super(name,age,sex);this.salary= salary;this.ID= ID;}
@Overridepublic voidplay() {
//重写抽象类中的play()方法System.out.println("员工编号:"+ this.getID());}
final voidemployeeInfo() {
System.out.println("员工姓名:"+ this.getName() + "员工性别:"+ this.getSex() + "员工年龄:"+ this.getAge() + "员工工资:"+ this.getSalary());}
}
classManager extendsEmployeeOne {
finalString vehicle;publicManager(String name, intage,String sex, doublesalary,String ID,String vehicle) {
super(name,age,sex,salary,ID);this.vehicle= "保时捷";}
}
public classPracticeOne {
public static voidmain(String[] args) {
//构造EmployeeOneEmployeeOne employeeOne = newEmployeeOne("张三",18,"男",5000,"123456");employeeOne.play();employeeOne.employeeInfo();//构造ManagerManager manager = newManager("李四",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.javainterfaceConstantValue {
doublePI= 3.1415926;//设置定值PI}
abstract classShape {
doublelength;doublearea;abstract doublegetLength();//构造虚方法abstract doublegetArea();//构造虚方法}
classCircle extendsShape {
doubleradius;Circle(doubleradius) {
this.radius= radius;}
@OverridedoublegetLength() {
length= 2* ConstantValue.PI* radius;returnlength;}
@OverridedoublegetArea() {
area= ConstantValue.PI* radius* radius;returnarea;}
}
classRectangle extendsShape{
doublewidth,height;Rectangle(doublewidth,doubleheight){
this.width= width;this.height= height;}
@OverridedoublegetLength() {
length= (width+ height) * 2;returnlength;}
@OverridedoublegetArea() {
area= width* height;returnarea;}
}
classCone {
Shape bottom;doubleheight;publicCone(Shape bottom, doubleheight) {
super();this.bottom= bottom;this.height= height;}
doublegetVolume() {
returnbottom.getArea() * height/ 3;}
}
public classTestShape {
public static voidcompute(Shape shape){
System.out.println(shape.getClass());System.out.println("周长为:"+ shape.getLength());System.out.println("面积为:"+ shape.getArea());}
public static voidmain(String []args){
Circle circle = newCircle(5);Rectangle rectangle = newRectangle(3,5);System.out.println("创建一个底面为圆形的椎体");Cone cone = newCone(circle,10);compute(circle);System.out.println("体积为:"+ cone.getVolume());System.out.println("------------这是华丽的分割线-------------");System.out.println("创建一个底面为矩形的椎体");cone = newCone(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