CodeGym /Java-Blog /Random-DE /Prinzipien von OOP
Autor
Milan Vucic
Programming Tutor at Codementor.io

Prinzipien von OOP

Veröffentlicht in der Gruppe Random-DE
Java ist eine objektorientierte Sprache. Das bedeutet, dass Sie Java-Programme unter Verwendung eines objektorientierten Paradigmas schreiben müssen. Und dieses Paradigma beinhaltet die Verwendung von Objekten und Klassen in Ihren Programmen. Versuchen wir anhand von Beispielen zu verstehen, was Klassen und Objekte sind und wie grundlegende OOP-Prinzipien (Abstraktion, Vererbung, Polymorphismus und Kapselung) in der Praxis angewendet werden.

Was ist ein Objekt?

Die Welt, in der wir leben, besteht aus Objekten. Wenn wir uns umschauen, können wir erkennen, dass wir von Häusern, Bäumen, Autos, Möbeln, Geschirr und Computern umgeben sind. Alle diese Dinge sind Objekte, und jedes 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, nutzen wir ein Auto. Wenn wir essen wollen, nutzen wir Geschirr. Und wenn wir uns ausruhen wollen, finden wir ein bequemes Sofa. Menschen sind es gewohnt, in Objekten zu denken, um Probleme im Alltag zu lösen. Dies ist ein Grund, warum Objekte in der Programmierung verwendet werden. Dieser Ansatz wird als objektorientierte Programmierung bezeichnet. Geben wir ein Beispiel. Stellen Sie sich vor, Sie haben ein neues Telefon entwickelt und möchten mit der Massenproduktion beginnen. Als Entwickler des Telefons wissen Sie, wozu es dient. wie es funktioniert und aus welchen Teilen es besteht (Gehäuse, Mikrofon, Lautsprecher, Kabel, Tasten usw.). Darüber hinaus wissen nur Sie, wie diese Teile miteinander verbunden werden. Aber Sie haben nicht vor, die Telefone selbst herzustellen – Sie haben ein ganzes Team von Arbeitern, die dafür zuständig sind. Damit Sie nicht immer wieder erklären müssen, wie die Teile des Telefons verbunden werden, und um sicherzustellen, dass alle Telefone auf die gleiche Weise hergestellt werden, müssen Sie vor Beginn der Produktion eine Zeichnung anfertigen, die den Aufbau des Telefons beschreibt. In OOP nennen wir eine solche Beschreibung, Zeichnung, ein solches Diagramm oder eine solche Vorlage eine Klasse. Es bildet die Grundlage für die Erstellung von Objekten, wenn das Programm ausgeführt wird. Eine Klasse ist eine Beschreibung von Objekten eines bestimmten Typs – wie eine gemeinsame Vorlage bestehend aus Feldern, Methoden und einem Konstruktor. Ein Objekt ist eine Instanz einer Klasse.

Abstraktion

Lassen Sie uns nun darüber nachdenken, wie wir von einem Objekt in der realen Welt zu einem Objekt in einem Programm gelangen können. Als Beispiel nehmen wir das Telefon. Dieses Kommunikationsmittel hat eine mehr als 100-jährige Geschichte. Das moderne Telefon ist ein viel komplexeres Gerät als sein Vorgänger aus dem 19. Jahrhundert. Wenn wir das Telefon benutzen, denken wir nicht über seine Organisation und die darin ablaufenden Prozesse nach. Wir nutzen einfach die von den Telefonentwicklern bereitgestellten Funktionen: Tasten oder einen Touchscreen, um eine Telefonnummer einzugeben und Anrufe zu tätigen. Eine der ersten Telefonschnittstellen war eine Kurbel, die zum Tätigen eines Anrufs gedreht werden musste. Das war natürlich nicht sehr praktisch. Aber es hat seine Funktion einwandfrei erfüllt. Wenn man die modernsten und die allerersten Telefone vergleicht, Sie erkennen sofort die wichtigsten Funktionen des Geräts aus dem späten 19. Jahrhundert und des modernen Smartphones. Dabei handelt es sich um die Fähigkeit, Anrufe zu tätigen und Anrufe entgegenzunehmen. Tatsächlich ist es das, was das Telefon zu einem Telefon macht und nicht zu etwas anderem. Jetzt habe ich gerade ein Prinzip von OOP angewendet: Identifizieren Sie die wichtigsten Eigenschaften und Informationen eines Objekts. Dieses Prinzip nennt man Abstraktion. In OOP kann Abstraktion auch als eine Methode zur Darstellung von Elementen einer realen Aufgabe als Objekte in einem Programm definiert werden. Abstraktion ist immer mit der Verallgemeinerung bestimmter Eigenschaften eines Objekts verbunden, daher geht es vor allem darum, im Kontext der jeweiligen Aufgabe sinnvolle Informationen von unbedeutenden zu trennen. Darüber hinaus kann es mehrere Abstraktionsebenen geben. Lassen' Versuchen wir, das Abstraktionsprinzip auf unsere Telefone anzuwenden. Zunächst identifizieren wir die gängigsten Telefontypen – von den allerersten Telefonen bis zu den heutigen. Wir könnten sie beispielsweise in Form des Diagramms in Abbildung 1 darstellen. Prinzipien von OOP - 2Mithilfe der Abstraktion können wir nun die allgemeinen Informationen in dieser Objekthierarchie identifizieren: das allgemeine abstrakte Objekt (Telefon), gemeinsame Merkmale des Telefons (z. B. Jahr seiner Erstellung) und die gemeinsame Schnittstelle (alle Telefone können Anrufe empfangen und tätigen). 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 outgoingNumber);
    public abstract void ring(int incomingNumber);
}
In einem Programm können wir mithilfe dieser abstrakten Klasse neue Telefontypen erstellen und andere Grundprinzipien von OOP anwenden, die wir weiter unten untersuchen werden.

Verkapselung

Mit der Abstraktion identifizieren wir, was allen Objekten gemeinsam ist. Aber jede Art von Telefon ist einzigartig und unterscheidet sich irgendwie von den anderen. Wie ziehen wir in einem Programm Grenzen und identifizieren diese Individualität? Wie stellen wir sicher, dass niemand versehentlich oder absichtlich unser Telefon kaputt macht oder versucht, ein Modell in ein anderes umzuwandeln? In der realen Welt liegt die Antwort auf der Hand: Sie müssen alle Teile in eine Telefonhülle stecken. Wenn Sie dies nicht tun und stattdessen alle Innenteile und Verbindungskabel des Telefons außen lassen, möchte ein neugieriger Experimentator unser Telefon auf jeden Fall „verbessern“. Um solche Manipulationen zu verhindern, wird beim Design und Betrieb eines Objekts das Prinzip der Kapselung angewendet. Dieses Prinzip besagt, dass die Attribute und das Verhalten eines Objekts in einer einzigen Klasse, dem Objekt, zusammengefasst werden. Die interne Implementierung von s bleibt dem Benutzer verborgen und es wird eine öffentliche Schnittstelle für die Arbeit mit dem Objekt bereitgestellt. Die Aufgabe des Programmierers besteht darin, zu bestimmen, welche Attribute und Methoden eines Objekts für den öffentlichen Zugriff verfügbar sein sollen und welche internen Implementierungsdetails nicht zugänglich sein sollten.

Kapselung und Zugangskontrolle

Angenommen, Informationen über ein Telefon (Produktionsjahr oder Herstellerlogo) werden bei der Herstellung auf der Rückseite eingraviert. Die Informationen (ihr Zustand) sind spezifisch für dieses bestimmte Modell. Wir können sagen, dass der Hersteller dafür gesorgt hat, dass diese Informationen unveränderlich sind – es ist unwahrscheinlich, dass irgendjemand auf die Idee kommt, die Gravur zu entfernen. In der Java-Welt beschreibt eine Klasse den Zustand zukünftiger Objekte mithilfe von Feldern und ihr Verhalten wird mithilfe von Methoden beschrieben. Der Zugriff auf den Status und das Verhalten eines Objekts wird mithilfe von Modifikatoren gesteuert, die auf Felder und Methoden angewendet werden: privat, geschützt, öffentlich und Standard. Wir haben beispielsweise entschieden, dass das Produktionsjahr, der Herstellername und eine der Methoden interne Implementierungsdetails der Klasse sind und nicht von anderen Objekten im Programm geändert werden können. In Code,

public class SomePhone {

    private int year;
    private String company;
    public SomePhone(int year, String company) {
        this.year = year;
        this.company = company;
    }
private void openConnection(){
    // findSwitch
    // openNewConnection...
}
public void call() {
    openConnection();
    System.out.println("Calling");
}

public void ring() {
    System.out.println("Ring-ring");
}

 }
Der private Modifikator ermöglicht den Zugriff auf die Felder und Methoden der Klasse nur innerhalb dieser Klasse. Das bedeutet, dass es nicht möglich ist, von außen auf private Felder zuzugreifen, da die privaten Methoden nicht aufgerufen werden können. Durch die Beschränkung des Zugriffs auf die openConnection- Methode haben wir auch die Möglichkeit, die interne Implementierung der Methode frei zu ändern, da garantiert ist, dass die Methode nicht von anderen Objekten verwendet wird oder deren Arbeit unterbricht. Um mit unserem Objekt zu arbeiten, lassen wir die Anruf- und Klingelmethoden mithilfe des öffentlichen Modifikators verfügbar. Zur Kapselung gehört auch die Bereitstellung öffentlicher Methoden für die Arbeit mit Objekten, denn wenn der Zugriff komplett verweigert würde, wäre dieser nutzlos.

Nachlass

Schauen wir uns noch einmal das Diagramm der Telefone an. Sie können sehen, dass es sich um eine Hierarchie handelt, in der ein Modell alle Funktionen der Modelle aufweist, die sich weiter oben in seinem Zweig befinden, und einige eigene hinzufügt. 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). Was wir hier haben, ist die Vererbung von Objekteigenschaften. In der Programmierung bedeutet Vererbung, vorhandene Klassen zu verwenden, um neue zu definieren. Betrachten wir ein Beispiel für die Verwendung der Vererbung zum Erstellen einer Smartphone-Klasse. Alle schnurlosen Telefone werden mit wiederaufladbaren Batterien betrieben, die eine bestimmte Akkulaufzeit haben. Dementsprechend fügen wir diese Eigenschaft zur Klasse der Schnurlostelefone hinzu:

public abstract class CordlessPhone extends AbstractPhone {

    private int hour;

    public CordlessPhone (int year, int hour) {
        super(year);
        this.hour = hour;
    }
    }
Mobiltelefone erben die Eigenschaften eines schnurlosen Telefons, und wir implementieren die Anruf- und Klingelmethoden in dieser Klasse:

public class CellPhone extends CordlessPhone {
    public CellPhone(int year, int hour) {
        super(year, hour);
    }

    @Override
    public void call(int outgoingNumber) {
        System.out.println("Calling " + outgoingNumber);
    }

    @Override
    public void ring(int incomingNumber) {
        System.out.println("Incoming call from " + incomingNumber);
    }
}
Und schließlich haben wir noch die Smartphone-Klasse, die im Gegensatz zu klassischen Mobiltelefonen über ein vollwertiges Betriebssystem verfügt. Sie können die Funktionalität Ihres Smartphones erweitern, indem Sie neue Programme hinzufügen, die auf dem Betriebssystem ausgeführt werden können. Im 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("Installing " + program + " for " + operationSystem);
}

}
Wie Sie sehen, haben wir ziemlich viel neuen Code zur Beschreibung der Smartphone- Klasse erstellt, aber wir haben eine neue Klasse mit neuer Funktionalität erhalten. Dieses OOP-Prinzip ermöglicht es, die Menge an benötigtem Java-Code deutlich zu reduzieren und somit dem Programmierer das Leben zu erleichtern.

Polymorphismus

Trotz der Unterschiede in Aussehen und Design verschiedener Telefontypen können wir ein gemeinsames Verhalten feststellen: Sie alle können Anrufe empfangen und tätigen und alle verfügen über relativ klare und einfache Bedienelemente. In Bezug auf die Programmierung können wir aufgrund des Abstraktionsprinzips (das uns bereits bekannt ist) sagen, dass Telefonobjekte eine gemeinsame Schnittstelle haben. Aus diesem Grund können Benutzer problemlos verschiedene Telefonmodelle verwenden, die über dieselben Bedienelemente (mechanische Tasten oder einen Touchscreen) verfügen, ohne sich mit den technischen Details des Geräts befassen zu müssen. So nutzen Sie ständig ein Mobiltelefon und können problemlos vom Festnetz Ihres Freundes aus telefonieren. Das Prinzip von OOP, das besagt, dass ein Programm Objekte mit einer gemeinsamen Schnittstelle verwenden kann, ohne Informationen über die interne Struktur des Objekts zu benötigen, wird Polymorphismus genannt. Lassen' Stellen Sie sich vor, wir benötigen unser Programm, um einen Benutzer zu beschreiben, der mit jedem Telefon einen anderen Benutzer anrufen kann. So können wir es machen:

public class User {
    private String name;

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

    public void callAnotherUser(int number, AbstractPhone phone){
// And here's polymorphism: using the AbstractPhone type in the code!
        phone.call(number);
    }
}
 }
Jetzt werden wir verschiedene Arten von Telefonen beschreiben. Eines der ersten Telefone:

public class ThomasEdisonPhone extends AbstractPhone {

public ThomasEdisonPhone(int year) {
    super(year);
}
    @Override
    public void call(int outgoingNumber) {
        System.out.println("Crank the handle");
        System.out.println("What number would you like to connect to?");
    }

    @Override
    public void ring(int incomingNumber) {
        System.out.println("The phone is ringing");
    }
}
Ein gewöhnliches Festnetztelefon:

public class Phone extends AbstractPhone {

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

    @Override
    public void call(int outgoingNumber) {
        System.out.println("Calling " + outgoingNumber);
    }

    @Override
    public void ring(int incomingNumber) {
        System.out.println("The phone is ringing");
    }
}
Und zum Schluss noch ein cooles Videotelefon:

public class VideoPhone extends AbstractPhone {

    public VideoPhone(int year) {
        super(year);
    }
    @Override
    public void call(int outgoingNumber) {
        System.out.println("Connecting video call to " + outgoingNumber);
    }
    @Override
    public void ring(int incomingNumber) {
        System.out.println("Incoming video call from " + incomingNumber);
    }
  }
Wir erstellen Objekte in der main()- Methode und testen die callAnotherUser()- Methode:

AbstractPhone firstPhone = new ThomasEdisonPhone(1879);
AbstractPhone phone = new Phone(1984);
AbstractPhone videoPhone=new VideoPhone(2018);
User user = new User("Jason");
user.callAnotherUser(224466, firstPhone);
// Crank the handle
// What number would you like to connect to?
user.callAnotherUser(224466, phone);
// Calling 224466
user.callAnotherUser(224466, videoPhone);
// Connecting video call to 224466
Der Aufruf derselben Methode für das Benutzerobjekt führt zu unterschiedlichen Ergebnissen. Eine bestimmte Implementierung der Aufrufmethode wird dynamisch innerhalb der Methode callAnotherUser() basierend auf dem spezifischen Objekttyp ausgewählt, der bei der Ausführung des Programms übergeben wird. Dies ist der Hauptvorteil des Polymorphismus – die Möglichkeit, zur Laufzeit eine Implementierung auszuwählen. In den oben angegebenen Beispielen für Telefonklassen haben wir das Überschreiben von Methoden verwendet – einen Trick, bei dem wir die Implementierung einer in der Basisklasse definierten Methode ändern, ohne die Methodensignatur zu ändern. Dies ersetzt im Wesentlichen die Methode: Die in der Unterklasse definierte neue Methode wird aufgerufen, wenn das Programm ausgeführt wird. Wenn wir eine Methode überschreiben, wird normalerweise @Override verwendetAnmerkung wird verwendet. Es weist den Compiler an, die Signaturen der überschriebenen und überschreibenden Methoden zu überprüfen. Um sicherzustellen, dass Ihre Java-Programme den Prinzipien von OOP entsprechen, befolgen Sie abschließend die folgenden Tipps:
  • die Hauptmerkmale eines Objekts identifizieren;
  • Identifizieren Sie gemeinsame Eigenschaften und Verhaltensweisen und nutzen Sie die Vererbung beim Erstellen von Klassen.
  • Verwenden Sie abstrakte Typen, um Objekte zu beschreiben.
  • Versuchen Sie, Methoden und Felder, die sich auf die interne Implementierung einer Klasse beziehen, immer auszublenden.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION