在本篇博客中将介绍JAVA里抽象类和接口的基础知识以及两者的异同点,在有继承和多态的基础知识上学习会更好~
目录
抽象类基础知识
在学习完继承和多态的知识后,我们对“类”的运用又有了更深的了解,那么在Java中还存在一个重要且特殊的类--抽象类,为什么说特殊,因为Java中的抽象类是不可以用于创建对象的,但是它可以包含抽象方法,这些方法将在具体的子类中实现,注意具体和子类两个关键字。下面是抽象类的具体定义:
在继承的层次结构中,每个新的子类都使类变得更加明确和具体。如果从一个子类向父类追溯,类就会变得更通用,也就更加不明确。类的设计应该确保父类包含它的子类的共同特征。有时候,一个父类设计得非常抽象,以至于它都没有任何具体的实例,这样的类称为抽象类(abstract class) 这里要记住它的特殊性!没有任何实例!
抽象类的定义、创建等基础
我们来举个栗子,创建下面这样一个GeometricObject (几何)类,这个在上一篇博客中也有,用来引入讲继承(大概意思是定义一个几何类,那么像Circle类和Rectangle类都可以从它衍生出来成为子类(并不是子集!))
public class GeometricObject //创建这样一个试用于所有几何的大类,简称父类
{
private String color = "white"; //一般设置为私有变量
private boolean filled; //布尔类型,是否填充
private java.util.Date dateCreated;
public GeometricObject() //创建一个初始的或者是错误的几何对象,初始构造函数
{
dateCreated = new java.util.Date();//记录创建时间
}
public GeometricObject(String color,boolean filled) //创建一个初始的对象包含颜色和是否填充
{
dateCreated = new java.util.Date(); //更新创建时间
this.color = color;
this.filled = filled;
}
public String getColor() //用户想得知颜色可以返回
{
return color;
}
public void setColor(String color) //用户在外部更改颜色
{
this.color = color;
}
public boolean isFilled()
{
return filled;
}
public void setFilled(Boolean filled)
{
this.filled = filled;
}
public java.util.Date getDateCreated()
{
return dateCreated;
}
//返回这个对象的基础信息,其实由前面学过的重载可知,我们这里是重载了toString这个函数,它的原始父类应该是在Object中
@Override
public String toString()
{
return "created on " + dateCreated + "\ncolor: " + color + " and filled: " + filled;
}
}
可以看到,GeometricObject类对几何对象的共同特征进行了建模,那么假设我们写了一个Circle类和Rectangle类(它的子类),然后它们都包含了分别用于计算圆和矩形的面积和周长的getArea()方法和getPerimeter()方法。
因为可以计算所有几何对象的面积和周长,所以最好在GeometricObject类中定义getArea()和getPerimeter()方法。但是!这些方法不能在GeometricObject类中实现,因为它们的实现取决于几何对象的具体类型!这样的方法就称之为抽象方法(abstract method),在方法头中使用abstract修饰符表示,一旦在GeometricObject类中定义了这些方法后,GeometricObject就成为了一个抽象类,在类的头部使用abstract修饰符表示该类为抽象类。我们现在给出新的GeometricObject类的定义:(很重要!认真看!)
public abstract class GeometricObject //抽象类前也要用abstract关键词定义
{
private String color = "white";
private boolean filled;
private java.util.Date dateCreated;
//创建一个初始的未设置的几何对象/构造方法
protected GeometricObject() //抽象类的构造方法定义为protected,因为它只被子类使用
{
dateCreated = new java.util.Date();
}
//创建一个初始的带设置的几何对象/这个也是构造方法,看方法头!
protected GeometricObject(String color, boolean filled)
{
dateCreated = new java.util.Date();
this.color = color;
this.filled = filled;
}
//接下来颜色和是否填充的获取器和修改器方法和之前的都一样
//下面这些就是抽象方法!也是使得这个类成为抽象类的原因!
public abstract double getArea();
public abstract double getPerimeter();
//注意!这里都不需要写怎么计算或者返回什么,因为并不确定具体的几何对象,也就是具体的子类!
}
抽象类的几点说明(一)
其实上面的注释中也提到了关于抽象类的重要知识点,我们在这里再总结一下:
1.抽象类和常规类很像,但是不能使用new操作符创建它的实例!抽象方法只有定义而没有实现!它的实现由子类提供!一个包含抽象方法的类必须声明为抽象类
2.抽象类的构造方法定义为protected,因为它只被子类使用!创建一个具体子类的实例时,其父类的构造方法被调用以初始化父类中定义的数据域!
那么Circle类在上一篇博客的继承中也有,这时候继承这个新定义的GeometricObject类就可以调试试试,写法上是没有任何差别的,调用定义抽象方法即可,同学们可以回上一篇看看
为何使用抽象方法
其实既然提到子类既然和之前的创建书写都没有什么不一样,那么为什么要在GeometricObject类中定义方法getArea()和getPerimeter()为抽象的,而不是在每个子类中定义他们,这样有什么好处?
我们来看一下下面这个代码,程序创建了两个几何对象:一个圆和一个矩形,调用equalArea方法来检查它们