Kürzlich bin ich beim Erlernen der PHP5-Schnittstelle auf Schwierigkeiten gestoßen. Im Buch heißt es, es sei eine Möglichkeit, Mehrfachvererbung zu implementieren, aber ich weiß immer noch nicht, wie ich es implementieren soll. Es gibt nur sehr wenige Informationen zur PHP-Schnittstelle im Internet, daher habe ich sie in Java überprüft. Tatsächlich sind sie im Grunde gleich. Nachdem ich den Artikel „Erklärung von Java (Schnittstellen und Vererbung)“ gelesen hatte, wurde mir plötzlich klar, dass ich ihn von Anfang an falsch verstanden hatte. Die sogenannte Mehrfachvererbung bezieht sich auf Schnittstellen, die Klassen erben, und nicht auf Klassen, die Schnittstellen erben.
Der Artikel erwähnte die Abstraktion von OO. Genau wie der Satz im Artikel – „Abstraktion bedeutet, den Bildteil zu entfernen“ –, als ich über Abstraktion nachdachte, dachte ich immer, dass sie schwer zu verstehen sei , es ist jetzt leicht zu verstehen. Ja, genau das tun Schnittstellen und abstrakte Klassen.
Der Artikel enthält viele weitere Standpunkte, die mir sehr geholfen haben, wie unten aufgeführt:
Die Essenz von OO liegt meiner Meinung nach in der Abstraktion von Objekten.
Kurz gesagt besteht die Funktion der Schnittstelle darin, den Klassentyp zu markieren. Durch die Zuordnung unterschiedlicher Klassentypen zu verschiedenen Schnittstellen können diese besser verwaltet werden.
Der Sinn der Vererbung ist auch die Abstraktion, nicht die Wiederverwendung von Code.
Nachdem ich diesen Artikel gelesen habe, verstehe ich nun grundsätzlich, wie man Schnittstellen, abstrakte Klassen und Vererbung anwendet.
Der Originaltext lautet wie folgt:
Klärung von Java (Schnittstellen und Vererbung) Mein Bruder, ein Student im zweiten Jahr an der Fakultät für Informatik, diskutierte mit mir über Java. Als wir uns trafen, drehten sich mehrere Fragen um die Verwendung von Schnittstellen. Warum Schnittstellen verwenden? Wann sollten Sie Schnittstellen verwenden? Ich bin froh, dass sie mich nicht gefragt haben, wie man mit Java eine Verbindung zu SQL Server herstellt oder wie man J2EE-Anwendungen entwickelt. Solche Fragen sind tödlich und sollten vermieden werden. In diesem Jahr hat die Fakultät für Informatik ein Abschlussprojekt zu J2ME. Die Studenten, die sich für dieses Thema entschieden haben, studierten Ende Mai noch mit einer Grimasse das Paket java.util.*, dies und das ... seufz.
Die meisten Menschen glauben, dass der Zweck von Schnittstellen darin besteht, die Mehrfachvererbung zu ersetzen. Wie wir alle wissen, verfügt Java nicht über einen Mehrfachvererbungsmechanismus wie C++, kann jedoch mehrere Schnittstellen implementieren. Tatsächlich ist dies weit hergeholt. Schnittstellen und Vererbung sind völlig unterschiedliche Dinge. Schnittstellen können die Mehrfachvererbung nicht ersetzen und haben keine solche Verpflichtung. Kurz gesagt besteht die Funktion der Schnittstelle darin, den Klassentyp zu markieren. Durch die Zuordnung unterschiedlicher Klassentypen zu verschiedenen Schnittstellen können diese besser verwaltet werden. Ich denke, das Wesen von OO ist die Abstraktion von Objekten, und die Schnittstelle verkörpert dies am besten. Der Grund, warum wir Entwurfsmuster nur für Sprachen mit abstrakten Fähigkeiten (wie C++, Java, C# usw.) diskutieren, liegt daran, dass es bei der Untersuchung von Entwurfsmustern tatsächlich darum geht, wie man vernünftig abstrahiert. (Cowboys berühmtes Sprichwort lautet „Abstraktion bedeutet, den Bildteil zu entfernen“, was wie ein Witz aussieht, aber tatsächlich wahr ist.)
Das grundlegendste Entwurfsmuster ist das Factory-Muster, das ich kürzlich erstellt habe. Ich wollte mein Bestes geben, um mein Programm zwischen mehreren Datenbanken portierbar zu machen. Dies bringt natürlich viele Probleme mit sich, einschließlich der Kompatibilität von SQL aus verschiedenen DBMS bereitet Kopfschmerzen. Wir könnten das Problem genauso gut zunächst vereinfachen und nur überlegen, wie verschiedene Datenbanken verbunden werden.
Angenommen, ich habe viele Klassen, nämlich Mysql.java, SQLServer.java, Oracle.java und DB2.java. Sie stellen jeweils eine Verbindung zu unterschiedlichen Datenbanken her, geben einheitlich ein Verbindungsobjekt zurück und verfügen alle über eine Schließmethode zum Schließen der Verbindung. Sie müssen nur verschiedene Klassen für Ihr DBMS auswählen und können es verwenden. Aber welche Datenbank wird mein Benutzer verwenden? Ich weiß nicht, ich hoffe, den Code so wenig wie möglich zu ändern, um seinen Bedürfnissen gerecht zu werden. Ich kann die folgende Schnittstelle abstrahieren:
Paket org.bromon.test;
öffentliche Schnittstellen-DB
{
java.sql.Connection openDB(String url,String user,String passwort);
void close();
}
Diese Schnittstelle definiert nur zwei Methoden ohne sinnvollen Code. Der spezifische Code wird von der Klasse bereitgestellt, die diese Schnittstelle implementiert, z. B. Mysql.java:
Package org.bromon.test;
java.sql.* importieren;
Die öffentliche Klasse MySQL implementiert DB
{
private String url="jdbc:mysql:localhost:3306/test";
privater String user="root";
privater String passwort=““;
private Verbindung conn;
öffentliche Verbindung openDB(URL,Benutzer,Passwort)
{
//Code zum Herstellen einer Verbindung zur Datenbank}
public void close()
{
//Datenbank schließen}
}
Ähnliche sind natürlich Oracle.java usw. Die Schnittstellen-DB klassifiziert diese Klassen in der Anwendung wie folgt:
org.bromon.test.DB myDB
verwenden, um die Datenbank zu betreiben, und Sie nicht. Ich muss mir keine Gedanken darüber machen, welche Klasse ich tatsächlich verwende, das sogenannte „Offen-Geschlossen“-Prinzip. Das Problem ist jedoch, dass die Schnittstelle nicht instanziiert werden kann, myDB = new DB (), ein solcher Code ist absolut falsch, wir können nur myDB = new Mysql () oder myDB = new Oracle () verwenden. Entschuldigung, ich muss noch angeben, welche Klasse instanziiert werden soll. Die Verwendung einer Schnittstelle ist nutzlos. Wir brauchen also eine Fabrik:
package org.bromon.test;
öffentliche Klasse DBFactory
{
öffentliche statische DB-Verbindung getConn()
{
Return(new Mysql());
}
}
Der Instanziierungscode lautet also: myDB=DBFactory.getConn();
Dies ist die grundlegendste gewöhnliche Factory (Factory) unter den 23 Modi. Die Factory-Klasse ist dafür verantwortlich, welche Klasse und andere Programmlogik auf der DB-Schnittstelle ausgeführt wird. Dies ist „Programmierung für die Schnittstelle“. Die Verantwortlichkeiten wurden an die Factory-Klasse weitergegeben. Natürlich können Sie die Factory-Schnittstelle auch weiterhin definieren und die Verantwortlichkeiten weiter hochwerfen, wodurch sich eine abstrakte Factory entwickelt.
Die Schnittstelle ist während des gesamten Prozesses nicht für bestimmte Vorgänge verantwortlich. Wenn andere Programme eine Verbindung zur Datenbank herstellen möchten, müssen sie lediglich ein DB-Objekt erstellen, unabhängig davon, wie sich die Factory-Klasse ändert. Darum geht es bei Schnittstellen: Abstraktion.
Es versteht sich von selbst, dass das Konzept der Vererbung leicht zu verstehen ist. Warum erben? Weil Sie Code wiederverwenden möchten? Dies ist definitiv kein Grund für die Vererbung, nicht für die Wiederverwendung von Code. Wenn Objekt A eine run()-Methode hat, möchte Objekt B auch diese Methode haben, sodass jemand Klasse B verwendet, um A zu erweitern. Das ist ein gedankenloser Ansatz. Kann derselbe Zweck erreicht werden, wenn Sie A in B instanziieren und die Run()-Methode von A aufrufen? wie folgt:
Klasse B
{
A a=neues A();
a.run();
}
Dies dient dazu, die Aggregation von Klassen zur Wiederverwendung von Code zu nutzen. Dies ist der Prototyp des Delegationsmodells und eine Praxis, die GoF immer befürwortet hat.
Was ist also der Sinn der Vererbung? Tatsächlich ist dies auf historische Gründe zurückzuführen. Die ursprüngliche OO-Sprache hatte nur Vererbung und keine Schnittstellen, sodass die Abstraktion nur durch Vererbung erreicht werden konnte. Bitte beachten Sie, dass die ursprüngliche Absicht der Vererbung die Abstraktion und nicht die Wiederverwendung von Code ist (obwohl dies auch bei der Vererbung der Fall ist). Dies ist einer der schwerwiegendsten Fehler vieler schlechter Java-Bücher. Schlechte Bücher sind für Menschen schädlich. Sie sind zu giftig. Wann sollten Sie die Vererbung nutzen? Verwenden Sie es nur in abstrakten Klassen und versuchen Sie, es nicht in anderen Situationen zu verwenden. Abstrakte Klassen können nicht instanziiert werden. Sie stellen lediglich eine Vorlage bereit, die das Problem veranschaulicht.
Die Wurzel allen Übels in der Softwareentwicklung, insbesondere unter C++-Programmierern, ist die Duplizierung von Code statt der Wiederverwendung von Code und der Missbrauch der Vererbung. Der Zweck des Verbots der Mehrfachvererbung in Java besteht darin, den Missbrauch der Vererbung zu stoppen. Dies ist ein sehr kluger Ansatz, aber viele Menschen verstehen ihn nicht. Java kann Design besser widerspiegeln, was einer der Gründe ist, warum ich fasziniert bin.