Computer und moderne Geräte

Die objektorientierte Programmierung (OOP) ist derzeit die beliebteste Programmiertechnologie. Die objektorientierte Programmierung ist eine Weiterentwicklung der strukturierten Programmiertechnologie, weist jedoch ihre eigenen charakteristischen Merkmale auf.

Die gebräuchlichsten objektorientierten visuellen Programmiersysteme sind Microsoft Visual Basic und Borland Delphi.

Bei der objektorientierten Programmierung geht es im Kern darum, Anwendungen aus Objekten zu erstellen, so wie Häuser aus Blöcken und verschiedenen Teilen gebaut werden. Manche Objekte müssen komplett selbst erstellt werden, andere können fertig aus verschiedenen Bibliotheken ausgeliehen werden.

Einen wichtigen Platz in der objektorientierten Programmiertechnologie nehmen ein Ereignis. Ereignisse können ein Mausklick auf ein Objekt, das Drücken einer bestimmten Taste, das Öffnen eines Dokuments usw. sein. Als Reaktion auf Ereignisse wird eine bestimmte Prozedur aufgerufen, die die Eigenschaften des Objekts ändern, seine Methoden aufrufen usw. können.

Objektorientierte Programmiersysteme verwenden typischerweise eine grafische Oberfläche, um den Programmierprozess zu visualisieren. Es wird möglich, Objekte zu erstellen und ihre Eigenschaften und ihr Verhalten mit der Maus festzulegen.

Ein Objekt verfügt einerseits über bestimmte Eigenschaften, die seinen Zustand zu einem bestimmten Zeitpunkt charakterisieren, andererseits sind Operationen möglich, die zu Änderungen der Eigenschaften führen.

Die Grundeinheit der objektorientierten Programmierung ist ein Objekt, das sowohl die es beschreibenden Daten (Eigenschaften) als auch die Mittel zur Verarbeitung dieser Daten (Methoden) kapselt.

Kapselung ist die Vereinigung der Eigenschaften eines Objekts und möglicher Operationen (Methoden) darauf.

Ein weiteres Prinzip, das OOP zugrunde liegt, ist die Möglichkeit, eine neue Klasse von Objekten zu erstellen, indem Eigenschaften und Methoden einer bereits vorhandenen Klasse geerbt werden.

Vererbung ist die Fähigkeit, eine Klasse von einer anderen abzuleiten und dabei alle Eigenschaften und Methoden der Vorgängerklasse (Vorläuferklasse, manchmal auch Superklasse genannt) beizubehalten und bei Bedarf neue Eigenschaften und Methoden hinzuzufügen.

Eine Reihe von Klassen, die durch Vererbung miteinander verbunden sind, wird als Hierarchie bezeichnet. Die Vererbung soll eine Eigenschaft der realen Welt wie die Hierarchie widerspiegeln.

Ein weiteres Prinzip von OOP ist das Prinzip des Polymorphismus.

Polymorphismus ist das Phänomen, bei dem eine Funktion (Methode) mit demselben Namen unterschiedlichem Programmcode (polymorpher Code) entspricht, je nachdem, welches Klassenobjekt beim Aufruf dieser Methode verwendet wird.

Polymorphismus wird durch die Änderung der Implementierung der Methode der Vorgängerklasse in der Nachfolgeklasse unter obligatorischer Beibehaltung der Methodensignatur gewährleistet. Dadurch wird sichergestellt, dass die Schnittstelle der Vorgängerklasse unverändert bleibt, und Sie können den Methodennamen im Code verschiedenen Klassen zuordnen – von dem Objekt, dessen Klasse der Aufruf erfolgt, wird von dieser Klasse die Methode mit dem angegebenen Namen übernommen. Dieser Mechanismus wird als dynamisches (oder spätes) Linken bezeichnet – im Gegensatz zum statischen (frühen) Linken, das zur Kompilierungszeit ausgeführt wird

Der objektorientierte Ansatz ermöglicht die Kombination eines statischen Modells, das die Eigenschaften eines Objekts beschreibt, und eines dynamischen Modells, das deren Änderungen beschreibt.

Bei diesem Ansatz ist der Zugriff auf die Änderung der Eigenschaften eines Objekts nur über Methoden möglich, die zu diesem Objekt gehören. Methoden „umgeben“ die Eigenschaften eines Objekts; Eigenschaften sollen in einem Objekt „gekapselt“ sein.

Einen zentralen Platz in der objektorientierten Programmierung nehmen daher Objekte ein, die die Eigenschaften eines Objekts und die darauf möglichen Operationen (Methoden) zu einem Ganzen vereinen (kapseln).

Objekte, die dieselbe Liste von Eigenschaften und Vorgängen kapseln, werden zu zusammengefasst Klassen. Jedes einzelne Objekt ist eine Instanz der Klasse. Instanzen einer Klasse können unterschiedliche Eigenschaftswerte haben.

Beispielsweise kann das Dateisystem eines Computers Hunderte oder Tausende von Dateien enthalten. Alle Dateien haben die gleichen Eigenschaften (Name, Position im Dateisystem usw.) und Operationen (Umbenennen, Verschieben oder Kopieren usw.) und bilden eine Klasse von Objekten Dateien.

Jede einzelne Datei ist eine Instanz dieser Klasse und verfügt über bestimmte Eigenschaftswerte (Name, Speicherort usw.).

Es kommt häufig vor, dass dieselben Operationen an Objekten verschiedener Klassen ausgeführt werden können. Die meisten Objektklassen in der Windows-Umgebung (Ordner, Dokumente, Symbole usw.) zeichnen sich auch durch eine Reihe gleicher Vorgänge (Umbenennen, Verschieben, Kopieren, Löschen usw.) aus. Diese Einheitlichkeit ist sehr benutzerfreundlich.

Es ist jedoch offensichtlich, dass die Mechanismen zur Implementierung dieser Operationen für verschiedene Klassen nicht gleich sind. Um beispielsweise einen Ordner zu kopieren, müssen Sie eine Reihe von Aktionen ausführen, um das Dateisystem zu ändern, und um ein Symbol zu kopieren, müssen Sie Änderungen am Dokument vornehmen. Diese Vorgänge werden von verschiedenen Programmen ausgeführt, die im Windows-Betriebssystem bzw. im Word-Texteditor verfügbar sind.

Auf diese Weise wird es verwirklicht Polymorphismus, diese. die Fähigkeit, dieselben Operationen an Objekten auszuführen, die zu verschiedenen Klassen gehören, und gleichzeitig individuelle Methoden für deren Implementierung für jede Klasse beizubehalten.

Es bilden sich Objekte mit denselben Eigenschaften- und Methodensätzen Objektklasse. In der Word-Anwendung gibt es also eine Objektklasse dokumentieren(Dokumente), das die folgenden Eigenschaften hat: Name(Name), Standorttion(FileNaine) usw. Objekte dieser Klasse verfügen auch über einen bestimmten Satz von Methoden, zum Beispiel: Öffnen eines DokumentsPolizist(Offen) Drucken von Dokumenten(Ausdrucken), Erhaltungdokumentieren(Speichern) usw.

Objekte in Anwendungen bilden eine Art Hierarchie. An der Spitze der Objekthierarchie steht Anwendung(Anwendung). Somit umfasst die Objekthierarchie der Word-Anwendung die folgenden Objekte: Anwendung(Anwendung), dokumentieren(Unterlagen), Dokumentfragment(Auswahl), Symbol(Charakter) usw.

Die Objekthierarchie der Excel-Anwendung umfasst die folgenden Objekte: Anwendung(Anwendung), Buch(Arbeitsmappe), Blatt(Arbeitsblatt) Zellbereich(Reichweite), Zellenka(Zelle) usw.

Eine vollständige Referenz auf ein Objekt besteht aus einer Reihe von Objektnamen, die nacheinander ineinander verschachtelt sind. Die Trennzeichen für Objektnamen in dieser Reihe sind Punkte; die Reihe beginnt mit dem Anwendungsobjekt der höchsten Ebene und endet mit dem Namen des für uns interessanten Objekts. Ein Link zum Dokument Пpo6a.doc in Word sieht beispielsweise so aus:

Anwendung. Unterlagen(„Ppo6a.doc“)

Damit ein Objekt eine Operation ausführen kann, muss eine Methode angegeben werden. Viele Methoden verfügen über Argumente, mit denen Sie Parameter für die auszuführenden Aktionen angeben können. Um Argumenten bestimmte Werte zuzuweisen, werden ein Doppelpunkt und ein Gleichheitszeichen verwendet und die Argumente werden durch ein Komma getrennt.

In Visual Basic werden Objekte nicht nur durch Eigenschaften und Methoden charakterisiert, sondern auch Veranstaltungen. Ein Ereignis ist eine von einem Objekt erkannte Aktion. Ein Ereignis kann vom Benutzer generiert werden (z. B. durch Drücken einer Maustaste oder einer Taste auf der Tastatur) oder das Ergebnis der Bedienung anderer Anwendungsobjekte sein.

Für jedes Ereignis können Sie eine Reaktion programmieren, also die Reaktion des Objekts auf das eingetretene Ereignis. Dieses Programm heißt Ereignisprozedur. Der Name einer Ereignisprozedur setzt sich üblicherweise aus dem Namen des Objekts und dem Namen des Ereignisses zusammen. Zum Beispiel für ein Schaltflächenobjekt mit dem Namen Befehl1 und Veranstaltungen Klicken(„Klick“, der auftritt, wenn wir den Mauszeiger über das Schaltflächenbild bewegen und die linke Maustaste drücken) erhält die Ereignisprozedur den Namen Befehl1_ Klicken.

An einer Ereignisprozedur können mehrere Objekte teilnehmen. Beispielsweise im oben genannten Verfahren Befehl1_ Klicken Team kann anwesend sein

Text1. Text= „Hallo!“,

als Ergebnis der Ausführung welches im „Textfeld“-Objekt mit dem Namen Text1 Es erscheint eine Zeile mit dem Wort „Hallo!“.

Mit der visuellen Programmierung, deren Methoden von der Visual Basic-Entwicklungsumgebung verwendet werden, können Sie eine grafische Oberfläche für entwickelte Anwendungen erstellen, die auf der Verwendung von Steuerelementen basiert, darunter Tasten(Befehlsschaltfläche), Kontrollkästchen(Kontrollkästchen) , Textfelder(Textfeld) Kombinationsfelder(ListBox) und andere. Diese Objekte, ihre Eigenschaften und Methoden werden im nächsten Abschnitt besprochen. Zunächst möchten wir nur darauf hinweisen, dass Steuerelemente am häufigsten dazu verwendet werden, Daten vom Benutzer zu empfangen und die Ergebnisse der Anwendung anzuzeigen. Somit sind Steuerelemente die Grundlage für den Aufbau der Benutzeroberfläche der Anwendung.

Die wichtigsten Objekte, die in der visuellen Programmierung verwendet werden, sind Formen(Bilden). Ein Formular ist ein Fenster, auf dem Steuerelemente platziert werden. Ein Formular ist auch ein Objekt, das durch eine Reihe von Eigenschaften und Methoden gekennzeichnet ist. Wie bei jedem anderen Objekt können Sie beispielsweise eine Ereignisprozedur für ein Formular schreiben Bilden_ Belastung, das beim Eintreten des Load-Ereignisses gestartet wird und infolgedessen die für den Betrieb der gestarteten Anwendung erforderlichen Anweisungen ausgeführt werden.

verwendete im Wesentlichen das Paradigma der präskriptiven Programmierung – das Ziel bestand darin, Code zu erstellen, der angemessen auf die Daten reagierte. Dieser Ansatz eignet sich gut zum Lösen kleinerer Probleme, führt jedoch beim Versuch, etwas zu erstellen, zu vielen hartnäckigen Problemen große Softwaresysteme.

Eine der Alternativen Direktive Programmierung Ist Objekt orientierte Programmierung, welche Wirklich hilft, die nichtlinear wachsende Komplexität von Programmen mit zunehmender Lautstärke zu bewältigen. Man sollte jedoch nicht zu dem Schluss kommen, dass die Verwendung des objektorientierten Programmierparadigmas eine erfolgreiche Lösung aller Probleme garantiert.

Um ein Profi im Programmieren zu werden, braucht man Talent, Kreativität, Intelligenz, Wissen, Logik, die Fähigkeit, Abstraktionen aufzubauen und zu nutzen und vor allem Erfahrung.

In diesem Abschnitt werden wir unsere Einführung in die Grundkonzepte der objektorientierten Programmierung fortsetzen, die wir im ersten Kapitel des Buches begonnen haben. Zunächst werden OOP-Konzepte besprochen, die verschiedenen Programmiersprachen gemeinsam sind, und anschließend deren Implementierung in der Java-Sprache.

Sie sollten sich darüber im Klaren sein, dass der Kurs über objektorientierte Programmierung für Bachelor-Studenten über ein ganzes Semester hinweg unterrichtet wird und das unten präsentierte Material daher nur eine sehr grundlegende Einführung in die Welt von OOP darstellt. Das Buch enthält eine viel umfassendere Behandlung vieler Probleme im Zusammenhang mit objektorientiertem Design, Engineering und Programmierung, und im dritten Kapitel des Buches finden Sie eine sehr klare Beschreibung aller objektorientierten Aspekte Java-Sprache.

Grundlegende OOP-Konzepte

Objektorientierte Programmierung oder OOP (objektorientierte Programmierung) - Programmiermethodik basiert auf der Darstellung eines Programms als Sammlung von Objekten, von denen jedes eine Implementierung eines bestimmten Typs ist, unter Verwendung eines Mechanismus Weiterleiten von Nachrichten und Kurse organisiert in Vererbungshierarchie.

Das zentrale Element von OOP ist die Abstraktion. Daten werden mithilfe der Abstraktion in Objekte umgewandelt, und die Verarbeitungssequenz dieser Daten wird zu einer Reihe von Nachrichten, die zwischen diesen Objekten übertragen werden. Jedes der Objekte hat sein eigenes, einzigartiges Verhalten. Objekte können als konkrete Einheiten behandelt werden, die auf Nachrichten reagieren, die ihnen befehlen, eine Aktion auszuführen.

OOP zeichnet sich durch folgende Prinzipien aus (nach Alan Kay):

  • alles ist ein Objekt;
  • Berechnungen werden durch Interaktion (Datenaustausch) zwischen Objekten durchgeführt, wobei ein Objekt die Ausführung einer Aktion durch ein anderes Objekt erfordert; Objekte interagieren, indem sie Nachrichten senden und empfangen; Eine Nachricht ist eine Aufforderung zur Ausführung einer Aktion, ergänzt durch eine Reihe von Argumenten, die bei der Ausführung der Aktion möglicherweise erforderlich sind.
  • Jedes Objekt hat ein unabhängiges Objekt Erinnerung, das aus anderen Objekten besteht;
  • Jedes Objekt ist ein Vertreter einer Klasse, die die allgemeinen Eigenschaften von Objekten eines bestimmten Typs ausdrückt.
  • im Unterricht eingestellt Funktionalität(Objektverhalten); somit können alle Objekte, die Instanzen derselben Klasse sind, dieselben Aktionen ausführen;
  • Klassen sind in einer einzigen Baumstruktur mit einer gemeinsamen Wurzel namens organisiert Vererbungshierarchie; Der mit Instanzen einer bestimmten Klasse verbundene Speicher und das Verhalten stehen automatisch jeder Klasse weiter unten im hierarchischen Baum zur Verfügung.

Definition 10.1. Abstraktion- eine Methode zur Lösung eines Problems, bei der Objekte verschiedener Art durch ein gemeinsames Konzept (Konzept) vereint werden und die gruppierten Einheiten dann als Elemente einer einzigen Kategorie betrachtet werden.

Abstraktion ermöglicht es Ihnen, die logische Bedeutung eines Programmfragments vom Problem seiner Implementierung zu trennen, indem Sie es teilen äußere Beschreibung(Schnittstelle) eines Objekts und seiner Interne Organisation(Implementierung).

Definition 10.2. Verkapselung- eine Technik, bei der Informationen, die aus Sicht der Schnittstelle des Objekts unbedeutend sind, darin verborgen werden.

Definition 10.3. Nachlass– eine Eigenschaft von Objekten, durch die Instanzen einer Klasse Zugriff auf die Daten und Methoden von Vorfahrenklassen erhalten, ohne diese neu zu definieren.

Durch Vererbung können verschiedene Datentypen denselben Code gemeinsam nutzen, was zu kleinerem Code und größerer Funktionalität führt.

Definition 10.4.

allgemeine Informationen

OOP ist ein Programmierstil, der in den 80er Jahren des 20. Jahrhunderts aufkam. Im Gegensatz zu prozeduralen Sprachen, in denen Daten und Anweisungen zu ihrer Verarbeitung getrennt vorliegen, werden diese Informationen bei der objektorientierten Programmierung zu einer einzigen Einheit zusammengefasst.

Grundprinzipien von OOP

Nachlass

Das zweite Prinzip von OOP, die Vererbung, ist die Fähigkeit einer Klasse, die Methoden einer anderen Klasse zu verwenden, ohne deren tatsächliche Implementierung zu wiederholen. Durch Vererbung können Sie Redundanzen im Quellcode beseitigen.

Polymorphismus

Ein weiteres Prinzip von OOP ist der Polymorphismus. Seine Verwendung bedeutet, dass Sie für die Manipulation von Objekten unterschiedlicher Komplexität eine Schnittstelle erstellen können, die unterschiedlich auf Ereignisse reagiert und gleichzeitig die zugewiesenen Aufgaben korrekt umsetzt.

OOP-Sprachen

OOP-Prinzipien werden in den gängigsten Programmiersprachen wie C++ und Java verwendet, in denen ein erheblicher Teil der Programme und Anwendungen entwickelt wird. Es gibt auch weniger verwendete OOP-Sprachen – Delphi, Object Pascal, Ruby und viele andere.

Kritik an OOP

Trotz überwiegend positiver Aussagen zu dieser Methodik werden die Prinzipien von OOP häufig kritisiert. Wie OOP hat es seine Nachteile.

Erstens die Schwierigkeit des Übergangs. Es wird ziemlich viel Zeit in Anspruch nehmen, die Prinzipien von OOP zu verstehen, insbesondere für Leute, die ausschließlich mit prozeduralen Programmiersprachen arbeiten.

Zweitens besteht der Nachteil in der komplexeren Dokumentation, da nicht nur Klassen und Objekte, sondern auch konkrete Fälle ihrer Implementierung beschrieben werden müssen.

Drittens kann eine übermäßige Universalität der Methoden dazu führen, dass der Quellcode und die entwickelten Programme mit Funktionen und Fähigkeiten überlastet werden, die im konkreten Fall nicht gefragt sind. Darüber hinaus stellen sie eine Ineffizienz bei der Speicherzuweisung fest. Unabhängig von der Meinung anderer wächst jedoch die Zahl der OOP-Programmierer ständig und die Sprachen selbst entwickeln sich rasant.

Hallo! Haben Sie sich jemals gefragt, warum Java so konzipiert ist? In dem Sinne, dass Sie darauf basierende Klassen erstellen – Objekte, Klassen haben Methoden usw. Aber warum ist die Struktur der Sprache so, dass Programme aus Klassen und Objekten bestehen und nicht aus etwas anderem? Warum war das Konzept „ ein Objekt” und in den Vordergrund stellen? Funktionieren alle Sprachen auf diese Weise und wenn nicht, welche Vorteile bietet es Java? Wie Sie sehen, gibt es viele Fragen :) Versuchen wir, jede davon in der heutigen Vorlesung zu beantworten.

Was ist objektorientierte Programmierung (OOP)?

Natürlich besteht Java aus einem bestimmten Grund aus Objekten und Klassen. Dies ist keine Laune seiner Schöpfer oder gar ihre Erfindung. Es gibt viele andere Sprachen, die auf Objekten basieren. Die erste derartige Sprache wurde genannt Simula, und es wurde bereits in den 1960er Jahren in Norwegen erfunden. Simula führte unter anderem die Konzepte von „ Klasse " Und " Methode ». Kristen Nygaard und Ole Johan Dahl – Schöpfer von Simula

Es scheint so, Simula- Nach Programmierstandards eine alte Sprache, aber ihre „Familienverbindung“ mit Java ist mit bloßem Auge sichtbar. Höchstwahrscheinlich können Sie den darauf geschriebenen Code leicht lesen und allgemein erklären, was er tut :) Begin Class Rectangle (Width, Height) ; Echte Breite, Höhe; Beginnen Sie mit realer Fläche, Umfang; Verfahrensaktualisierung; Anfangsbereich: = Breite * Höhe; OutText( „Rechteck wird aktualisiert, Fläche =“); OutFix(Bereich, 2, 8); OutImage; Umfang: = 2 * (Breite + Höhe); OutText( „Rechteck wird aktualisiert, Umfang =“); OutFix(Perimeter, 2, 8); OutImage; Ende des Updates; Aktualisieren; OutText("Rechteck erstellt: "); OutFix(Breite, 2, 6); OutFix(Höhe, 2, 6); OutImage; Ende des Rechtecks; Rechteckklasse ColoredRectangle(Color); Textfarbe; Beginn OutText( „ColoredRectangle erstellt, color =“); OutText(Farbe); OutImage; Ende von ColoredRectangle; Ref(Rechteck)Cr; Cr: - New ColoredRectangle(10, 20, "Green"); Ende; Das Codebeispiel ist dem Artikel Simula – 50 Jahre OOP entnommen. Wie Sie sehen, unterscheiden sich Java und sein Vorfahre nicht so sehr voneinander :) Dies liegt an der Tatsache, dass das Erscheinen von Simula die Geburt eines neuen Konzepts markierte – Objekt orientierte Programmierung. Wikipedia gibt die folgende Definition von OOP: Objektorientierte Programmierung (OOP) – eine Programmiermethodik, die auf der Darstellung eines Programms als Sammlung von Objekten basiert, von denen jedes eine Instanz einer bestimmten Klasse ist und die Klassen eine Vererbungshierarchie bilden. Meiner Meinung nach ist es sehr erfolgreich. Du hast vor kurzem angefangen, Java zu lernen, aber es gibt kaum Wörter darin, die dir unbekannt sind :) Heute OOP- die gebräuchlichste Programmiermethode. Neben Java werden sie in vielen beliebten Sprachen verwendet, von denen Sie vielleicht schon gehört haben. Dies sind C++ (es wird aktiv von Computerspielentwicklern verwendet), Objective-C und Swift (sie schreiben Programme für Apple-Geräte), Python (am gefragtesten im Bereich maschinelles Lernen), PHP (eine der beliebtesten Webentwicklungssprachen), JavaScript (einfacher gesagt, was sie nicht damit machen) und viele andere. Was sind eigentlich diese „Prinzipien“ von OOP? Lassen Sie uns es Ihnen genauer erzählen.

OOP-Prinzipien

Das sind die Grundlagen. 4 Hauptmerkmale, die zusammen das objektorientierte Programmierparadigma bilden. Sie zu verstehen ist der Schlüssel, um ein erfolgreicher Programmierer zu werden.

Prinzip 1. Vererbung.

Die gute Nachricht ist, dass Sie bereits mit einigen Prinzipien von OOP! vertraut sind. :) Wir sind in Vorlesungen bereits einige Male mit der Vererbung in Berührung gekommen und hatten Zeit, uns damit zu beschäftigen. Nachlass - ein Mechanismus, der es Ihnen ermöglicht, eine neue Klasse basierend auf einer vorhandenen (übergeordneten) Klasse zu beschreiben. In diesem Fall werden die Eigenschaften und Funktionalitäten der übergeordneten Klasse von der neuen Klasse übernommen. Warum ist eine Erbschaft notwendig und welche Vorteile bietet sie? Erstens: Code-Wiederverwendung. In übergeordneten Klassen beschriebene Felder und Methoden können in untergeordneten Klassen verwendet werden. Wenn alle Fahrzeugtypen 10 gemeinsame Felder und 5 identische Methoden haben, müssen Sie diese nur in die übergeordnete Klasse einfügen Auto. Sie können sie problemlos in abgeleiteten Klassen verwenden. Solide Vorteile: sowohl quantitativ (weniger Code) als auch qualitativ (Klassen werden viel einfacher). Gleichzeitig ist der Vererbungsmechanismus sehr flexibel und Sie können die fehlenden Funktionen in den Nachkommen separat hinzufügen (einige Felder oder klassenspezifisches Verhalten). Im Allgemeinen gilt wie im normalen Leben: Wir sind alle in mancher Hinsicht unseren Eltern ähnlich, unterscheiden uns aber in mancher Hinsicht von ihnen :)

Prinzip 2. Abstraktion

Das ist ein sehr einfaches Prinzip. Abstraktion bedeutet, die wichtigsten und bedeutsamsten Eigenschaften eines Objekts hervorzuheben und umgekehrt – sekundäre, unbedeutende Eigenschaften zu verwerfen. Erfinden wir das Rad nicht neu und erinnern uns an ein Beispiel aus einer alten Vorlesung über Unterricht. Nehmen wir an, wir erstellen ein Archiv mit den Mitarbeitern des Unternehmens. Um Mitarbeiterobjekte zu erstellen, haben wir die Employee-Klasse geschrieben. Welche Merkmale sind für die Beschreibung in der Firmenakte wichtig? Vollständiger Name, Geburtsdatum, Sozialversicherungsnummer, ZINN. Aber es ist unwahrscheinlich, dass wir auf einer Karte dieser Art seine Größe, Augen- und Haarfarbe benötigen. Das Unternehmen benötigt diese Informationen über den Mitarbeiter nicht. Daher werden wir für die Employee-Klasse die Variablen String name, int age, int socialInsuranceNumber und int taxNumber sowie abstrakte Informationen festlegen, die für uns nicht erforderlich sind, wie z. B. die Augenfarbe. Wenn wir aber für eine Agentur einen Katalog mit Fotomodellen erstellen, ändert sich die Situation dramatisch. Die Beschreibung des Fotomodells ist uns sehr wichtig Höhe, Augenfarbe Und Haarfarbe, und eine TIN-Nummer ist nicht erforderlich. Daher erstellen wir in der Model-Klasse die Variablen String height, String hair, String eyes.

Prinzip 3: Kapselung

Wir sind bereits darauf gestoßen. Kapselung in Java bedeutet, den Zugriff auf Daten und die Möglichkeit, diese zu ändern, einzuschränken. Wie Sie sehen, basiert es auf dem Wort „Kapsel“. In dieser „Kapsel“ verbergen wir einige für uns wichtige Daten, die niemand ändern soll. Ein einfaches Beispiel aus dem Leben. Sie haben einen Vor- und Nachnamen. Jeder, den Sie kennen, kennt sie. Sie haben jedoch keinen Zugriff darauf, Ihren Vor- und Nachnamen zu ändern. Man könnte sagen, dieser Vorgang ist im Passamt „gekapselt“: Nur dort können Sie Ihren Vor- und Nachnamen ändern, und nur Sie können es tun. Andere „Benutzer“ haben nur lesenden Zugriff auf Ihren Vor- und Nachnamen :) Ein weiteres Beispiel ist das Geld in Ihrer Wohnung. Es ist keine gute Idee, sie sichtbar mitten im Raum zu lassen. Jeder „Benutzer“ (eine Person, die zu Ihnen nach Hause kommt) kann die Anzahl Ihres Geldes ändern, d. h. Hole sie ab. Es ist besser, sie in einem Safe einzukapseln. Nur Sie haben Zugriff und nur mit einem speziellen Code. Offensichtliche Beispiele für Kapselung, mit denen Sie bereits gearbeitet haben, sind Zugriffsmodifikatoren ( Privat, öffentlich usw.) sowie Getter-Setter. Wenn das Altersfeld der Cat-Klasse nicht gekapselt ist, kann jeder schreiben: Cat. Alter = - 1000 ; Und der Kapselungsmechanismus ermöglicht es uns, das Altersfeld mit einer Setter-Methode zu schützen, mit der wir überprüfen können, dass das Alter keine negative Zahl sein darf.

Prinzip 4. Polymorphismus

Polymorphismus - Dies ist die Fähigkeit, mit mehreren Typen zu arbeiten, als wären sie derselbe Typ. In diesem Fall unterscheidet sich das Verhalten von Objekten je nach Typ, zu dem sie gehören. Klingt etwas kompliziert? Lass es uns jetzt herausfinden. Nehmen wir das einfachste Beispiel: Tiere. Erstellen wir eine Klasse „Animal“ mit einer einzigen Methode – „voice()“ – und zwei ihrer Nachkommen – „Cat“ und „Dog“. öffentliche Klasse Animal ( public void voice () ( System. out. println ("Voice!" ) ; ) ) public class Dog erweitert Animal ( @Override public void voice () ( System. out. println ("Woof-woof!" ) ; ) ) öffentliche Klasse Cat erweitert Animal ( @Override public void voice () ( System. out. println ("Meow!" ) ; ) ) Versuchen wir nun, eine Animal-Referenz zu erstellen und ihr ein Dog-Objekt zuzuweisen. öffentliche Klasse Main ( public static void main (String args) ( Animal dog = new Dog (); dog. voice () ; ) ) Welche Methode wird Ihrer Meinung nach aufgerufen? Animal.voice() oder Dog.voice() ? Die Klassenmethode wird aufgerufen Hund : Wow! Wir haben eine Tierreferenz erstellt, aber das Objekt verhält sich wie ein Hund. Bei Bedarf kann er sich wie eine Katze, ein Pferd oder ein anderes Tier verhalten. Die Hauptsache besteht darin, einem Objekt einer bestimmten Nachkommenklasse eine Referenz vom allgemeinen Typ Animal zuzuweisen. Das ist logisch, denn alle Hunde sind Tiere. Das haben wir gemeint, als wir sagten: „Objekte verhalten sich unterschiedlich, je nachdem, um welchen Typ es sich handelt.“ Wenn wir ein Cat-Objekt erstellen würden – public static void main (String args) ( Animal cat = new Cat (); cat. voice () ; ) die Methode voice() würde „ausgeben“ Miau!». Was bedeutet „die Fähigkeit, mit mehreren Typen zu arbeiten, als wären sie derselbe Typ“? Das geht auch ganz einfach. Stellen wir uns vor, wir gründen einen Friseursalon für Tiere. Unser Friseursalon muss in der Lage sein, allen Tieren die Haare zu schneiden, daher erstellen wir eine shear()-Methode mit einem Animal-Parameter – dem Tier, das wir schneiden werden. öffentliche Klasse AnimalBarbershop ( öffentliche Leere Schere (Tier Tier) ( System. out. println ( „Der Haarschnitt ist fertig!“); )) Und jetzt können wir sowohl Cat- als auch Dog-Objekte an die Schermethode übergeben! public static void main (String args) ( Cat cat = new Cat (); Dog dog = new Dog (); AnimalBarbershop barbershop = new AnimalBarbershop (); barbershop. shear (cat) ; barbershop. shear (dog) ; ) Hier wir Ein typisches Beispiel: Die Klasse „AnimalBarbershop“ behandelt die Typen „Katze“ und „Hund“, als wären sie vom gleichen Typ. Gleichzeitig haben Katze und Hund ein unterschiedliches Verhalten: Sie äußern sich unterschiedlich.

Gründe für die Entstehung von OOP

Warum ist dieses neue Programmierkonzept entstanden? OOP ? Programmierer verfügten über funktionierende Werkzeuge: prozedurale Sprachen zum Beispiel. Was hat sie dazu bewogen, etwas grundlegend Neues zu erfinden? Erstens die Kompliziertheit der Aufgaben, vor denen sie standen. Wenn vor 60 Jahren die Aufgabe eines Programmierers so aussah: „Berechnen Sie eine mathematische Gleichung so und so“, könnte es heute so klingen: „Implementieren Sie 7 verschiedene Enden für das Spiel S.T.A.L.K.E.R.“ abhängig davon, welche Entscheidungen der Benutzer in den Spielmomenten A, B, C, D, E, F und Kombinationen dieser Entscheidungen getroffen hat.“ Wie Sie sehen, sind die Aufgaben in den letzten Jahrzehnten deutlich komplexer geworden. Das bedeutet, dass die Datentypen komplexer geworden sind. Dies ist ein weiterer Grund für die Entstehung von OOP. Das Beispiel mit der Gleichung lässt sich leicht mit gewöhnlichen Grundelementen lösen, hier werden keine Objekte benötigt. Aber es wird schwierig sein, das Problem mit den Enden des Spiels überhaupt zu beschreiben, ohne einige von Ihnen erfundene Klassen zu verwenden. Aber gleichzeitig ist es ganz einfach, es in Klassen und Objekten zu beschreiben: Wir werden natürlich eine Klasse brauchen Ein Spiel, Klasse Stalker, Klasse Ende, Klasse Entscheidung des Spielers, Klasse GamingMoment usw. Das heißt, auch ohne mit der Lösung eines Problems zu beginnen, können wir uns leicht „Skizzen“ seiner Lösung in unserem Kopf vorstellen. Die zunehmende Komplexität von Problemen hat Programmierer gezwungen, das Problem in Teile zu unterteilen. Aber in der prozeduralen Programmierung war das nicht so einfach. Und sehr oft war das Programm ein „Baum“ aus einer Reihe von Zweigen mit allen möglichen Optionen für seinen Betrieb. Abhängig von bestimmten Bedingungen wurde das Programm entlang der einen oder anderen Verzweigung ausgeführt. Für kleine Programme war diese Option praktisch, aber die Aufteilung einer großen Aufgabe in Teile war sehr schwierig. Dieses Bedürfnis wurde zu einem weiteren Grund für die Entstehung von OOP. Dieses Konzept gab Programmierern die Möglichkeit, ein Programm in eine Reihe von „Modulen“ von Klassen zu unterteilen, von denen jedes seinen eigenen Teil der Arbeit erledigte. Alle miteinander interagierenden Objekte bilden die Arbeit unseres Programms. Darüber hinaus kann der von uns geschriebene Code an anderer Stelle im Programm wiederverwendet werden, was ebenfalls viel Zeit spart. Englische Version dieses Beitrags:

Wahrscheinlich die Hälfte der offenen Stellen (wenn nicht mehr) erfordern Kenntnisse und Verständnis von OOP. Ja, diese Methodik hat definitiv viele Programmierer fasziniert! Normalerweise erfordert das Verständnis von OOP Erfahrung, da es zu diesem Thema praktisch keine geeigneten und zugänglichen Materialien gibt. Und selbst wenn dies der Fall ist, ist es keineswegs sicher, dass die Leser darüber stolpern werden. Ich hoffe, dass ich die Prinzipien dieser wunderbaren Methodik, wie man so sagt, an meinen Fingern erklären kann.

Daher habe ich bereits zu Beginn des Artikels den Begriff „Methodik“ erwähnt. Wenn dieser Begriff auf die Programmierung angewendet wird, impliziert er das Vorhandensein einer Reihe von Möglichkeiten, Code zu organisieren und Methoden zu schreiben, anhand derer der Programmierer in der Lage sein wird, vollständig verwendbare Programme zu schreiben.

OOP (oder objektorientierte Programmierung) ist eine Methode zum Organisieren von Programmcode, bei der die Hauptbausteine ​​des Programms Objekte und Klassen sind und die Logik des Programms auf ihrer Interaktion basiert.


Über Objekte und Klassen

Klasse- Dies ist eine Datenstruktur, die vom Programmierer selbst erstellt werden kann. In OOP-Begriffen besteht eine Klasse aus Felder(in einfachen Worten - Variablen) und Methoden(in einfachen Worten - Funktionen). Und wie sich herausstellte, verleiht die Kombination von Daten und Funktionen für die Bearbeitung in einer Struktur eine unvorstellbare Leistungsfähigkeit. Ein Objekt ist eine bestimmte Instanz einer Klasse. In Anlehnung an die Analogie einer Klasse mit einer Datenstruktur ist ein Objekt eine bestimmte Datenstruktur, deren Feldern einige Werte zugewiesen sind. Lassen Sie es mich anhand eines Beispiels erklären:

Nehmen wir an, wir müssen ein Programm schreiben, das den Umfang und die Fläche eines Dreiecks berechnet, das durch zwei Seiten und den Winkel zwischen ihnen gegeben ist. Um ein solches Programm mit OOP zu schreiben, müssen wir eine Klasse (d. h. eine Struktur) Triangle erstellen. Die Triangle-Klasse speichert drei Felder (drei Variablen): Seite A, Seite B, den Winkel zwischen ihnen; und zwei Methoden (zwei Funktionen): Berechnen Sie den Umfang, berechnen Sie die Fläche. Mit dieser Klasse können wir jedes Dreieck beschreiben und den Umfang und die Fläche berechnen. Daher wird ein bestimmtes Dreieck mit bestimmten Seiten und einem Winkel zwischen ihnen als Instanz der Triangle-Klasse bezeichnet. Somit ist eine Klasse eine Vorlage und eine Instanz eine konkrete Implementierung der Vorlage. Aber Instanzen sind Objekte, also spezifische Elemente, die bestimmte Werte speichern.

Eine der am weitesten verbreiteten objektorientierten Programmiersprachen ist Java. Da kommt man ohne den Einsatz von Objekten einfach nicht aus. So würde der Code für eine Klasse, die ein Dreieck in dieser Sprache beschreibt, aussehen:

/** * Dreiecksklasse. */ class Triangle ( /** * Spezielle Methode namens Klassenkonstruktor. * Nimmt drei Parameter als Eingabe: * Länge der Seite A, Länge der Seite B, * Winkel zwischen diesen Seiten (in Grad) */ Triangle(double sideA, double sideB , double angleAB) ( this.sideA = sideA; this.sideB = sideB; this.angleAB = angleAB; ) double sideA; //Klassenfeld, speichert den Wert der Seite A im beschriebenen Dreieck double sideB; //Klassenfeld , speichert den Wert der Seite B im beschriebenen Dreieck double angleAB; //Klassenfeld speichert den Winkel (in Grad) zwischen zwei Seiten im beschriebenen Dreieck /** * Klassenmethode, die die Fläche des Dreiecks berechnet */ double getSquare() ( double quadrat = this.sideA * this .sideB * Math.sin(this.angleAB * Math.PI / 180); return quadrat; ) /** * Klassenmethode, die den Umfang eines Dreiecks berechnet */ double getPerimeter() ( double sideC = Math.sqrt(Math.pow (this.sideA, 2) + Math.pow(this.sideB, 2) - 2 * this.sideA * this.sideB * Math.cos(this. angleAB * Math.PI / 180)); double perimeter = this.sideA + this.sideB + sideC; Rücklaufumfang; ) )

Wenn wir den folgenden Code innerhalb der Klasse hinzufügen:

/** * Hier läuft das Programm */ public static void main(String args) ( //Werte 5, 17, 35 gehen in den Triangle-Klassenkonstruktor Triangle Triangle1 = new Triangle(5, 17, 35 ); System.out .println("Fläche von Dreieck1: "+triangle1.getSquare()); System.out.println("Umfang von Dreieck1: "+triangle1.getPerimeter()); //Werte 6 , 8, 60 gehe zum Triangle-Klassenkonstruktor Triangle Triangle2 = new Triangle(6, 8, 60); System.out.println("Area of ​​​​triangle1: "+triangle2.getSquare()); System.out.println ("Umfang von Dreieck1: "+triangle2.getPerimeter()); )

dann kann das Programm bereits zur Ausführung gestartet werden. Dies ist eine Funktion der Java-Sprache. Wenn die Klasse eine solche Methode hat

Public static void main(String args)

dann kann diese Klasse ausgeführt werden. Schauen wir uns den Code genauer an. Beginnen wir mit der Zeile

Dreieck Dreieck1 = neues Dreieck(5, 17, 35);

Hier erstellen wir eine Instanz von Triangle1 der Triangle-Klasse und geben ihr sofort die Parameter der Seiten und den Winkel zwischen ihnen. Gleichzeitig wird eine spezielle Methode namens Konstruktor aufgerufen und füllt die Felder des Objekts mit den an den Konstruktor übergebenen Werten. Nun, was ist mit den Zeilen?

System.out.println("Fläche von Dreieck1: "+triangle1.getSquare()); System.out.println("Umfang von Dreieck1: "+triangle1.getPerimeter());

Geben Sie die berechnete Fläche des Dreiecks und seinen Umfang an die Konsole aus.

Das Gleiche passiert für die zweite Instanz der Triangle-Klasse.

Das Verständnis der Essenz von Klassen und der Konstruktion konkreter Objekte ist ein sicherer erster Schritt zum Verständnis der OOP-Methodik.

Noch einmal das Wichtigste:

OOP- Dies ist eine Möglichkeit, Programmcode zu organisieren;

Klasse- Dies ist eine benutzerdefinierte Datenstruktur, die Daten und Funktionen für die Arbeit mit ihnen (Klassenfelder und Klassenmethoden) zusammenfasst.

Ein Objekt ist eine bestimmte Instanz einer Klasse, deren Felder bestimmte Werte erhalten.


Drei magische Worte

OOP umfasst drei Schlüsselansätze: Vererbung, Kapselung und Polymorphismus. Zunächst gebe ich Definitionen aus Wikipedia:

Kapselung ist eine Systemeigenschaft, die es Ihnen ermöglicht, Daten und Methoden, die mit ihnen arbeiten, in einer Klasse zu kombinieren. Einige Sprachen (z. B. C++) setzen Kapselung mit Verstecken gleich, aber die meisten (Smalltalk, Eiffel, OCaml) unterscheiden zwischen diesen Konzepten.

Vererbung ist eine Systemeigenschaft, mit der Sie eine neue Klasse basierend auf einer vorhandenen Klasse mit teilweise oder vollständig übernommener Funktionalität beschreiben können. Die Klasse, von der die Vererbung abgeleitet wird, wird Basis-, Eltern- oder Oberklasse genannt. Eine neue Klasse ist eine Nachkommen-, Erb-, Kind- oder abgeleitete Klasse.

Polymorphismus ist eine Systemeigenschaft, die es Ihnen ermöglicht, Objekte mit derselben Schnittstelle zu verwenden, ohne Informationen über den Typ und die interne Struktur des Objekts zu benötigen.

Es ist ziemlich schwierig zu verstehen, was all diese Definitionen tatsächlich bedeuten. In Fachbüchern, die sich mit diesem Thema befassen, ist jeder Definition oft ein ganzes Kapitel, mindestens aber ein Absatz gewidmet. Allerdings ist die Essenz dessen, was ein Programmierer verstehen und für immer in seinem Gehirn einprägen muss, sehr gering.
Und als Beispiel für die Analyse verwenden wir Figuren in einer Ebene. Aus der Schulgeometrie wissen wir, dass es für alle auf einer Ebene beschriebenen Figuren möglich ist, den Umfang und die Fläche zu berechnen. Für einen Punkt sind beispielsweise beide Parameter gleich Null. Für ein Segment können wir nur den Umfang berechnen. Und für ein Quadrat, ein Rechteck oder ein Dreieck – beides. Jetzt werden wir diese Aufgabe in OOP-Begriffen beschreiben. Es ist auch nützlich, die Argumentationskette zu verstehen, die zur Klassenhierarchie führt, die wiederum im Arbeitscode verkörpert ist. Gehen:


Ein Punkt ist also die kleinste geometrische Figur, die die Grundlage aller anderen Konstruktionen (Figuren) ist. Daher wurde der Punkt als Basis-Elternklasse gewählt. Schreiben wir eine Punktklasse in Java:

/** * Punktklasse. Basisklasse */ class Point ( /** * Leerer Konstruktor */ Point() () /** * Klassenmethode, die die Fläche einer Figur berechnet */ double getSquare() ( return 0; ) /** * Klassenmethode, die den Umfang der Figur berechnet */ double getPerimeter() ( return 0; ) /** * Klassenmethode, die eine Beschreibung der Figur zurückgibt */ String getDescription() ( return "Point"; ) )

Die resultierende Point-Klasse hat einen leeren Konstruktor, da wir in diesem Beispiel ohne spezifische Koordinaten arbeiten und nur mit Parametern und Seitenwerten arbeiten. Da der Punkt keine Seiten hat, müssen ihm keine Parameter übergeben werden. Beachten Sie außerdem, dass die Klasse über die Methoden Point::getSquare() und Point::getPerimeter() zur Berechnung von Fläche und Umfang verfügt. Beide geben 0 zurück. Für einen Punkt ist dies logisch.


Da unser Punkt die Basis aller anderen Figuren ist, erben wir die Klassen dieser anderen Figuren von der Point-Klasse. Beschreiben wir die Klasse eines Segments, die von der Klasse eines Punktes geerbt wurde:

/** * Klasse Liniensegment */ Klasse LineSegment erweitert Point ( LineSegment(double segmentLength) ( this.segmentLength = segmentLength; ) double segmentLength; // Länge der Linie /** * Überschriebene Klassenmethode, die die Fläche von berechnet die Zeile */ double getSquare( ) ( return 0; ) /** * Überschriebene Klassenmethode, die den Umfang eines Segments berechnet */ double getPerimeter() ( return this.segmentLength; ) String getDescription() ( return „Segmentlänge: " + this.segmentLength; ) )

Die Klasse LineSegment erweitert Point

bedeutet, dass die LineSegment-Klasse von der Point-Klasse erbt. Die Methoden LineSegment::getSquare() und LineSegment::getPerimeter() überschreiben die entsprechenden Basisklassenmethoden. Die Fläche eines Segments ist immer Null und die Fläche des Umfangs ist gleich der Länge dieses Segments.

Nun beschreiben wir, ähnlich wie die Segmentklasse, die Dreiecksklasse (die auch von der Punktklasse erbt):

/** * Dreiecksklasse. */ Klasse Dreieck erweitert Punkt ( /** * Klassenkonstruktor. Nimmt drei Parameter als Eingabe: * Länge von Seite A, Länge von Seite B, * Winkel zwischen diesen Seiten (in Grad) */ Dreieck(doppelte SeiteA, doppelte SeiteB, double angleAB ) ( this.sideA = sideA; this.sideB = sideB; this.angleAB = angleAB; ) double sideA; //Klassenfeld, speichert den Wert der Seite A im beschriebenen Dreieck double sideB; //Klassenfeld, speichert der Wert der Seite B im beschriebenen Dreieck Dreieck double angleAB; //Klassenfeld, das den Winkel (in Grad) zwischen zwei Seiten im beschriebenen Dreieck speichert /** *Klassenmethode, die die Fläche eines Dreiecks berechnet */double getSquare() ( double quadrat = (this.sideA * this.sideB * Math.sin(this.angleAB * Math.PI / 180))/2; return quadrat; ) /** * Klassenmethode, die den Umfang von a berechnet Dreieck */ double getPerimeter() ( double sideC = Math.sqrt(Math. pow(this.sideA, 2) + Math.pow(this.sideB, 2) - 2 * this.sideA * this.sideB * Math.cos (this.angleAB * Math.PI / 180)); double perimeter = this.sideA + this.sideB + sideC; Rücklaufumfang; ) String getDescription() ( return „Dreieck mit Seiten: „ + this.sideA +“, „ + this.sideB + „ und Winkel zwischen ihnen: „ + this.angleAB; ) )

Hier gibt es nichts Neues. Außerdem überschreiben die Methoden Triangle::getSquare() und Triangle::getPerimeter() die entsprechenden Methoden der Basisklasse.
Nun, tatsächlich genau der Code, der die Magie des Polymorphismus zeigt und die Leistungsfähigkeit von OOP offenbart:

Klasse Main ( /** * Hier wird das Programm ausgeführt */ public static void main(String args) ( //ArrayList – Dies ist eine spezielle Datenstruktur in Java //, mit der Sie Objekte eines bestimmten Typs in einer speichern können array. ArrayList Figures = new ArrayList (); //Füge drei verschiedene Objekte zum Figures-Array hinzu Figures.add(new Point()); Figures.add(new LineSegment(133)); Figures.add(new Triangle(10, 17, 55)); für ( int i = 0;i

Wir haben ein Array von Objekten der Point-Klasse erstellt, und da die Klassen LineSegment und Triangle von der Point-Klasse erben, können wir sie in diesem Array platzieren. Es stellt sich heraus, dass wir jede Figur im Figures-Array als Objekt der Point-Klasse betrachten können. Das ist Polymorphismus: Es ist nicht bekannt, zu welcher Klasse die Objekte im Zahlen-Array gehören, aber da alle Objekte in diesem Array zur gleichen Basisklasse Point gehören, sind alle Methoden, die auf die Point-Klasse anwendbar sind, auch anwendbar zu seinen Nachkommenklassen.


Nun zur Kapselung. Die Tatsache, dass wir die Parameter einer Figur und Methoden zur Berechnung von Fläche und Umfang in einer Klasse zusammengefasst haben, ist Kapselung; wir haben die Figuren in separate Klassen gekapselt. Die Tatsache, dass wir in der Klasse eine spezielle Methode zur Berechnung des Umfangs verwenden, ist eine Kapselung; wir haben die Berechnung des Umfangs in der Methode getPerimiter() gekapselt. Mit anderen Worten, die Kapselung verbirgt die Implementierung (vielleicht die kürzeste und gleichzeitig umfangreichste Definition der Kapselung).


Vollständiger Beispielcode:

Importieren Sie java.util.ArrayList; class Main ( /** * Hier wird das Programm ausgeführt */ public static void main(String args) ( //ArrayList ist eine spezielle Datenstruktur in Java //, mit der Sie Objekte eines bestimmten Typs in einem Array speichern können. ArrayList Figures = new ArrayList (); //Füge drei verschiedene Objekte zum Figures-Array hinzu Figures.add(new Point()); Figures.add(new LineSegment(133)); Figures.add(new Triangle(10, 17, 55)); für ( int i = 0;i

Wenn Sie einen Fehler bemerken, wählen Sie einen Textabschnitt aus und drücken Sie Strg+Eingabetaste
AKTIE:
Computer und moderne Geräte