JavaRush /Java-Blog /Random-DE /OOP-Prinzipien

OOP-Prinzipien

Veröffentlicht in der Gruppe Random-DE
Java ist eine objektorientierte Sprache. Das bedeutet, dass Sie Java-Programme in einem objektorientierten Stil schreiben müssen. Und dieser Stil basiert auf der Verwendung von Objekten und Klassen im Programm.

Grundprinzipien von OOP:

Prinzipien von OOP - 1Versuchen wir anhand von Beispielen zu verstehen, was Klassen und Objekte sind und wie man die Grundprinzipien von OOP in der Praxis anwendet: Abstraktion, Vererbung, Polymorphismus und Kapselung.

Was ist ein Objekt?

Die Welt, in der wir leben, besteht aus Objekten. Wenn wir uns umschauen, werden wir feststellen, dass wir von Häusern, Bäumen, Autos, Möbeln, Geschirr und Computern umgeben sind. Alle diese Gegenstände sind Objekte und jeder von ihnen hat eine Reihe spezifischer Eigenschaften, Verhaltensweisen und Zwecke. Wir sind an Gegenstände gewöhnt und verwenden sie immer für ganz bestimmte Zwecke. Wenn wir zum Beispiel zur Arbeit müssen, benutzen wir ein Auto, wenn wir essen wollen, benutzen wir Geschirr, und wenn wir uns entspannen wollen, brauchen wir ein bequemes Sofa. Ein Mensch ist es gewohnt, objektiv zu denken, um Probleme im Alltag zu lösen. Dies war einer der Gründe für die Verwendung von Objekten in der Programmierung, und dieser Ansatz zur Programmerstellung wurde als objektorientiert bezeichnet. Geben wir ein Beispiel. Stellen Sie sich vor, Sie haben ein neues Telefonmodell entwickelt und möchten mit der Massenproduktion beginnen. Als Telefondesigner wissen Sie, wozu es dient, wie es funktioniert und aus welchen Teilen es bestehen wird (Gehäuse, Mikrofon, Lautsprecher, Kabel, Tasten usw.). Allerdings wissen nur Sie, wie Sie diese Teile verbinden. Sie planen jedoch nicht, Telefone selbst zu produzieren, dafür verfügen Sie über einen ganzen Mitarbeiterstab. Damit Sie nicht jedes Mal erklären müssen, wie die Teile des Telefons verbunden werden, und damit alle Telefone in der Produktion gleich ausfallen, müssen Sie vor Beginn der Produktion eine Zeichnung in Form eines anfertigen Beschreibung des Aufbaus des Telefons. In OOP wird eine solche Beschreibung, Zeichnung, ein Diagramm oder eine Vorlage als Klasse bezeichnet, aus der bei der Ausführung des Programms ein Objekt erstellt wird. Eine Klasse ist eine Beschreibung eines Objekts, das noch nicht erstellt wurde, wie eine allgemeine Vorlage bestehend aus Feldern, Methoden und einem Konstruktor, und ein Objekt ist eine Instanz einer Klasse, die auf der Grundlage dieser Beschreibung erstellt wurde.

OOP-Abstraktion

Lassen Sie uns nun am Beispiel des Telefons darüber nachdenken, wie wir von einem Objekt in der realen Welt zu einem Objekt in einem Programm wechseln können. Die Geschichte dieses Kommunikationsmittels reicht über 100 Jahre zurück und das moderne Telefon ist im Gegensatz zu seinem Vorgänger aus dem 19. Jahrhundert ein viel komplexeres Gerät. Wenn wir ein Telefon benutzen, denken wir nicht über seine Struktur und die darin ablaufenden Prozesse nach. Wir nutzen einfach die von den Telefonentwicklern bereitgestellten Funktionen – Tasten oder Touchscreen, um eine Nummer auszuwählen und Anrufe zu tätigen. Eine der ersten Telefonschnittstellen war ein Knopf, den man zum Tätigen eines Anrufs drehte. Das war natürlich nicht sehr praktisch. Dennoch erfüllte der Griff seine Funktion einwandfrei. Schaut man sich das modernste und allererste Telefon an, erkennt man sofort die wichtigsten Details, die sowohl für ein Gerät aus dem späten 19. Jahrhundert als auch für ein hochmodernes Smartphone wichtig sind. Dabei wird ein Anruf getätigt (eine Nummer gewählt) und ein Anruf entgegengenommen. Im Wesentlichen ist es das, was ein Telefon zu einem Telefon macht und nicht zu etwas anderem. Jetzt haben wir das Prinzip in OOP angewendet – die Hervorhebung der wichtigsten Eigenschaften und Informationen zu einem Objekt. Dieses Prinzip von OOP wird Abstraktion genannt. Abstraktion kann in OOP auch als eine Möglichkeit definiert werden, Elemente eines realen Problems als Objekte in einem Programm darzustellen. Abstraktion ist immer mit der Verallgemeinerung einiger Informationen über die Eigenschaften von Objekten oder Objekten verbunden, daher geht es vor allem darum, im Kontext des zu lösenden Problems wesentliche Informationen von unbedeutenden Informationen zu trennen. Dabei kann es mehrere Abstraktionsebenen geben. Versuchen wir, das Abstraktionsprinzip auf unsere Telefone anzuwenden. Lassen Sie uns zunächst die gängigsten Telefontypen von den Anfängen bis heute hervorheben. Sie können beispielsweise in Form eines in Abbildung 1 dargestellten Diagramms dargestellt werden. Prinzipien von OOP - 2Mit Hilfe der Abstraktion können wir nun allgemeine Informationen in dieser Objekthierarchie hervorheben: einen gemeinsamen abstrakten Objekttyp - Telefon, ein allgemeines Merkmal von das Telefon – das Jahr seiner Entstehung und eine gemeinsame Schnittstelle – alle Telefone sind in der Lage, Anrufe zu empfangen und zu senden. So sieht es in Java aus:
public abstract class AbstractPhone {
    private int year;

    public AbstractPhone(int year) {
        this.year = year;
    }
    public abstract void call(int outputNumber);
    public abstract void ring (int inputNumber);
}
Basierend auf dieser abstrakten Klasse können wir im Programm neue Telefontypen erstellen und dabei andere grundlegende Java-OOP-Prinzipien verwenden, die wir im Folgenden betrachten werden.

Verkapselung

Mit Hilfe der Abstraktion heben wir hervor, was allen Objekten gemeinsam ist. Allerdings ist jedes Telefonmodell individuell und unterscheidet sich etwas von anderen. Wie können wir im Programm Grenzen ziehen und diese Individualität benennen? Wie können wir sicherstellen, dass keiner der Benutzer versehentlich oder absichtlich unser Telefon kaputt macht oder versucht, ein Modell in ein anderes umzuwandeln? Für die Welt der realen Objekte liegt die Antwort auf der Hand: Sie müssen alle Teile in das Telefongehäuse einbauen. Wenn wir dies nicht tun und das gesamte Innere des Telefons und die Verbindungskabel draußen lassen, wird es mit Sicherheit einen neugierigen Experimentator geben, der die Funktionsweise unseres Telefons „verbessern“ möchte. Um solche Eingriffe in das Design und den Betrieb eines Objekts zu vermeiden, nutzt OOP das Prinzip der Kapselung – ein weiteres Grundprinzip von OOP, bei dem die Attribute und das Verhalten eines Objekts in einer Klasse zusammengefasst werden, die interne Implementierung des Objekts bleibt jedoch verborgen dem Benutzer und es wird eine offene Schnittstelle für die Arbeit mit dem Objekt bereitgestellt. Die Aufgabe des Programmierers besteht darin, zu bestimmen, welche Attribute und Methoden öffentlich zugänglich sind und welche interne Implementierungen des Objekts sind und nicht geändert werden sollten.

Kapselung und Zugriffskontrolle

Nehmen wir an, dass während der Produktion auf der Rückseite des Telefons Informationen darüber eingraviert werden: das Herstellungsjahr oder das Logo des Herstellers. Diese Information charakterisiert dieses Modell ganz konkret – seinen Zustand. Wir können sagen, dass der Telefonentwickler auf die Unveränderlichkeit dieser Informationen geachtet hat – es ist unwahrscheinlich, dass jemand auf die Idee kommt, die Gravur zu entfernen. In der Java-Welt wird der Zustand zukünftiger Objekte in einer Klasse mithilfe von Feldern beschrieben, und ihr Verhalten wird mithilfe von Methoden beschrieben. Die Möglichkeit, Status und Verhalten zu ändern, wird mithilfe von Zugriffsmodifikatoren auf Felder und Methoden ausgeführt – private, protected, publicund default(Standardzugriff). Wir haben beispielsweise entschieden, dass das Erstellungsjahr, der Name des Telefonherstellers und eine der Methoden zur internen Implementierung der Klasse gehören und nicht von anderen Objekten im Programm geändert werden können. Mithilfe von Code kann die Klasse wie folgt beschrieben werden:
public class SomePhone {

    private int year;
    private String company;
    public SomePhone(int year, String company) {
        this.year = year;
        this.company = company;
    }
private void openConnection(){
    //findComutator
    //openNewConnection...
}
public void call() {
    openConnection();
    System.out.println(„Ich rufe eine Nummer an“);
}

public void ring() {
    System.out.println("Дзынь-дзынь");
}

 }
Ein Modifikator privatemacht die Felder und Methoden einer Klasse nur innerhalb dieser Klasse verfügbar. Das bedeutet, dass privatevon außen weder auf Felder zugegriffen werden kann noch privateMethoden aufgerufen werden können. Das Verbergen des Zugriffs auf eine Methode openConnectiongibt uns auch die Möglichkeit, die interne Implementierung dieser Methode frei zu ändern, da diese Methode garantiert nicht von anderen Objekten verwendet wird und deren Betrieb nicht stört. Um mit unserem Objekt zu arbeiten, lassen wir die Methoden callmit ringdem Modifikator offen public. Die Bereitstellung öffentlicher Methoden für die Arbeit mit einem Objekt ist ebenfalls Teil des Kapselungsmechanismus, denn wenn der Zugriff auf ein Objekt vollständig verweigert wird, wird es unbrauchbar.

Nachlass

Schauen wir uns noch einmal die Telefontabelle an. Sie können sehen, dass es sich um eine Hierarchie handelt, in der das darunter liegende Modell alle Merkmale der weiter oben in der Verzweigung befindlichen Modelle sowie seine eigenen aufweist. Beispielsweise nutzt ein Smartphone ein Mobilfunknetz zur Kommunikation (hat die Eigenschaften eines Mobiltelefons), ist drahtlos und tragbar (hat die Eigenschaften eines schnurlosen Telefons) und kann Anrufe empfangen und tätigen (hat die Eigenschaften eines Telefons). In diesem Fall können wir von der Vererbung von Objekteigenschaften sprechen. In der Programmierung bezeichnet Vererbung die Verwendung bestehender Klassen zur Definition neuer Klassen. Schauen wir uns ein Beispiel für die Erstellung einer Smartphone-Klasse mithilfe der Vererbung an. Alle schnurlosen Telefone werden mit wiederaufladbaren Batterien betrieben, die eine bestimmte Betriebsdauer in Stunden haben. Fügen wir diese Eigenschaft also zur Klasse der Mobiltelefone hinzu:
public abstract class WirelessPhone extends AbstractPhone {

    private int hour;

    public WirelessPhone(int year, int hour) {
        super(year);
        this.hour = hour;
    }
    }
Mobiltelefone erben die Eigenschaften eines Mobiltelefons. Wir haben dieser Klasse auch eine Implementierung der Methoden callund hinzugefügt ring:
public class CellPhone extends WirelessPhone {
    public CellPhone(int year, int hour) {
        super(year, hour);
    }

    @Override
    public void call(int outputNumber) {
        System.out.println(„Eine Nummer anrufen“ + outputNumber);
    }

    @Override
    public void ring(int inputNumber) {
        System.out.println(„Ein Teilnehmer ruft Sie an“ + inputNumber);
    }
}
Und schließlich die Smartphone-Klasse, die im Gegensatz zu klassischen Mobiltelefonen über ein vollwertiges Betriebssystem verfügt. Sie können Ihrem Smartphone neue, von diesem Betriebssystem unterstützte Programme hinzufügen und so dessen Funktionalität erweitern. Mithilfe von Code kann die Klasse wie folgt beschrieben werden:
public class Smartphone extends CellPhone {

    private String operationSystem;

    public Smartphone(int year, int hour, String operationSystem) {
        super(year, hour);
        this.operationSystem = operationSystem;
    }
public void install(String program){
    System.out.println(„Installieren“ + program + "Für" + operationSystem);
}

}
Wie Sie sehen, Smartphonehaben wir nur sehr wenig neuen Code zur Beschreibung der Klasse erstellt, aber wir haben eine neue Klasse mit neuer Funktionalität erhalten. Der Einsatz des OOP-Vererbungsprinzips kann die Codemenge deutlich reduzieren und somit die Arbeit des Programmierers erleichtern.

Polymorphismus

Wenn wir uns alle Telefonmodelle ansehen, können wir trotz der Unterschiede in Aussehen und Design der Modelle ein gemeinsames Verhalten erkennen: Sie können alle Anrufe entgegennehmen und tätigen und verfügen über einen ziemlich klaren und einfachen Satz von Steuertasten. Wenn wir eines der Grundprinzipien von OOP anwenden, das uns bereits bekannt ist, die Abstraktion in Programmiersprache, können wir sagen, dass das Telefonobjekt eine gemeinsame Schnittstelle hat. Daher können Telefonbenutzer ganz bequem verschiedene Modelle mit denselben Bedientasten (mechanisch oder Touch) bedienen, ohne auf die technischen Details des Geräts eingehen zu müssen. Sie nutzen also ständig ein Mobiltelefon und können problemlos über das Festnetztelefon telefonieren. Das Prinzip in OOP, bei dem ein Programm Objekte mit derselben Schnittstelle verwenden kann, ohne Informationen über die interne Struktur des Objekts zu benötigen, wird als Polymorphismus bezeichnet . Stellen wir uns vor, dass wir in unserem Programm einen Benutzer beschreiben müssen, der jedes Telefonmodell verwenden kann, um einen anderen Benutzer anzurufen. So geht's:
public class User {
    private String name;

    public User(String name) {
        this.name = name;
            }

    public void callAnotherUser(int number, AbstractPhone phone){
// hier ist es Polymorphismus – Verwendung des abstrakten Typs AbstractPhone phone im Code!
        phone.call(number);
    }
}
 }
Beschreiben wir nun die verschiedenen Telefonmodelle. Eines der ersten Telefonmodelle:
public class ThomasEdisonPhone extends AbstractPhone {

public ThomasEdisonPhone(int year) {
    super(year);
}
    @Override
    public void call(int outputNumber) {
        System.out.println(„Den Griff umdrehen“);
        System.out.println(„Geben Sie mir die Telefonnummer, Sir“);
    }

    @Override
    public void ring(int inputNumber) {
        System.out.println("Anrufe");
    }
}
Normales Festnetztelefon:
public class Phone extends AbstractPhone {

    public Phone(int year) {
        super(year);
    }

    @Override
    public void call(int outputNumber) {
        System.out.println(„Ich rufe eine Nummer an“ + outputNumber);
    }

    @Override
    public void ring(int inputNumber) {
        System.out.println("Anrufe");
    }
}
Und zum Schluss noch ein cooles Videotelefon:
public class VideoPhone extends AbstractPhone {

    public VideoPhone(int year) {
        super(year);
    }
    @Override
    public void call(int outputNumber) {
        System.out.println(„Ich verbinde einen Videokanal für den Abonnenten“ + outputNumber );
    }
    @Override
    public void ring(int inputNumber) {
        System.out.println(„Sie haben einen eingehenden Videoanruf …“ + inputNumber);
    }
  }
Lassen Sie uns Objekte in der Methode erstellen main()und die Methode testen callAnotherUser:
AbstractPhone firstPhone = new ThomasEdisonPhone(1879);
AbstractPhone phone = new Phone(1984);
AbstractPhone videoPhone=new VideoPhone(2018);
User user = new User(„Andrei“);
user.callAnotherUser(224466,firstPhone);
// Drehen Sie den Knopf
// Sagen Sie mir die Nummer des Abonnenten, Sir
user.callAnotherUser(224466,phone);
//Rufnummer 224466
user.callAnotherUser(224466,videoPhone);
//Ich verbinde den Videokanal für Teilnehmer 224466
Durch den Aufruf derselben Methode für das Objekt usererhielten wir unterschiedliche Ergebnisse. Die Auswahl einer bestimmten Methodenimplementierung callinnerhalb einer Methode callAnotherUsererfolgte dynamisch basierend auf dem spezifischen Typ des aufrufenden Objekts während der Programmausführung. Dies ist der Hauptvorteil des Polymorphismus – die Wahl der Implementierung während der Programmausführung. In den obigen Beispielen für Telefonklassen haben wir das Überschreiben von Methoden verwendet, eine Technik, die die in der Basisklasse definierte Methodenimplementierung ändert, ohne die Methodensignatur zu ändern. Dabei handelt es sich im Wesentlichen um eine Methodenersetzung, und es ist die neue Methode, die in der Unterklasse definiert ist, die aufgerufen wird, wenn das Programm ausgeführt wird. Normalerweise wird beim Überschreiben einer Methode die Annotation verwendet @Override, die den Compiler anweist, die Signaturen der überschriebenen und überschreibenden Methoden zu überprüfen. Um sicherzustellen, dass der Stil Ihres Programms dem OOP-Konzept und den OOP-Java-Prinzipien entspricht, befolgen Sie daher die folgenden Tipps:
  • Heben Sie die Hauptmerkmale des Objekts hervor;
  • Hervorheben gemeinsamer Eigenschaften und Verhaltensweisen und Verwenden der Vererbung beim Erstellen von Objekten;
  • Verwenden Sie abstrakte Typen, um Objekte zu beschreiben.
  • Versuchen Sie, Methoden und Felder, die sich auf die interne Implementierung der Klasse beziehen, immer auszublenden.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION