Heim >Java >javaLernprogramm >Was ist die Schnittstelle? Was ist eine abstrakte Klasse?

Was ist die Schnittstelle? Was ist eine abstrakte Klasse?

零下一度
零下一度Original
2017-06-30 11:20:011607Durchsuche

Was ist eine Schnittstelle und was ist eine abstrakte Klasse? Warum brauchen wir bei abstrakten Klassen Schnittstellen?

Abstrakte Klasse

Das Konzept der abstrakten Klasse:

 Abstrakte Klassen sind relativ zu gewöhnlichen Klassen. Gewöhnliche Klassen sind vollständige Funktionsklassen, die direkt instanziierte Objekte generieren können. Gewöhnliche Klassen können Konstruktoren enthalten. gewöhnliche Methoden, statische Methoden, Konstanten und Variablen usw. Abstrakte Klassen beziehen sich auf das Hinzufügen abstrakter Methodenkomponenten zur Struktur gewöhnlicher Klassen oder auf die direkte Deklaration der Klasse als abstrakten Typ.

Ebenso sind abstrakte Methoden relativ zu gewöhnlichen Methoden sei ein „{}“ vor allen gewöhnlichen Methoden, das den Methodenkörper darstellt. Methoden mit Methodenkörpern müssen direkt von Objekten verwendet werden. Abstrakte Methoden beziehen sich auf Methoden ohne Methodenkörper, und abstrakte Methoden müssen auch mit dem Schlüsselwort abstract geändert werden. Eine Klasse mit abstrakten Methoden ist eine abstrakte Klasse, und abstrakte Klassen müssen mit dem Schlüsselwort abstract deklariert werden.

Das Folgende ist eine einfache abstrakte Klasse:

package abstractdemo;  
  
//抽象类  public abstract class AbstractDemo {  //抽象方法,没有方法体  public abstract void test();  
      public void test1(){  
        System.out.println("普通方法");  
    }  
  public static void main(String[] args) {  
        Class18f2cef21ebec83e6009fc1ed61f2bdf c = AbstractDemo.class;  
        System.out.println(c.getName());  
    }  
}

Instanz der abstrakten Klasse:

package abstractdemo;  
  
public abstract class AbstractTest {  
  public static void main(String[] args) {  
        AbstractDemo ad = new AbstractDemo() {  
              
            @Override  public void test() {  
                System.out.println("实例抽象类要重写抽象类中所有的抽象方法!");  
            }  
        };  
        ad.test();  
        System.out.println(ad.getClass());  
    }  
  
}

Wie aus dem Obigen ersichtlich ist, können abstrakte Klassen nicht direkt instanziiert werden. Warum kann es nicht direkt instanziiert werden? Wenn eine Klasse instanziiert wird, bedeutet dies, dass das Objekt Attribute oder Methoden in der Klasse aufrufen kann. In abstrakten Klassen gibt es jedoch abstrakte Methoden. Abstrakte Methoden haben keinen Methodenkörper und können nicht ohne Methodenkörper aufgerufen werden. Da keine Methodenaufrufe möglich sind, erfahren Sie, wie instanziierte Objekte generiert werden. Daher werden Sie beim Instanziieren einer abstrakten Klasse aufgefordert, zuerst die abstrakte Methode in der abstrakten Klasse zu überschreiben. Wenn in einer abstrakten Klasse keine abstrakte Methode vorhanden ist, kann die Klasse nicht instanziiert werden und während der Instanziierung wird ein Kompilierungsfehler gemeldet ;

Die Prinzipien für die Verwendung abstrakter Klassen lauten wie folgt:
(1) Abstrakte Methoden müssen öffentlich oder geschützt sein (denn wenn sie privat sind, sind sie kann nicht von Unterklassen geerbt werden und Unterklassen können sie nicht implementieren) Diese Methode ist standardmäßig öffentlich
(2) Abstrakte Klassen können nicht direkt instanziiert werden und müssen von Unterklassen durch Aufwärtstransformation verarbeitet werden; 🎜>
(3) Abstrakte Klassen müssen Unterklassen haben. Eine Unterklasse kann nur eine abstrakte Klasse erben Alle abstrakten Methoden in der Klasse überschreiben (wenn die Unterklasse die abstrakte Methode der übergeordneten Klasse nicht implementiert, ist die Unterklasse auch eine abstrakte Klasse)
Sehen Sie sich ein Stück an Code unten:

现在就可以清楚的发现: 
(1)抽象类继承子类里面有明确的方法覆写要求,而普通类可以有选择性的来决定是否需要覆写; 
(2)抽象类实际上就比普通类多了一些抽象方法而已,其他组成部分和普通类完全一样; 
(3)普通类对象可以直接实例化,但抽象类的对象必须经过向上转型之后才可以得到。

虽然一个类的子类可以去继承任意的一个普通类,可是从开发的实际要求来讲,普通类尽量不要去继承另外一个普通类,而是去继承抽象类。

抽象类的使用限制:

1.由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。抽象类中是有构造函数的,所以子类继承抽象类,构造方法的调用顺序仍然是先父类构造函数,然后子类构造函数

2.抽象类不可以修饰为final,因为抽象类有子类,而final修饰的类不能被继承;

3.外部抽象类不能被修饰为static,外部抽象类不允许使用static声明,而内部的抽象类运行使用static声明。使用static声明的内部抽象类相当于一个外部抽象类的成员,继承的时候使用“外部类.内部类”的形式表示类名称。

package com.wz.abstractdemo;static abstract class A{//定义一个抽象类public abstract void print();

}class B extends A{public void print(){
        System.out.println("**********");
    }
}public class TestDemo {public static void main(String[] args) {
        A a = new B();//向上转型        a.print();
    }

}

执行结果

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Illegal modifier for the class A; only public, abstract & final are permitted
    at com.wz.abstractdemo.A.<init>(TestDemo.java:3)
    at com.wz.abstractdemo.B.<init>(TestDemo.java:9)
    at com.wz.abstractdemo.TestDemo.main(TestDemo.java:18)

再看一个关于内部抽象类:

package com.wz.abstractdemo;abstract class A{//定义一个抽象类static abstract class B{//static定义的内部类属于外部类public abstract void print();
    }

}class C extends A.B{public void print(){
        System.out.println("**********");
    }
}public class TestDemo {public static void main(String[] args) {
        A.B ab = new C();//向上转型        ab.print();
    }

}

执行结果:

**********

4.任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。但是修饰为abstract的抽象方法,不能修饰为static,没有意义; 

5.有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略掉外部子类。这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。

范例如下:

package com.wz.abstractdemo;abstract class A{//定义一个抽象类public abstract void print();private static class B extends A{//内部抽象类子类public void print(){//覆写抽象类的方法System.out.println("Hello World !");
        }
    }//这个方法不受实例化对象的控制public static A getInstance(){return new B();
    }

}public class TestDemo {public static void main(String[] args) {//此时取得抽象类对象的时候完全不需要知道B类这个子类的存在A a = A.getInstance();
        a.print();
    }
}

运行结果:

Hello World !

抽象类的应用——模板设计模式

例如,现在有三类事物: 
(1)机器人:充电,工作; 
(2)人:吃饭,工作,睡觉; 
(3)猪:进食,睡觉。 
现要求实现一个程序,可以实现三种不同事物的行为。

先定义一个抽象行为类:

package com.wz.abstractdemo;public abstract class Action{public static final int EAT = 1 ;public static final int SLEEP = 3 ;public static final int WORK = 5 ;public abstract void eat();public abstract void sleep();public abstract void work();public void commond(int flags){      switch(flags){case EAT:this.eat();break;case SLEEP:this.sleep();break;case WORK:this.work();break;case EAT + SLEEP:this.eat();this.sleep();break;case SLEEP + WORK:this.sleep();this.work();break;default:break;
        }
    }
}

定义一个机器人的类:

package com.wz.abstractdemo;public class Robot extends Action{

    @Overridepublic void eat() {
        System.out.println("机器人充电");

    }

    @Overridepublic void sleep() {

    }

    @Overridepublic void work() {
        System.out.println("机器人工作");

    }

}

定义一个人的类:

package com.wz.abstractdemo;public class Human extends Action{

    @Overridepublic void eat() {
        System.out.println("人吃饭");

    }

    @Overridepublic void sleep() {
        System.out.println("人睡觉");

    }

    @Overridepublic void work() {
        System.out.println("人工作");

    }

}

定义一个猪的类:

package com.wz.abstractdemo;public class Pig extends Action{

    @Overridepublic void eat() {
        System.out.println("猪进食");

    }

    @Overridepublic void sleep() {
        System.out.println("猪睡觉");

    }

    @Overridepublic void work() {


    }

}

测试主类:

package com.wz.abstractdemo;public class AbstractDemo {public static void main(String[] args) {

        fun(new Robot());

        fun(new Human());

        fun(new Pig());

    }public static void fun(Action act){
        act.commond(Action.EAT);
        act.commond(Action.SLEEP);
        act.commond(Action.WORK);
    }

}

运行结果:

机器人充电
机器人工作
人吃饭
人睡觉
人工作
猪进食
猪睡觉
 

Wenn alle Unterklassen den Vorgang normal abschließen möchten, müssen sie gemäß der angegebenen Methode überschreiben. Zu diesem Zeitpunkt ist die Funktion der abstrakten Klasse die Funktion einer Klassendefinitionsvorlage.

-------------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -----------------------------------------------

Schnittstelle

  Eine Schnittstelle ist eine „Klasse“, die abstrakter ist als eine abstrakte Klasse. Ich setze „Klasse“ hier in Anführungszeichen, weil ich kein besseres Wort finde, um es auszudrücken, aber wir müssen uns darüber im Klaren sein, dass die Schnittstelle selbst keine Klasse ist, was daran zu erkennen ist, dass wir eine Schnittstelle nicht instanziieren können. Zum Beispiel ist new Runnable(); definitiv falsch. Wir können nur die Implementierungsklasse new.

Die Schnittstelle wird zum Erstellen eines Protokolls zwischen Klassen verwendet. Sie stellt lediglich ein Formular ohne spezifische Implementierung bereit. Gleichzeitig muss die Implementierungsklasse, die die Schnittstelle implementiert, alle Methoden der Schnittstelle implementieren. Durch die Verwendung des Schlüsselworts „implementiert“ wird angegeben, dass die Klasse einer bestimmten Schnittstelle oder Gruppe bestimmter Schnittstellen folgt, und es gibt auch an, dass „Schnittstelle“ ist nur sein Aussehen, aber jetzt muss erklärt werden, wie es funktioniert.

Die Schnittstelle ist eine Erweiterung der abstrakten Klasse. Um die Datensicherheit zu gewährleisten, kann Java keine Mehrfachvererbung haben, das heißt, die Vererbung kann nur eine übergeordnete Klasse haben Unterschiedlich und eine Klasse kann gleichzeitig mehrere Schnittstellen implementieren, unabhängig davon, ob eine Beziehung zwischen diesen Schnittstellen besteht. Daher wird der Fehler, dass abstrakte Klassen keine Mehrfachvererbung haben können, empfohlen und Schnittstellen zusammen, da dadurch nicht nur die Datensicherheit gewährleistet, sondern auch eine Mehrfachvererbung erreicht werden kann.

Bei der Verwendung der Schnittstelle müssen Sie auf folgende Punkte achten:

1. Alle Methodenzugriffsrechte einer Schnittstelle werden automatisch deklariert als öffentlich. Um genau zu sein, kann es nur öffentlich sein, Sie können es natürlich explizit als geschützt oder privat deklarieren, aber die Kompilierung führt zu Fehlern!

2. Sie können „Mitgliedsvariablen“ in der Schnittstelle oder unveränderliche Konstanten definieren, da die „Mitgliedsvariablen“ in der Schnittstelle automatisch zu öffentlichen statischen Endgültigen werden. Der Zugriff erfolgt direkt über den Klassennamen: ImplementClass.name.

3. Es gibt keine implementierte Methode in der Schnittstelle.

4. Eine nicht abstrakte Klasse, die eine Schnittstelle implementiert, muss alle Methoden der Schnittstelle implementieren. Abstrakte Klassen müssen nicht implementiert werden.

5. Sie können den neuen Operator nicht zum Instanziieren einer Schnittstelle verwenden, aber Sie können eine Schnittstellenvariable deklarieren, die auf ein Objekt einer Klasse verweisen muss, die die Schnittstelle implementiert. Mit „instanceof“ können Sie prüfen, ob ein Objekt eine bestimmte Schnittstelle implementiert. Zum Beispiel: if(anObject Instanz von Comparable){}.

6. Achten Sie bei der Implementierung mehrerer Schnittstellen darauf, doppelte Methodennamen zu vermeiden.

Der Unterschied zwischen abstrakter Klasse und Schnittstelle

In der Java-Sprache werden abstrakte Klasse und Schnittstelle unterstützt Zwei Mechanismen zur abstrakten Klassendefinition. Gerade aufgrund der Existenz dieser beiden Mechanismen erhält Java leistungsstarke objektorientierte Fähigkeiten. Es gibt große Ähnlichkeiten zwischen abstrakten Klassen und Schnittstellen hinsichtlich der Unterstützung der Definition abstrakter Klassen und sie können sogar untereinander ersetzt werden. Daher scheinen viele Entwickler bei der Definition abstrakter Klassen eher locker mit der Wahl der abstrakten Klasse und Schnittstelle umzugehen. Tatsächlich gibt es immer noch einen großen Unterschied zwischen den beiden. Ihre Wahl spiegelt sogar das Verständnis der Natur des Problembereichs wider und ob das Verständnis der Entwurfsabsicht richtig und vernünftig ist.

Abstrakte Klasse

Schnittstelle

Instantiierung

Kann nicht

Kann nicht

Klasse

Eine Vererbungsbeziehung, eine Klasse kann die Vererbungsbeziehung nur einmal verwenden . Mehrfachvererbung kann durch die Vererbung mehrerer Schnittstellen erreicht werden

Eine Klasse kann mehrere Schnittstellen implementieren

Datenelemente

können ihre eigene

Statisch haben kann nicht geändert werden, das heißt, es muss statisch endgültig sein. 🎜>

Können private, nicht abstrakte Methoden sein, abstrakte Methoden müssen implementiert werden.

Kann nicht privat sein, der Standardwert ist öffentlich, abstrakter Typ

Variablen

kann privat sein und der Standardwert ist freundlich Typ, sein Wert kann in einer Unterklasse neu definiert oder neu zugewiesen werden

kann nicht privat sein, der Standardwert ist der öffentliche statische Endtyp und muss ihm übergeben werden. Der Anfangswert kann in der Implementierungsklasse nicht neu definiert werden und sein Wert kann nicht geändert werden.

Designkonzept

bedeutet „ist- ein“ Beziehung

stellt die „like-a“-Beziehung dar

Um

zu implementieren, ist Vererbung erforderlich. Sie müssen Extends verwenden.

Sie müssen Verwenden Sie Geräte

Abstrakte Klasse und Schnittstelle werden beide zum Erstellen abstrakter Klassen in der Java-Sprache verwendet (die abstrakte Klasse in diesem Artikel ist nicht aus der abstrakten Klasse übersetzt, sie stellt einen abstrakten Körper dar und die abstrakte Klasse ist eine Methode). wird verwendet, um abstrakte Klassen in der Java-Sprache zu definieren. Was ist also eine abstrakte Klasse und welche Vorteile kann uns die Verwendung abstrakter Klassen bringen?

Eine Klasse, die die Existenz einer Methode deklariert, ohne sie zu implementieren, wird als abstrakte Klasse bezeichnet. Sie wird verwendet, um eine Klasse zu erstellen, die bestimmte grundlegende Verhaltensweisen verkörpert, und Deklarieren Sie eine Methode für die Klasse, sie kann jedoch nicht in der Klasse implementiert werden. Instanzen abstrakter Klassen können nicht erstellt werden. Sie können jedoch eine Variable erstellen, deren Typ eine abstrakte Klasse ist, und diese auf eine Instanz einer konkreten Unterklasse verweisen lassen. Es kann keine abstrakten Konstruktoren oder abstrakten statischen Methoden geben. Unterklassen der Abstract-Klasse stellen Implementierungen für alle abstrakten Methoden in ihrer übergeordneten Klasse bereit, andernfalls handelt es sich auch um abstrakte Klassen. Implementieren Sie die Methode stattdessen in einer Unterklasse. Andere Klassen, die sich ihres Verhaltens bewusst sind, können diese Methoden in ihrer Klasse implementieren.

Eine Schnittstelle ist eine Variante einer abstrakten Klasse. In einer Schnittstelle sind alle Methoden abstrakt. Durch die Implementierung einer solchen Schnittstelle kann eine Mehrfachvererbung erreicht werden. Alle Methoden in der Schnittstelle sind abstrakt und keine von ihnen verfügt über einen Programmkörper. Schnittstellen können nur statische Endelementvariablen definieren. Die Implementierung einer Schnittstelle ähnelt der Unterklassenbildung, mit der Ausnahme, dass die implementierende Klasse das Verhalten nicht von der Schnittstellendefinition erben kann. Wenn eine Klasse eine bestimmte Schnittstelle implementiert, definiert sie alle Methoden dieser Schnittstelle (d. h. gibt ihnen den Programmkörper). Anschließend kann es die Methoden der Schnittstelle für jedes Objekt der Klasse aufrufen, die die Schnittstelle implementiert. Da es abstrakte Klassen gibt, ist die Verwendung des Schnittstellennamens als Typ der Referenzvariablen möglich. Die normale dynamische Verknüpfung wird wirksam. Referenzen können in und von Schnittstellentypen konvertiert werden, und der Operator „instanceof“ kann verwendet werden, um zu bestimmen, ob die Klasse eines Objekts die Schnittstelle implementiert.

Schnittstellen können Schnittstellen erben. Abstrakte Klassen können Schnittstellen implementieren und abstrakte Klassen können Entitätsklassen erben. Voraussetzung ist jedoch, dass die Entitätsklasse über einen klaren Konstruktor verfügen muss. Schnittstellen konzentrieren sich mehr darauf, „welche Funktionen erreicht werden können“, unabhängig davon, „wie sie implementiert werden“ .

1. Ähnlichkeiten
A. Beide sind abstrakte Klassen und können nicht instanziiert werden.
B. Sowohl Schnittstellenimplementierungsklassen als auch Unterklassen der abstrakten Klasse müssen die deklarierten abstrakten Methoden implementieren.

2. Unterschiede
Eine Schnittstelle muss mithilfe von Implements implementiert werden, während die abstrakte Klasse mithilfe von Extends vererbt werden muss.
B. Eine Klasse kann mehrere Schnittstellen implementieren, aber eine Klasse kann nur eine abstrakte Klasse erben.
Die C-Schnittstelle legt den Schwerpunkt auf die Implementierung spezifischer Funktionen, während die abstrakte Klasse die Eigentumsbeziehung betont.
D. Obwohl sowohl die Schnittstellenimplementierungsklasse als auch die Unterklassen der abstrakten Klasse die entsprechenden abstrakten Methoden implementieren müssen, sind die Implementierungsformen unterschiedlich. Jede Methode in der Schnittstelle ist eine abstrakte Methode und wird nur deklariert. (Deklaration, kein Methodenkörper), die Implementierungsklasse muss es implementieren. Unterklassen einer abstrakten Klasse können selektiv implementiert werden.
Diese Auswahl hat zwei Bedeutungen:
Erstens sind nicht alle Methoden in der Abastract-Klasse abstrakt, sondern nur die Methoden mit dem Titel abstract. Es ist abstrakt und muss von Unterklassen implementiert werden. Für Methoden ohne Abstract muss der Methodenkörper in der Abstract-Klasse definiert werden.
Zweitens: Wenn eine Unterklasse einer abstrakten Klasse diese erbt, kann sie nicht-abstrakte Methoden direkt erben oder überschreiben. Sie können diese auch implementieren oder ihre Methode erneut als abstrakt deklarieren, ohne sie implementieren zu müssen ihren Unterklassen überlassen, diese Klasse muss aber auch als abstrakt deklariert werden. Da es sich um eine abstrakte Klasse handelt, kann sie natürlich nicht instanziiert werden.

Die abstrakte Klasse E ist der Vermittler zwischen Schnittstelle und Klasse.
Die Schnittstelle ist vollständig abstrakt. Sie kann nur Methoden deklarieren und nur öffentliche Methoden können nicht deklariert werden. Methodenkörper können nicht definiert werden und Instanzvariablen können nicht deklariert werden. Allerdings können Schnittstellen konstante Variablen deklarieren, und es ist nicht schwer, solche Beispiele im JDK zu finden. Das Platzieren konstanter Variablen in einer Schnittstelle verstößt jedoch gegen deren Zweck, als Schnittstelle zu existieren, und bringt außerdem die unterschiedlichen Werte von Schnittstellen und Klassen durcheinander. Wenn Sie es wirklich benötigen, können Sie es in die entsprechende abstrakte Klasse oder Klasse einfügen.
Abstrakte Klasse spielt eine verbindende Rolle in Schnittstelle und Klasse. Einerseits ist eine abstrakte Klasse abstrakt und kann abstrakte Methoden deklarieren, um die Funktionen zu standardisieren, die Unterklassen implementieren müssen. Andererseits kann sie Standardmethodenkörper für die direkte Verwendung oder Überschreibung durch Unterklassen definieren. Darüber hinaus kann es durch Vererbung eigene Instanzvariablen zur Verwendung durch Unterklassen definieren.

Anwendungsfälle der Schnittstelle
A. Klassen benötigen vorher spezifische Schnittstellen zur Koordination, unabhängig davon, wie sie implementiert werden.
B. Es existiert als Logo, das eine bestimmte Funktion realisieren kann, oder es kann ein reines Logo ohne Schnittstellenmethoden sein.
C. Eine Gruppe von Klassen muss als eine einzelne Klasse behandelt werden, und der Anrufer kontaktiert diese Gruppe von Klassen nur über die Schnittstelle.
D. Es müssen mehrere bestimmte Funktionen implementiert werden, und diese Funktionen haben möglicherweise überhaupt keine Verbindung.

Anwendungsfälle abstrakter Klassen
Kurz gesagt, wenn sowohl eine einheitliche Schnittstelle als auch Instanzvariablen oder Standardwerte benötigt werden, Sie können es verwenden. Die gebräuchlichsten sind:
A. Definieren Sie eine Reihe von Schnittstellen, möchten aber nicht jede Implementierungsklasse zwingen, alle Schnittstellen zu implementieren. Sie können eine abstrakte Klasse verwenden, um eine Reihe von Methodenkörpern oder sogar leere Methodenkörper zu definieren, und dann Unterklassen die Methoden auswählen lassen, die sie abdecken möchten.
B. In einigen Fällen können reine Schnittstellen die Koordination zwischen Klassen auch nicht erfüllen, um verschiedene Beziehungen zu unterscheiden. Die Vermittlerrolle des Abstrakten kann dies sehr gut erfüllen.
C. Standardisiert eine Reihe gegenseitig koordinierter Methoden, von denen einige gemeinsam und zustandsunabhängig sind und ohne die Notwendigkeit geteilt werden können, dass Unterklassen sie separat implementieren müssen; Klassen implementieren bestimmte Funktionen basierend auf ihrem spezifischen Zustand.

Vorteile von Schnittstellen und abstrakten Klassen:

    好像定义接口是提前做了个多余的工作。下面我给大家总结了4点关于JAVA中接口存在的意义:

  1、重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。

  2、简单、规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些业务,而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无法看明白)。

  3、维护、拓展性:比如你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,然后你就这样定义了这个类。

    可是在不久将来,你突然发现这个类满足不了你了,然后你又要重新设计这个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起来很麻烦。

    如果你一开始定义一个接口,把绘制功能放在接口里,然后定义类时实现这个接口,然后你只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。

  4、安全、严密性:接口是实现软件松耦合的重要手段,它描叙了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多)。

    尽管抽象类和接口之间存在较大的相同点,甚至有时候还可以互换,但这样并不能弥补他们之间的差异之处。下面将从语法层次和设计层次两个方面对抽象类和接口进行阐述。

语法层次

在语法层次,java语言对于抽象类和接口分别给出了不同的定义。下面已Demo类来说明他们之间的不同之处。

使用抽象类来实现:

public abstract class Demo {  abstract void method1();  
      
      void method2(){  //实现      }  
}

 

使用接口来实现

interface Demo {  void method1();  void method2();  
}

 

    抽象类方式中,抽象类可以拥有任意范围的成员数据,同时也可以拥有自己的非抽象方法,但是接口方式中,它仅能够有静态、不能修改的成员数据(但是我们一般是不会在接口中使用成员数据),同时它所有的方法都必须是抽象的。在某种程度上来说,接口是抽象类的特殊化。

    对子类而言,它只能继承一个抽象类(这是java为了数据安全而考虑的),但是却可以实现多个接口。

设计层次

      上面只是从语法层次和编程角度来区分它们之间的关系,这些都是低层次的,要真正使用好抽象类和接口,我们就必须要从较高层次来区分了。只有从设计理念的角度才能看出它们的本质所在。一般来说他们存在如下三个不同点:

    1、 抽象层次不同。抽象类是对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。

    2、 跨域不同。抽象类所跨域的是具有相似特点的类,而接口却可以跨域不同的类。我们知道抽象类是从子类中发现公共部分,然后泛化成抽象类,子类继承该父类即可,但是接口不同。实现它的子类可以不存在任何关系,共同之处。例如猫、狗可以抽象成一个动物类抽象类,具备叫的方法。鸟、飞机可以实现飞Fly接口,具备飞的行为,这里我们总不能将鸟、飞机共用一个父类吧!所以说抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is-a" 关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的, 仅仅是实现了接口定义的契约而已。

    3、 设计层次不同。对于抽象类而言,它是自下而上来设计的,我们要先知道子类才能抽象出父类,而接口则不同,它根本就不需要知道子类的存在,只需要定义一个规则即可,至于什么子类、什么时候怎么实现它一概不知。比如我们只有一个猫类在这里,如果你这是就抽象成一个动物类,是不是设计有点儿过度?我们起码要有两个动物类,猫、狗在这里,我们在抽象他们的共同点形成动物抽象类吧!所以说抽象类往往都是通过重构而来的!但是接口就不同,比如说飞,我们根本就不知道会有什么东西来实现这个飞接口,怎么实现也不得而知,我们要做的就是事前定义好飞的行为接口。所以说抽象类是自底向上抽象而来的,接口是自顶向下设计出来的。

      我们有一个Door的抽象概念,它具备两个行为open()和close(),此时我们可以定义通过抽象类和接口来定义这个抽象概念:

   抽象类:

abstract class Door{  abstract void open();  abstract void close();  
}

 

   接口

interface Door{  void open();  void close();  
}

 

       至于其他的具体类可以通过使用extends使用抽象类方式定义Door或者Implements使用接口方式定义Door,这里发现两者并没有什么很大的差异。

   但是现在如果我们需要门具有报警的功能,那么该如何实现呢?

   解决方案一:给Door增加一个报警方法:clarm();

abstract class Door{  abstract void open();  abstract void close();  abstract void alarm();  
}

 

    或者

interface Door{  void open();  void close();  void alarm();  
}

 

 

       这种方法违反了面向对象设计中的一个核心原则 ISP (Interface Segregation Principle)(参见:),在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方 法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变而改变,反之依然。

   解决方案二

   既然open()、close()和alarm()属于两个不同的概念,那么我们依据ISP原则将它们分开定义在两个代表两个不同概念的抽象类里面,定义的方式有三种:

   1、两个都使用抽象类来定义。

   2、两个都使用接口来定义。

   3、一个使用抽象类定义,一个是用接口定义。

   由于java不支持多继承所以第一种是不可行的。后面两种都是可行的,但是选择何种就反映了你对问题域本质的理解。

   如果选择第二种都是接口来定义,那么就反映了两个问题:1、我们可能没有理解清楚问题域,AlarmDoor在概念本质上到底是门还报警器。2、如果我们对问题域的理解没有问题,比如我们在分析时确定了AlarmDoor在本质上概念是一致的,那么我们在设计时就没有正确的反映出我们的设计意图。因为你使用了两个接口来进行定义,他们概念的定义并不能够反映上述含义。

   第三种,如果我们对问题域的理解是这样的:AlarmDoor本质上Door,但同时它也拥有报警的行为功能,这个时候我们使用第三种方案恰好可以阐述我们的设计意图。AlarmDoor本质是们,所以对于这个概念我们使用抽象类来定义,同时AlarmDoor具备报警功能,说明它能够完成报警概念中定义的行为功能,所以alarm可以使用接口来进行定义。如下:

abstract class Door{  abstract void open();  abstract void close();  
}  
  
interface Alarm{  void alarm();  
}  
  
class AlarmDoor extends Door implements Alarm{  void open(){}  void close(){}  void alarm(){}  
}

 

       这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实抽象类表示的是"is-a"关系,接口表示的是"like-a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。

      批注:

   ISP(Interface Segregation Principle):面向对象的一个核心原则。它表明使用多个专门的接口比使用单一的总接口要好。

   一个类对另外一个类的依赖性应当是建立在最小的接口上的。

   一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。

Zusammenfassung

1. Abstrakte Klassen stellen eine Vererbungsbeziehung in der Java-Sprache dar. Eine Unterklasse kann nur eine übergeordnete Klasse haben, es können jedoch mehrere Schnittstellen vorhanden sein.

2. Abstrakte Klassen können ihre eigenen Mitgliedsvariablen und nicht-abstrakten Klassenmethoden haben, aber in Schnittstellen können nur statische und unveränderliche Mitgliedsdaten vorhanden sein (aber im Allgemeinen nicht in Schnittstellen), die Mitgliedsdaten definieren ), und alle seine Methoden sind abstrakt.

3. Die von abstrakten Klassen und Schnittstellen reflektierten Designkonzepte sind unterschiedlich. Abstrakte Klassen repräsentieren die „ist-ein“-Beziehung, während Schnittstellen die „wie-ein“-Beziehung darstellen.

Abstrakte Klassen und Schnittstellen sind zwei verschiedene abstrakte Konzepte in der Java-Sprache. Ihre Existenz bietet eine sehr gute Unterstützung für Polymorphismus, obwohl es große Ähnlichkeiten zwischen ihnen gibt. Ihre Wahl spiegelt jedoch häufig Ihr Verständnis des Problembereichs wider. Nur mit einem guten Verständnis der Natur des Problembereichs können wir korrekte und vernünftige Entwürfe erstellen.

Das obige ist der detaillierte Inhalt vonWas ist die Schnittstelle? Was ist eine abstrakte Klasse?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn