用最简单的话来讲,一个抽象类就是使用keyword声明为abstract的abstract
。它可能包含也可能不包含任何抽象方法。JVM将抽象类标识为不完整类,该类还没有定义其完整行为。声明一个类abstract
仅强制执行一件事:您不能建立此类的实例,仅此而已。
那么,为何还要费心建立一个根本没法实例化的类呢?答案在于解决某些关键设计问题的方法。咱们将在本文后面介绍这一部分。
html
abstract class TestAbstractClass { public abstract void abstractMethod(); public void normalMethod() { //method body } }
在这里,咱们TestAbstractClass
有两种方法,一种是抽象方法,第二种是普通方法。抽象方法。在类中使用抽象方法将迫使您将类声明为抽象自己。
java
一个抽象方法,是未取代实施的方法。抽象方法给类增长了不完整性,所以编译器但愿将整个类声明为抽象。
在应用程序中使用抽象类的惟一方法是扩展此类。若是不abstract
再次声明其子类,则能够实例化。子类继承了超类的行为,而且超类能够保留对子类的引用的功能在不少方面增长了抽象类的重要性。
python
接口是大多数Java API的另外一个基本构建块。您将其命名为collection,I / O或SWT,您能够在任何地方看到它们的运行状况。程序员
接口定义合同,实现类须要遵照这些合同。api
这些合同本质上是未实现的方法。Java已经有一个未实现方法的关键字,即_abstract_。Java规定任何类均可以实现任何接口,所以在接口中声明的全部方法仅需是公共的。
oracle
public interface TestInterface { void implementMe(); }
对于上述接口,任何实现类都须要重写implementMe()
方法。
框架
当实现一个接口而且不重写该方法即声明实现类自己时,只有一种状况abstract
。
抽象类ide
public abstract class TestMain implements TestInterface { //No need to override implement Me }
不然,您必须implementMe()
在您的类中实现该方法,而没有任何其余例外。
非抽象类学习
public class TestMain implements TestInterface { @Override public void implementMe() { // TODO Auto-generated method stub } }
让咱们记下抽象类和接口之间的差别以便快速查看:ui
extends
,而为了实现接口关键字是implements
。一个类只能扩展一个类,但能够实现任何数量的接口。在Java中,此属性一般称为多重继承的模拟。abstract
,不能实例化;Java抽象类也没法实例化,可是若是存在main()则能够调用它。接下来,若是咱们既有抽象方法又有主类,可能会有一个问题,咱们能够尝试从中调用抽象方法main()
。可是这种尝试将失败,由于main()
方法始终是静态的,而抽象方法永远不会是静态的,所以您永远没法访问静态方法内部的任何非静态方法。
始终记住,在接口或抽象类之间进行选择既不是/也不是方案,在这种状况下,选择未经适当分析的任何人都会产生相同的结果。了解当前问题后,必须很是明智地作出选择。让咱们尝试在这里添加一些智慧。
抽象类使您能够定义一些行为。它使它们成为应用程序框架内的优秀候选人。
让咱们以HttpServlet为例。若是要使用Servlets技术开发Web应用程序,则必须继承该类。众所周知,每一个servlet都有明确的生命周期阶段,即初始化,服务和破坏。若是咱们建立了每一个servlet,咱们必须一次又一次地编写关于初始化和销毁的同一段代码。固然,这将是一个很大的痛苦。
JDK设计人员经过制做HttpServlet
抽象类来解决此问题。它具备为初始化Servlet和销毁Servlet而编写的全部基本代码。您只须要重写某些方法便可在其中编写与应用程序处理相关的代码。有道理吧!
可使用界面添加上述功能吗?不,即便能够,对于大多数无辜的程序员来讲,设计也将是一个地狱。
如今,让咱们看一下接口的用法。接口仅提供合同,实现类的责任是实现提供给它的每一个合同。
若是只想定义class的特征,而且要强制全部实现实体实现这些特征,那么接口是最合适的。
我想以Map
集合框架中的接口为例。它仅提供规则,以及map在实践中应如何表现。例如,它应存储键值对,应使用键等访问该值。这些规则在接口中采用抽象方法的形式。
全部实现类(例如HashMap,HashTable,TreeMap或WeakHashMap)均以不一样方式实现全部方法,所以与其余方法相比具备不一样的功能。
一样,接口可用于定义职责分离。例如,HashMap
实现3个接口:Map
,Serializable和Cloneable。每一个接口定义了各自的职责,所以实现类选择要实现的对象,所以将提供有限的功能。
使用Java 8,您如今能够在接口中定义方法。这些称为默认方法。默认方法使您能够向库的接口添加新功能,并确保与为这些接口的较早版本编写的代码二进制兼容。
顾名思义,Java 8中的默认方法就是默认的。若是不重写它们,则它们是调用方类将调用的方法。
默认方法
public interface Moveable { default void move(){ System.out.println("I am moving"); } }
在上面的示例中,Moveable
接口定义了一种方法,move()
而且还提供了默认实现。若是有任何类实现此接口,则无需实现它本身的move()
方法版本。它能够直接调用instance.move()
。
public class Animal implements Moveable{ public static void main(String[] args){ Animal tiger = new Animal(); tiger.move(); //I am moving } }
而且,若是类愿意定制行为,那么它能够提供本身的定制实现并重写该方法。如今将调用它本身的自定义方法。
public class Animal implements Moveable{ public void move(){ System.out.println("I am running"); } public static void main(String[] args){ Animal tiger = new Animal(); tiger.move(); //I am running }
若是您看到了,咱们如今也能够提供带有接口的部分实现,就像抽象类同样。所以,从本质上说,接口与抽象类之间的界限变得很是狭窄。它们如今提供几乎相同的功能。
如今,只有一个很大的不一样,即您不能扩展多个类,而能够实现多个接口。除了这种差别以外,您还能够经过接口实现任何可能的功能,这些接口可使抽象类成为可能,反之亦然。
但愿您在Java中找到有关接口和抽象类的足够信息。
学习愉快!
更多精彩请关注公众号【lovepythoncn】