If you're seeing this message, it means we're having trouble loading external resources on our website.

Wenn du hinter einem Webfilter bist, stelle sicher, dass die Domänen *. kastatic.org und *. kasandbox.org nicht blockiert sind.

Hauptinhalt

Wiederholung: Objektorientiertes Design

Dies ist eine Wiederholung von dem, was wir in diesem Tutorial über objektorientiertes Design gelernt haben.
Wenn wir Programme erstellen, wollen wir oft viele verschiedene Objekte mit ähnlichen Eigenschaften erstellen. Wie z. B. viele Katzen, welche alle eine etwas andere Fell-Farbe und Größe haben. Oder viele Buttons mit verschiedenen Beschriftungen und Positionen. Wir wollen die Möglichkeit haben zu sagen "Normalerweise sieht eine Katze so aus" und dann sagen "und diese, diese und diese Katze haben gewisse Eigenschaften gleich und ein paar andere ganz anders". In diesem Fall verwenden wir objektorientiertes Design, um Objekttypen zu definieren und Instanzen dieser Objekte zu verwenden.
Um in JavaScript einen Objekttypen zu definieren, müssen wir zuerst den "Konstruktor" deklarieren. Dies ist eine Funktion, welche wir immer dann verwenden, wenn wir eine neue Instanz eines Objekttypes erstellen wollen. Hier der Konstruktor für den Objekttyp Book, welcher ein Buch darstellt:
var Book = function(title, author, numPages) {
  this.title = title;
  this.author = author;
  this.numPages = numPages;
  this.currentPage = 0;
};
Die Funktion akzeptiert Parameter für die Aspekte, welche für jedes Buch anders sein können, den Titel, Autor und die Anzahl Seiten (title, author, numPages). Dann initialisiert sie die Eigenschaften des Objektes mit den Werten dieser Parameter, indem sie das Schlüsselwort this verwendet. Wenn wir this in einem Objekt verwenden, dann beziehen wir uns auf die aktuelle Instanz eines Objektes. Das Objekt referenziert sich selbst. Wir müssen diese Eigenschaften auf this speichern, damit wir später wieder auf diese zugreifen können.
Um eine Instanz des Objektes Book zu erstellen, deklarieren wir eine neue Variable, um diese zu speichern. Dann benutzen wir das Schlüsselwort new gefolgt von einem Aufruf des Konstruktors und übergeben diesem die erwarteten Parameter für die Eigenschaften des neuen Objektes.
var book = new Book("Robot Dreams", "Isaac Asimov", 320);
Mit der Punktnotation können wir danach auf die Eigenschaften des neuen Objektes zugreifen:
println("I loved reading " + book.title); // I loved reading Robot Dreams
println(book.author + " is my fav author"); // "Isaac Asimov" is my fav author
Wir wollen dies nun kurz genauer anschauen. Was wäre denn passiert, wenn wir unseren Konstruktor nicht korrekt implementiert hätten:
var Book = function(title, author, numPages) {
};
var book = new Book("Little Brother", "Cory Doctorow", 380);
println("I loved reading " + book.title); // I loved reading undefined
println(book.author + " is my fav author"); // undefined is my favorite author
Wenn wir die Parameter dem Konstruktor übergeben, aber darin diese nicht explizit auf dem Objekt this speichern, dann können wir später nicht mehr auf diese zugreifen! Das Objekt vergisst diese, sobald der Konstruktor ausgeführt ist.
Wenn wir Objekttypen definieren, wollen wir oft Eigenschaften und das Verhalten mit ihnen verknüpfen. Zum Beispiel sollen alle unsere Katzenobjekte miauen() und fressen() können. Daher müssen wir Funktionen mit unseren Objekttypen verbinden. Dies machen wir, indem wir diese auf dem sogenannten Prototyp eines Objektes definieren:
Book.prototype.readItAll = function() {
  this.currentPage = this.numPages;
  println("You read " + this.numPages + " pages!");
};
Dies ist genau gleich, wie wir auch sonst eine Funktion deklarieren. Aber anstatt diese global zu deklarieren, deklarieren wir sie auf dem Prototypen von Book. So weiß JavaScript, dass diese Funktion auf Objekten des Typs Book aufgerufen werden kann und dass diese Funktion Zugriff auf this des Objektes hat, für welches sie aufgerufen wurde.
So eine Funktion nennen wir, nun da sie zu einem Objekt gehört, Methode. Wir können sie folgendermaßen aufrufen:
var book = new Book("Animal Farm", "George Orwell", 112);
book.readItAll(); // You read 112 pages!
Beachte, mit objektorientiertem Design wollen wir es uns einfach machen, mehrere verwandte Objekte (Objektinstanzen) zu erstellen. Schauen wir uns an, wie der Code dazu aussieht:
var pirate = new Book("Pirate Cinema", "Cory Doctorow", 384);
var giver = new Book("The Giver", "Lois Lowry", 179);
var tuck = new Book("Tuck Everlasting", "Natalie Babbit", 144);

pirate.readItAll(); // Du hast 384 Seiten gelesen!
giver.readItAll(); // Du hast 179 Seiten gelesen!
tuck.readItAll(); // Du hast 144 Seiten gelesen!
Mit diesem kurzen Stück Code erstellen wir drei Instanzen von Book. Diese haben alle die gleichen Eigenschaften, welche aber trotzdem unterschiedlich sind. Schön!
Nun, wenn du dir aber die reale Welt anschaust, dann sind Katzen und Hunde verschiedene Objekte. Daher würdest du wohl beim Programmieren einer Katze und eines Hundes unterschiedliche Objekttypen deklarieren. Eine Katze würde miauen() und ein Hund würde bellen(). Aber beide sind sich trotzdem ähnlich, denn beide können fressen() und haben ein Alter und ein Geburtsdatum und ein Todesdatum. Beide sind Säugetiere. Dies bedeutet, dass sie vieles gemeinsam haben, obwohl sie unterschiedliche Tiere sind.
In diesem Fall verwenden wir die Idee der Objektvererbung. Ein Objekttyp kann Eigenschaften und Verhalten (Methoden) an abgeleitete Objekttypen vererben. Die abgeleiteten Objekte können aber weiterhin ihre eigenen Eigenschaften und Methoden hinzufügen. All die Katzen und Hunde können von Säugetiere abgeleitet werden. So müssten sie die Methode fressen() nicht neu erfinden. Aber wie machen wir dies in JavaScript?
Gehen wir zurück zu unserem Beispiel mit Büchern und sagen wir, dass Book der zugrundeliegende Objekttyp ist und wir die Objekttypen Paperback und EBook davon ableiten.
Ein Taschenbuch (Paperback) ist ähnlich wie ein Buch, hat aber zumindest in unserem Programm einen Unterschied: Es hat ein Titelbild. Wegen dieser zusätzlichen Information muss unser Konstruktor nun vier Parameter akzeptieren.
var PaperBack = function(title, author, numPages, cover) {
  // ...
}
Wir wollen nun aber nicht all den Code aus dem Konstruktor vonBook wiederholen. Wir wollen den Vorteil, dass dieser Code gleich ist, wahrnehmen. Wir können den Konstruktor von Book aus dem Konstruktor von PaperBack aufrufen und ihm die notwendigen drei Parameter übergeben.
var PaperBack = function(title, author, numPages, cover) {
  Book.call(this, title, author, numPages);
  // ...
};
Wir müssen aber immer noch die Eigenschaft cover im Objekt speichern. Wir brauchen dafür eine zusätzliche Zeile:
var PaperBack = function(title, author, numPages, cover) {
  Book.call(this, title, author, numPages);
  this.cover = cover;
};
Nun da wir einen Konstruktor für unser PaperBack haben, der uns hilft die Eigenschaften von Book wiederzuverwenden, wollen wir nun aber auch die Methoden an PaperBack vererben. Und so sagen wir dem Programm, dass der Prototyp von PaperBack vom Prototypen von Book abgeleitet werden soll:
PaperBack.prototype = Object.create(Book.prototype);
Vielleicht wollen wir auch Taschenbuch-spezifische Verhalten, wie die Möglichkeit, es zu verbrennen, definieren. Dies machen wir, indem wir zusätzliche Funktionen auf dem Prototypen nach der Zeile oben definieren:
PaperBack.prototype.burn = function() {
  println("Omg, du hast alle " + this.numPages + " Seiten verbrannt");
  this.numPages = 0;
};
Und jetzt können wir ein neues Taschenbuch erstellen, es lesen und auch verbrennen (burn)!
var calvin = new PaperBack("The Essential Calvin & Hobbes", "Bill Watterson", 256, "http://ecx.images-amazon.com/images/I/61M41hxr0zL.jpg");

calvin.readItAll(); // Du hast 256 Seiten gelesen!
calvin.burn(); // Wow! du hast alle 256 Seiten verbrannt!
(Gut, wir werden es nicht wirklich verbrennen, da es ein großartiges Buch ist, aber vielleicht dann, wenn wir einmal in einer Eisspalte feststecken und uns verzweifelt nach Wärme sehnen.)
Und nun versehst du, wie man objektorientiertes Design in JavaScript benutzt, um für deine Programme komplexe Daten und Modelle zu erstellen, um die Welt um dich herum abzubilden.