当前位置: 首页 > Web前端 > HTML

JAVA中的“抽象接口”

时间:2023-04-02 11:25:06 HTML

在编程的过程中,读者很可能会遇到这样的困境:设计了一个接口,但是实现这个接口的子类不需要实现接口中的所有方法,即,换句话说,接口中的方法太多了,对于一些子类来说是多余的,我们不得不浪费时间写一个空的实现。今天小菜说的“抽象接口”就是用来解决这个问题的。为了不误导读者,我先解释一下什么是“抽象接口”。所谓“抽象接口”,就是在提供接口的同时提供一个抽象类,使用抽象类来实现接口(其实这是默认的适配方式)。以下小菜举例,让读者体验一下这样做的好处。代码写得不好。为了不让读者看糊涂,贴个类图:具体代码:  ITestInterface.java复制代码1/*2假设有一个顶层接口3*/4publicinterfaceITestInterface{5voidmethod1();6intmethod2();7booleanmethod3();8}复制代码  TestAbstract.java复制代码1/*2抽象类抽象实现ITestInterface顶层接口3*/45公共抽象类TestAbstract实现ITestInterface{6//找出接口中必要的方法,即子类必须实现的方法,定义为抽象方法,交给子类实现7publicabstractvoidmethod1();8公共抽象int方法2();910//抽象类中可以默认实现一些独特的方法11publicbooleanmethod3(){12returntrue;13}14}复制代码    TestClass1.javaCopycode1/*2普通类TestClass1继承TestAbstract抽象类3*/45publicclassTestClass1extendsTestAbstract{67//TestClass1必须实现抽象方法method1,该方法首先定义在接口8publicvoidmethod1(){910}11//TestClass1必须实现抽象方法method2method,首先定义在接口中12publicintmethod2(){13return1;14}1516//接口中的method3方法与TestClass1无关,故不重写。17}复制代码  TestClass2.javaCopycode1/*2CommonclassTestClass2inheritsTestAbstractabstractclass3*/45publicclassTestClass2extendsTestAbstract{67//TestClass2必须实现抽象方法1方法,这是最早的它定义在接口8publicvoidmethod1(){910}11//TestClass2必须实现抽象method2方法,该方法首先定义在接口12publicintmethod2(){13return2;14}1516//method3方法对TestClass2至关重要,必须重写。17publicbooleanmethod3(){18returnfalse;19}2021}复制代码代码精髓:    从上面的例子我们可以看出最高层的接口是由抽象类实现的。在抽象类中,我们把关键的method1和method2方法定义为抽象方法,强制子类去实现它们,而“唯一”的method3方法在抽象类中有默认实现。    当TestClass1和TestClass2继承TestAbstract抽象类时,优势就会体现出来。TestClass1和TestClass2必须实现method1和method2,如果没有使用method3,可以直接忽略。    通过接口和抽象类的结合,避免了实现接口的子类中大量“无意义”的实现。这种“无意义”的实现被缓冲成抽象类,完美的体现了代码复用(抽象类可以理解为接口和实现类之间的缓冲)。    需要指出的是,我们可以选择继承抽象类或者实现接口。这并不意味着我们必须继承抽象类。这取决于实际情况。这里有两个选择和两个机会。至此,读者可能会认为文章结束了,其实不然。..这样做的好处还不止于此,细细品味,如果我们在接口上加一个方法。..具体代码:  温馨提示:不要被代码吓倒。其实这些代码和上面的差不多,只是多了一个方法而已。  ITestInterface.java复制代码1/*2假设有一个顶层接口3*/4publicinterfaceITestInterface{5voidmethod1();6int方法2();7布尔方法3();8//接口中新增Method9Stringmethod4();10}复制代码  TestAbstract.javaCopycode1/*2abstractclassabstractimplementsITestInterfacetop-levelinterface3*/45publicabstractclassTestAbstractimplementsITestInterface{6//找到接口必要的方法,也就是子类必须实现的方法,定义为抽象方法,由子类实现7publicabstractvoidmethod1();8公共抽象int方法2();910//一些特有的方法可以在抽象类中使用默认实现11publicbooleanmethod3(){12returntrue;13}1415//抽象类中提供了一个默认实现,避免"alarming"allsubclasses16publicStringmethod4(){17return"";18}19}复制代码  TestClass1.javaCopycode1/*2CommonclassTestClass1inheritsTestAbstractabstractclass3*/45publicclassTestClass1extendsTestAbstract{67//TestClass1必须实现抽象method1方法,该方法首先定义在接口8publicvoidmethod1(){910}11//TestClass1必须实现抽象方法2,该方法首先定义在接口12浦blicintmethod2(){13return1;14}1516//接口中的method3方法与TestClass1无关,不要重写1718//新方法对TestClass1很重要,必须重写19publicStringmethod4(){20return"Class1";21}2223}复制代码  TestClass2.java复制代码1/*2CommonclassTestClass2继承TestAbstract抽象类3*/45publicclassTestClass2extendsTestAbstract{67//TestClass2必须实现接口中首先定义的抽象方法1方法8publicvoidmethod1(){910}11//TestClass2必须实现接口中首先定义的抽象方法2方法12publicintmethod2(){13return2;14}1516//method3方法对于TestClass2很重要,所以必须重写。17publicbooleanmethod3(){18returnfalse;19}2021//新添加的方法与TestClass2无关,不需要知道新添加的method4的存在22}复制代码代码本质:    this代码演示如果项目已经形成,但是需求发生了变化,我们要在接口中添加一个新的方法。如果子类直接实现了该接口,那么这些子类就必须修改以实现该接口的新方法。    但是在这个例子中,TestClass1和TestClass2的子类并没有直接实现接口,而是通过继承抽象类间接实现了接口,所以好处立马体现出来了!    接口中添加的方法可以缓存在实现接口的抽象类中,并提供默认实现。这样一来,就不必强制所有的子类(通过继承抽象类间接实现接口的类)都被修改,可以形象地理解为“不打扰子类”。需要使用该方法的子类直接重写即可。小菜感叹:    人类的智慧真是太伟大了!数组和链表的结合产生了一个高效的哈希表;接口和抽象类的结合产生了一种优雅的默认适配模式。让我们努力吧!!!写成下面的话:    世上没有完美的东西,设计模式也是如此。讨论太多的优点和缺点是没有意义的。适合的才是最好的。适合什么?这就是智慧发挥作用的地方。