抽象方法和类
抽象类是声明为abstract
的类,它可以包含也可以不包含抽象方法。抽象类不能被实例化,但是可以被子类化。
抽象方法是一种无需实现即可声明的方法(不带花括号,后跟分号),如下所示:
abstract void moveTo(double deltaX, double deltaY);
如果类包含抽象方法,则必须将类本身声明为abstract
,如下所示:
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
当抽象类被子类化时,该子类通常为其父类中的所有抽象方法提供实现。但是,如果没有,则子类也必须声明为abstract
。
Note:
interface中未声明为默认或静态的方法(请参见Interfaces部分)是隐式抽象的,因此abstract
修饰符不适用于interface方法。 (可以使用,但不必要.)
抽象类与interface的比较
抽象类类似于interface。您无法实例化它们,它们可能包含使用或不使用实现声明的方法的混合。但是,使用抽象类,您可以声明非静态和final字段,并定义公共,受保护的和私有的具体方法。使用interface时,所有字段都自动是公共的,静态的和final的,并且您声明或定义的所有方法(作为默认方法)都是公共的。另外,无论是否抽象,您都只能扩展一个类,而您可以实现任何数量的interface。
您应该使用哪个抽象类或interface?
-
如果以下任何一种情况适用于您的情况,请考虑使用抽象类:
-
您想在几个紧密相关的类之间共享代码。
-
您期望扩展您的抽象类的类具有许多公共方法或字段,或者需要除 public(例如 protected 和 private)之外的访问修饰符。
-
您要声明非静态或非final字段。这使您能够定义可以访问和修改它们所属对象的状态的方法。
-
-
如果以下任何一种情况适用于您的情况,请考虑使用interface:
-
您期望不相关的类将实现您的interface。例如,interfaceComparable和Cloneable由许多不相关的类实现。
-
您想指定特定数据类型的行为,但不关心谁实现了它的行为。
-
您想利用类型的多重继承。
-
JDK 中的抽象类的一个示例是AbstractMap,它是 Collections Framework 的一部分。它的子类(包括HashMap
,TreeMap
和ConcurrentHashMap
)共享AbstractMap
定义的许多方法(包括get
,put
,isEmpty
,containsKey
和containsValue
)。
JDK 中实现多个interface的类的示例是HashMap,该类实现了Serializable
,Cloneable
和Map<K, V>
interface。通过阅读此interface列表,您可以推断HashMap
的实例(无论实现该类的开发人员或公司如何)都可以克隆,并且可以序列化(这意味着可以将其转换为字节流;请参见Serializable Objects部分)。 ),并具有 Map 功能。此外,Map<K, V>
interface已通过许多默认方法进行了增强,例如merge
和forEach
,实现此interface的旧类无需定义。
注意,许多软件库同时使用抽象类和interface。 HashMap
类实现了多个interface,并且还扩展了抽象类AbstractMap
。
抽象类示例
在面向对象的绘图应用程序中,您可以绘制圆形,矩形,直线,贝塞尔曲线和许多其他图形对象。这些对象都有共同的某些状态(例如:位置,方向,线条颜色,填充颜色)和行为(例如:moveTo,旋转,调整大小,绘制)。所有图形对象的某些状态和行为都是相同的(例如:position,fill color 和 moveTo)。其他的则需要不同的实现(例如,调整大小或绘制)。所有GraphicObject
都必须能够自行绘制或调整大小;他们只是在做事方式上有所不同。对于抽象超类来说,这是一个完美的情况。您可以利用这些相似之处,并声明所有图形对象都将从同一抽象父对象(例如GraphicObject
)继承,如下图所示。
从 RectectObject 继承的 Rectangle,Line,Bezier 和 Circle 类
首先,您声明一个抽象类GraphicObject
,以提供所有子类(例如当前位置和moveTo
方法)完全共享的成员变量和方法。 GraphicObject
还声明了诸如draw
或resize
之类的方法的抽象方法,这些方法必须由所有子类实现,但必须以不同的方式实现。 GraphicObject
类可以如下所示:
abstract class GraphicObject {
int x, y;
...
void moveTo(int newX, int newY) {
...
}
abstract void draw();
abstract void resize();
}
GraphicObject
的每个非抽象子类(例如Circle
和Rectangle
)都必须提供draw
和resize
方法的实现:
class Circle extends GraphicObject {
void draw() {
...
}
void resize() {
...
}
}
class Rectangle extends GraphicObject {
void draw() {
...
}
void resize() {
...
}
}
抽象类实现interface时
在Interfaces的小节中,注意到实现interface的类必须实现interface的所有方法。但是,可以定义一个不实现所有interface方法的类,前提是该类被声明为abstract
。例如,
abstract class X implements Y {
// implements all but one method of Y
}
class XX extends X {
// implements the remaining method in Y
}
在这种情况下,类X
必须为abstract
,因为它没有完全实现Y
,但实际上XX
类可以实现Y
。
Class Members
抽象类可能具有static
个字段和static
个方法。您可以将这些静态成员与类引用(例如AbstractClass.staticMethod()
)一起使用,就像对其他任何类一样。