Java中的抽象类

Java中的“抽象类”是什么?

206752 次浏览

它是一个不能被实例化的类,并且强制实现类尽可能地实现它概述的抽象方法。

Java类在以下条件下变成抽象类:

1. 至少有一个方法被标记为abstract:

public abstract void myMethod()

在这种情况下,编译器会强制您将整个类标记为抽象类。

2. 该类被标记为abstract:

abstract class MyClass

如前所述:如果你有一个抽象方法,编译器会强迫你将整个类标记为抽象。但是即使你没有任何抽象方法,你仍然可以把类标记为抽象的。

常见的使用:

抽象类的一个常见用途是提供类的大纲,类似于接口。但与接口不同的是,它已经可以提供功能,即类的某些部分已经实现,而另一些部分只是用方法声明来概述。(“摘要”)

抽象类不能被实例化,但是可以基于抽象类创建具体类,然后可以实例化抽象类。要做到这一点,你必须继承抽象类并重写抽象方法,即实现它们。

简单地说,您可以将抽象类看作是具有更多功能的接口。

你不能实例化一个接口,这也适用于一个抽象类。

在你的接口上,你可以只定义方法头,所有的实现者都是强迫来实现它们的所有。在抽象类上,你也可以定义方法头,但在这里——不同于接口——你也可以定义方法的主体(通常是默认实现)。此外,当其他类扩展(注意,不是实现,因此每个子类也可以只有一个抽象类)你的抽象类时,它们不会强制实现你抽象类的所有方法,除非你指定了抽象方法(在这种情况下,它就像接口一样工作,你不能定义方法体)。

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();
}

解决方案——基类(抽象)

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();


}

除了这些帖子之外。

有时候你可能想声明一个 类,但不知道如何定义 所有的方法都属于这个 类。例如,你可能想要 声明一个名为作家的类和 在它中包含一个名为 write ()。然而,你不知道如何编码write (),因为它是 每种类型的作者都不一样 设备。当然,你打算处理 通过派生Writer的子类, 如打印机,磁盘,网络和 控制台。< / p >

抽象类不能直接实例化,但必须从抽象类派生才能使用。类必须是抽象的,如果它包含抽象方法

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
}
}

抽象类是不能被实例化的类。抽象类是通过创建继承的子类来使用的,该子类将被实例化可以。抽象类为继承的子类做了一些事情:

  1. 定义可由继承子类使用的方法。
  2. 定义继承子类必须实现的抽象方法。
  3. 提供一个公共接口,允许子类与所有其他子类交换。

这里有一个例子:

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!"); }
}

你不能这样做,因为在AbstractClassfinalMethod()的实现被标记为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!"); }
}

不能在接口中实现方法。这意味着如果实现两个不同的接口,这些接口中的不同方法不能冲突。由于接口中的所有方法都是抽象的,因此必须实现该方法,并且由于您的方法是继承树中唯一的实现,因此编译器知道它必须使用您的方法。

类,它可以有具体方法和非具体方法,即有主体和没有主体。

  1. 没有实现的方法必须包含'abstract'关键字。
  2. 抽象类不能被实例化。

抽象类是声明为抽象的类——它可以包含也可以不包含抽象方法。抽象类不能被实例化,但可以被子类化。

换句话说,用abstract关键字声明的类在java中称为抽象类。它可以有抽象方法(没有主体的方法)和非抽象方法(有主体的方法)。

< >强重要提示:- 抽象类不能用于实例化对象,它们可以用于创建对象引用,因为Java的运行时多态性方法是通过使用超类引用实现的。因此,必须能够创建对抽象类的引用,以便可以使用它指向子类对象。您将在下面的示例

中看到该特性
abstract class Bike{
abstract void run();
}


class Honda4 extends Bike{
void run(){
System.out.println("running safely..");
}


public static void main(String args[]){
Bike obj = new Honda4();
obj.run();
}
}

从oracle 文档

抽象方法和类:

抽象类是声明为抽象的类——它可以包含也可以不包含抽象方法

抽象类不能被实例化,但可以被子类化

抽象方法是一种声明时没有实现(没有大括号,后面跟着分号)的方法,像这样:

abstract void moveTo(double deltaX, double deltaY);

如果一个类包含抽象方法,那么类本身必须声明为抽象的,如下所示:

public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}

当抽象类被子类化时,子类通常为其父类中的所有抽象方法提供实现。然而,如果不是这样,那么子类也必须声明为抽象的

因为abstract classesinterfaces是相关的,看看下面的SE问题:

接口和抽象类的区别是什么?< / >

我应该如何解释接口和抽象类之间的区别?< / >

抽象类是指没有完全实现但为子类提供了某种蓝图的类。它可以部分实现,因为它包含完全定义的具体方法,但它也可以包含抽象方法。这些是带有签名但没有方法主体的方法。任何子类都必须为每个抽象方法定义一个主体,否则也必须声明为抽象。 因为抽象类不能被实例化,所以它们必须被至少一个子类扩展才能被利用。把抽象类看作泛型类,子类是用来填补缺失信息的
使用摘要关键字声明的类称为abstract class。 抽象是一个隐藏数据实现细节,只向用户显示功能的过程。抽象让你关注对象做了什么,而不是它是如何做的

抽象类的主要内容

  • 抽象类可以包含抽象方法,也可以不包含。可以有非抽象方法。

    抽象方法是声明时不带参数的方法 实现(不带大括号,后面跟着一个分号),比如:

    例:abstract void moveTo(double deltaX, double deltaY);

  • 如果一个类至少有一个抽象方法,那么这个类必须是抽象的

  • 抽象类不能被实例化(不允许创建抽象类的对象)

  • 要使用抽象类,必须从另一个类继承它。为其中的所有抽象方法提供实现。

  • 如果继承了抽象类,则必须为其中的所有抽象方法提供实现。

声明抽象类 在声明类之前指定abstract关键字使其抽象。看看下面的代码:

abstract class AbstractDemo{ }

声明抽象方法 在声明过程中,在方法之前指定abstract关键字使其抽象。看看下面的代码,

abstract void moveTo();//no body

为什么我们需要抽象类

在面向对象的绘图应用程序中,您可以绘制圆、矩形、直线、贝塞尔曲线和许多其他图形对象。这些对象都有某些共同的状态(例如:位置、方向、线条颜色、填充颜色)和行为(例如:移动、旋转、调整大小、绘制)。其中一些状态和行为对于所有图形对象都是相同的(例如:填充颜色、位置和移动)。其他则需要不同的实现(例如:调整大小或绘制)。所有图形对象都必须能够绘制或调整自己的大小,它们只是在如何做到这一点上有所不同。

对于抽象超类来说,这是一个完美的情况。你可以利用相似之处,将所有图形对象声明为继承自相同的抽象父对象(例如:GraphicObject),如下图所示。 enter image description here < / p >

首先,你声明一个抽象类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的每个非抽象子类,例如CircleRectangle,必须为drawresize方法提供实现

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中有两种实现抽象的方法

  • 抽象类(0到100%)
  • 接口(100%)

具有构造函数、数据成员、方法等的抽象类

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

引用:

它什么都不做,只是提供一个公共模板,它将被它的子类共享

什么是抽象类? 好的!让我们举个例子,你对化学有点了解,我们有一个元素碳(符号C)。碳有一些基本的原子结构,你不能改变,但用碳你可以制造很多化合物,如(CO2),甲烷(CH4),丁烷(C4H10)

所以这里碳是抽象类,你不想改变它的基本结构,但你想让他们的孩子(CO2,CH4等)使用它。但是以他们自己的方式