什么是Java中的“抽象类”?
什么是Java中的“抽象类”?
Answers:
抽象类是无法实例化的类。通过创建可以实例化的继承子类来使用抽象类。抽象类为继承的子类做一些事情:
这是一个例子:
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收到类似的信息时,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!"); }
}
您不能这样做,因为finalMethod()
in 的实现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()
。
在以下情况下,Java类变为抽象:
1.至少一种方法被标记为抽象:
public abstract void myMethod()
在这种情况下,编译器会迫使您将整个类标记为抽象。
2.该类被标记为抽象:
abstract class MyClass
如前所述:如果您有抽象方法,则编译器会强制您将整个类标记为抽象。但是,即使您没有任何抽象方法,也仍然可以将类标记为抽象。
常用:
抽象类的常见用法是提供类似于接口的类的概述。但是与接口不同,它已经可以提供功能,即实现了该类的某些部分,而某些部分仅使用方法声明进行了概述。(“抽象”)
抽象类不能被实例化,但是您可以基于抽象类创建一个具体的类,然后可以对其进行实例化。为此,您必须继承抽象类并覆盖抽象方法,即实现它们。
abstract
关键字是使类抽象的必要条件。但是具体的类不能包含abstract
方法。因此,如果您的类具有abstract
方法,则必须将其声明为abstract
编译器的类。
使用abstract关键字声明的类称为abstract class
。抽象是隐藏数据实现细节并仅向用户显示功能的过程。抽象使您可以专注于对象的功能,而不是对象的功能。
抽象类的主要内容
抽象类可以包含抽象方法,也可以不包含抽象方法。
抽象方法是这样的一种方法,该方法无需实现即可声明(不带花括号,后跟分号),如下所示:
例如: abstract void moveTo(double deltaX, double deltaY);
如果一个类至少具有一个抽象方法,则该类必须是抽象的
不能实例化Abstract类(不允许创建Abstract类的对象)
要使用抽象类,您必须从另一个类继承它。提供其中所有抽象方法的实现。
如果继承一个抽象类,则必须为其中的所有抽象方法提供实现。
声明抽象类abstract
在声明期间,在类之前
指定关键字使它抽象。看下面的代码:
abstract class AbstractDemo{ }
声明抽象方法abstract
在声明过程中在方法之前
指定关键字使其抽象。看下面的代码,
abstract void moveTo();//no body
为什么我们需要抽象类
在面向对象的绘图应用程序中,您可以绘制圆形,矩形,直线,贝塞尔曲线和许多其他图形对象。这些对象都有共同的某些状态(例如--:位置,方向,线条颜色,填充颜色)和行为(例如--moveTo,旋转,调整大小,绘制)。所有图形对象的某些状态和行为都是相同的(例如:填充颜色,位置和moveTo)。其他要求不同的实现(例如:调整大小或绘制)。所有图形对象必须能够绘制或调整其大小,只是它们的操作方式不同。
对于抽象超类来说,这是一个完美的情况。您可以利用这些相似之处,并声明所有图形对象都将从同一个抽象父对象(例如ex:)继承,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
。
参考文献:
简而言之,您可以将抽象类视为具有更多功能的接口。
您不能实例化一个接口,该接口也适用于抽象类。
在您的界面上,您只需定义方法标头,所有实现者都将被强制实现所有 方法。在抽象类上,您还可以定义方法标头,但是在这里-与接口的不同-您还可以定义方法的主体(通常是默认实现)。此外,当其他类扩展(注意,没有实现,因此,你也可以只是一个抽象类,每个子类)的抽象类,他们并不是一定要去实现你的所有的抽象类的方法,除非你指定的抽象方法(在这种情况下,它的作用类似于接口,您无法定义方法主体)。
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();
}
从oracle 文档
抽象方法和类:
抽象类是被声明为抽象的类,它可能包含也可能不包含抽象方法
抽象类不能被实例化,但是可以被子类化
抽象方法是这样一种方法,该方法无需实现即可声明(不带花括号,后跟分号),如下所示:
abstract void moveTo(double deltaX, double deltaY);
如果类包含抽象方法,则必须将类本身声明为抽象,如:
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
当抽象类被子类化时,子类通常为其父类中的所有抽象方法提供实现。但是,如果没有,则子类也必须声明为abstract。
由于abstract classes
和interfaces
相关,请查看以下SE问题:
在这里获取答案:
顺便说一句-这些是您最近提出的问题。考虑建立声誉的新问题...
编辑:
刚刚意识到,此问题和所引用问题的发布者具有相同或至少相似的名称,但用户ID始终不同。因此,或者有一个技术问题,就是keyur在再次登录并找到他的问题的答案时遇到了问题,或者这是一种娱乐SO社区的游戏;)
抽象类不能直接实例化,但必须派生自类才能使用。如果一个类包含抽象方法,则它必须是抽象的:直接
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
}
}
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关键字声明的类在Java中被称为abstract class。它可以有抽象方法(无主体的方法)和非抽象方法(有主体的方法)。
重要说明:- 抽象类不能用于实例化对象,它们可以用于创建对象引用,因为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();
}
}