Java中的"抽象类"是什么?
Java中的"抽象类"是什么?
抽象类是一种无法实例化的类。通过创建继承抽象类的子类,可以实例化子类。抽象类对继承的子类做了以下几件事情:
以下是一个示例:
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
需要注意的是,“abstractMethod()”没有任何方法体。因此,您不能执行以下操作:
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
没有实现abstractMethod()
的方法!因此当JVM收到new ImplementingClass().abstractMethod()
时,它无法知道应该执行什么操作。
这里是一个正确的ImplementingClass
。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
请注意,您不必定义implementedMethod()
或finalMethod()
。它们已经被AbstractClass
定义了。
这里是另一个正确的ImplementingClass
。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
在这种情况下,您已经重写了implementedMethod()
方法。final
关键字,以下操作是不可能的。public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
public void finalMethod() { System.out.print("ERROR!"); }
}
由于AbstractClass
中的finalMethod()
被标记为最终实现,所以您不能这样做:不允许任何其他实现。
现在您也可以两次实现抽象类:
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
// In a separate file.
public class SecondImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("second abstractMethod()"); }
}
现在你可以在某处编写另一个方法。
public tryItOut()
{
ImplementingClass a = new ImplementingClass();
AbstractClass b = new ImplementingClass();
a.abstractMethod(); // prints "abstractMethod()"
a.implementedMethod(); // prints "Overridden!" <-- same
a.finalMethod(); // prints "finalMethod()"
b.abstractMethod(); // prints "abstractMethod()"
b.implementedMethod(); // prints "Overridden!" <-- same
b.finalMethod(); // prints "finalMethod()"
SecondImplementingClass c = new SecondImplementingClass();
AbstractClass d = new SecondImplementingClass();
c.abstractMethod(); // prints "second abstractMethod()"
c.implementedMethod(); // prints "implementedMethod()"
c.finalMethod(); // prints "finalMethod()"
d.abstractMethod(); // prints "second abstractMethod()"
d.implementedMethod(); // prints "implementedMethod()"
d.finalMethod(); // prints "finalMethod()"
}
请注意,尽管我们将b
声明为AbstractClass
类型,但它显示的是"Overriden!"
。这是因为我们实例化的对象实际上是一个ImplementingClass
,它的implementedMethod()
被覆盖了。(您可能已经看到这被称为多态。)
如果我们希望访问特定子类的成员,必须首先向下转换为该子类:
// Say ImplementingClass also contains uniqueMethod()
// To access it, we use a cast to tell the runtime which type the object is
AbstractClass b = new ImplementingClass();
((ImplementingClass)b).uniqueMethod();
最后,您不能执行以下操作:
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
每次只能扩展一个类。如果你需要扩展多个类,这些类必须是接口。你可以这样做:
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
这是一个示例界面:
interface InterfaceA
{
void interfaceMethod();
}
这基本上与以下内容相同:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
唯一的区别在于第二种方式不会让编译器知道它实际上是一个接口。如果您希望仅允许其他人实现您的接口而不是其他接口,这可能很有用。但是,总的来说,初学者应该遵循以下规则:如果您的抽象类只包含抽象方法,最好将其设计为接口。
以下是非法的:
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
接口中不能实现方法。这意味着如果你实现了两个不同的接口,这些接口中的不同方法就不会冲突。由于接口中的所有方法都是抽象的,所以你必须实现这些方法,而且由于你的方法是继承树中唯一的实现,编译器知道它必须使用你的方法。
c.implementedMethod()
会输出"Overriden!"呢?SecondImplementingClass
并没有重写implementedMethod()
。 - John RedJava类在满足以下条件下会成为抽象类:
1. 至少有一个方法被标记为抽象方法:
public abstract void myMethod()
在这种情况下,编译器会强制你将整个类标记为抽象。
2. 类被标记为抽象:
abstract class MyClass
正如已经说过的:如果你有一个抽象方法,编译器会强制你将整个类标记为抽象类。但是即使你没有任何抽象方法,你仍然可以将该类标记为抽象类。
常见用法:
抽象类的常见用途是提供一个类的概要,类似于接口的作用。但与接口不同的是,它可以提供功能实现,也就是类的某些部分已经被实现,而其他部分则仅用方法声明进行概述。(“抽象”)
抽象类不能被实例化,但您可以基于抽象类创建一个具体类,然后可以对其进行实例化。为此,你需要从抽象类继承并重写抽象方法,也就是实现它们。
abstract
关键字是使类成为抽象类所必需的。但是具体类不能包含abstract
方法。因此,如果您的类具有abstract
方法,则必须将其声明为abstract
类以供编译器使用。 - user2453382抽象类
。抽象是一种隐藏数据实现细节,仅向用户展示功能的过程。抽象使您专注于对象执行的操作,而不是其如何执行。
抽象类的主要特点:
abstract
关键字可将其变成抽象类。请参阅下面的代码示例:abstract class AbstractDemo{ }
声明抽象方法
在声明方法时,在方法前加上abstract
关键字即可将它声明为抽象方法。请看下面的代码,
abstract void moveTo();//no body
为什么我们需要抽象类
在面向对象的绘图应用中,您可以绘制圆形、矩形、直线、贝塞尔曲线和许多其他图形对象。这些对象都有某些共同的状态(例如:位置、方向、线条颜色、填充颜色)和行为(例如:moveTo、rotate、resize、draw)。其中一些状态和行为对于所有图形对象都是相同的(例如:填充颜色、位置和moveTo)。其他状态和行为则需要不同的实现(例如:resize或draw)。所有图形对象都必须能够自我绘制或调整大小,它们只是以不同的方式实现。
这是使用抽象超类的完美情况。您可以利用相似之处,并声明所有图形对象从同一个抽象父对象(例如:GraphicObject
)继承,如下图所示。
首先,您声明一个抽象类GraphicObject
,提供成员变量和方法,这些成员变量和方法被所有子类完全共享,例如当前位置和moveTo方法。GraphicObject
还声明抽象方法,例如draw或resize,需要由所有子类实现,但必须以不同的方式实现。 GraphicObject
类可能如下所示:
abstract class GraphicObject {
void moveTo(int x, int y) {
// Inside this method we have to change the position of the graphic
// object according to x,y
// This is the same in every GraphicObject. Then we can implement here.
}
abstract void draw(); // But every GraphicObject drawing case is
// unique, not common. Then we have to create that
// case inside each class. Then create these
// methods as abstract
abstract void resize();
}
在子类中使用抽象方法
GraphicObject
的每个非抽象子类,如Circle
和Rectangle
,都必须为draw
和resize
方法提供实现。
class Circle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
class Rectangle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
在main
方法中,您可以像这样调用所有方法:
public static void main(String args[]){
GraphicObject c = new Circle();
c.draw();
c.resize();
c.moveTo(4,5);
}
Java中实现抽象化的方式
Java中有两种实现抽象化的方式:
带有构造函数、数据成员、方法等的抽象类
abstract class GraphicObject {
GraphicObject (){
System.out.println("GraphicObject is created");
}
void moveTo(int y, int x) {
System.out.println("Change position according to "+ x+ " and " + y);
}
abstract void draw();
}
class Circle extends GraphicObject {
void draw() {
System.out.println("Draw the Circle");
}
}
class TestAbstract {
public static void main(String args[]){
GraphicObject grObj = new Circle ();
grObj.draw();
grObj.moveTo(4,6);
}
}
输出:
GraphicObject is created
Draw the Circle
Change position according to 6 and 4
记住两个规则:
如果一个类有少量的抽象方法和少量的具体方法,将其声明为abstract
类。
如果一个类只有抽象方法,将其声明为interface
。
参考资料:
这是一个无法实例化的类,它强制要求实现类可能要实现它所概述的抽象方法。
来自oracle的文档
抽象方法和抽象类:
抽象类是声明为abstract的类,它可能包含或不包含抽象方法
抽象类不能被实例化,但可以被子类化
抽象方法是声明为没有实现的方法(没有大括号,并在后面跟着一个分号),像这样:
abstract void moveTo(double deltaX, double deltaY);
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
public abstract class MyAbstractClass{
public abstract void DoSomething();
}
public abstract class MyAbstractClass{
public int CalculateCost(int amount){
//do some default calculations
//this can be overriden by subclasses if needed
}
//this MUST be implemented by subclasses
public abstract void DoSomething();
}
在这里获取您的答案:
顺便说一下 - 这些是您最近提出的问题。考虑一个新问题来建立声誉...
编辑:
刚刚意识到,这篇文章和引用的问题的发布者具有相同或至少相似的名称,但用户ID始终不同。因此,要么存在技术问题,即keyur无法再次登录并找到他的问题的答案,要么这是一种娱乐SO社区的游戏;)
public abstract class Place {
String Name;
String Postcode;
String County;
String Area;
Place () {
}
public static Place make(String Incoming) {
if (Incoming.length() < 61) return (null);
String Name = (Incoming.substring(4,26)).trim();
String County = (Incoming.substring(27,48)).trim();
String Postcode = (Incoming.substring(48,61)).trim();
String Area = (Incoming.substring(61)).trim();
Place created;
if (Name.equalsIgnoreCase(Area)) {
created = new Area(Area,County,Postcode);
} else {
created = new District(Name,County,Postcode,Area);
}
return (created);
}
public String getName() {
return (Name);
}
public String getPostcode() {
return (Postcode);
}
public String getCounty() {
return (County);
}
public abstract String getArea();
}
abstract class Foo {
abstract void someMethod();
}
或间接地
interface IFoo {
void someMethod();
}
abstract class Foo2 implements IFoo {
}
然而,一个类可以是抽象的,而不包含抽象方法。这是一种防止直接实例化的方式,例如:
abstract class Foo3 {
}
class Bar extends Foo3 {
}
Foo3 myVar = new Foo3(); // illegal! class is abstract
Foo3 myVar = new Bar(); // allowed!
abstract class Processor {
protected abstract int[] filterInput(int[] unfiltered);
public int process(int[] values) {
int[] filtered = filterInput(values);
// do something with filtered input
}
}
class EvenValues extends Processor {
protected int[] filterInput(int[] unfiltered) {
// remove odd numbers
}
}
class OddValues extends Processor {
protected int[] filterInput(int[] unfiltered) {
// remove even numbers
}
}
对于所有这些帖子的小补充。
有时候,您可能想要声明一个类,但不知道如何定义属于该类的所有方法。例如,您可能想要声明一个名为Writer的类,并在其中包含一个名为write()的成员方法。但是,您不知道如何编写write(),因为它对于每种类型的Writer设备都是不同的。当然,您计划通过派生Writer的子类(例如Printer、Disk、Network和Console)来处理此问题。