Objektorientierung in JavaScript/Datenkapselung, Vererbung, Polymorphie/Vererbung

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>Javascript</language>
<html>
<head>
<style>
p.dotted {border-style: dotted; padding: 10px;}
</style>
</head>
</html>

==Das Klonen von Objekten==

Ein Prototyp dient als Vorlage für neue Objekte. Jedes bereits vorhandene Objekt kann ein Prototyp sein. Die neuen Objekte erhalten alle Eigenschaften und Methoden ihres Prototypen: Sie ''erben'' diese.
In JavaScript können Objekte mit der Anweisung <tt>Object.Create(prototype)</tt> erzeugt werden.

<p class=dotted>Ein Prototyp ist die Vorlage für ein neues Objekt. Das neue Objekt erbt alle Methoden und Attribute von seinem Prototypen.</p>

<code id="542717510qff3042016">
var altmetall = {
  masseInKg: 20,
  form : "Quader"
};
var neumetall = Object.create(altmetall);
neumetall.form = "Zylinder";
</code>
<run id="542717e5403042016">
neumetall.masseInKg;
</run>
Das neue Objekt hat die gleiche Masse wie das Altmetall, aber es hat eine andere Form. Objekte können die Eigenschaften und Funktionen ihrer Prototypen ändern oder neue hinzufügen.

Die Eigenschaft <tt>masseInKg</tt> des Objekts <tt>neumetall</tt> referenziert (verweist auf) die Eigenschaft von<tt>altmetall</tt>. Das heißt, es speichert den Wert der Variablen nicht selbst, sondern leitet den Aufruf an den Prototypen weiter.
<code id="5427181003042016">
altmetall.masseInKg= 50;
</code>
<run id="5426181003042016g">
neumetall.masseInKg;
</run>
Der Wert einer Eigenschaft eines Objekts ändert sich, wenn sich der Wert des Prototypen ändert.

Ob ein Objekt eine eigene Eigenschaft besitzt oder diese durch seinen Prototypen erlangt, kann man durch <tt>hasOwnProperty("property")</tt> überprüfen, welche alle Objekte von <tt>Object</tt> erben.

<run id="5427181403042016">
neumetall.hasOwnProperty("masseInKg") + "\n" + neumetall.hasOwnProperty("form");
//Masse wird geerbt, Form wird geändert
</run>

==Vererbung zwischen Klassen==
Durch die Vererbung zwischen Klassen können ''spezifische Klassen'' von ''allgemeinen Klassen'' abgeleitet werden. Es ist damit möglich, Klassenhierarchien zu konstruieren, in denen eine allgemeine Klasse (z.B. <tt>Lebewesen</tt>) immer weiter spezifiziert wird, bis man zu konkreten Ausprägungen wie dem <tt>LoxodontaAfricana</tt> kommt. In der allgemeinen Klasse können Methoden definiert werden, die alle Lebewesen haben, beispielsweise <tt>vererben()</tt> oder <tt>wachsen()</tt>. In einer ''Unterklasse'' von <tt>Lebewesen</tt> können dann die Merkmale von Säugetieren spezifiziert werden. In der ''konkreten Klasse'' <tt>HomoSapiens</tt> werden dann letztendlich die Merkmale und Funktionen eines Menschen beschrieben.
Die vererbende Klasse nennt man ''Ober-, Basis- oder Superklasse'', die erbende ''Unter- oder Subklasse''.
<p class=dotted>Durch Vererbung können spezifische von allgemeinen Klassen abgeleitet werden.</p>
===JavaScript===
Damit Klassen voneinander erben, muss die Eigenschaft <tt>prototype</tt> der Klasse ein Objekt der Oberklasse referenzieren.
<code id="5427182903042016">
function Lebewesen() {
  this.reizbarkeit = true;
  this.stoffUndEnergiewechsel = function() {
    return "Stoff- und Energiewechsel";
  };
}
function Saeugetier() {
  this.wirbelsaeule = true;
}
Saeugetier.prototype = new Lebewesen();
function Mensch(vorname, nachname, alter) {
  this.vorname = vorname;
  this.nachname = nachname;
  this.alter = alter;
  this.sprechen = function(aussage) {
    return aussage;
  };
}
Mensch.prototype = new Saeugetier();
</code>
<run id="5426184003042016">
var peter = new Mensch("Peter", "Maier", 54);
(peter.reizbarkeit + "\n" +
 peter.wirbelsaeule + "\n" +
 peter.vorname)
</run>
<tt>Peter</tt> kann Eigenschaften und Funktionen der Klassen <tt>Lebewesen</tt>, <tt>Säugetier</tt> und <tt>Mensch</tt> aufrufen. Er ist ein Objekt von all diesen Klassen.

Möchte man jetzt noch eine Klasse <tt>Person</tt> erstellen, kann diese von <tt>Mensch</tt> erben. <tt>Mensch</tt> hat aber einen parametrisierten Konstruktor. Damit die Klasse <tt>Person</tt> die Variablen, die auch die Oberklasse besitzt, nicht selbst speichern muss, werden diese an die Oberklasse übergeben.

<run id="5427190903042016" readonly nooutput>Person.prototype = new Mensch(vorname, nachname, alter);</run>
'''So nicht''', sondern so:

<code id="5427030420161840uh">
function Person(vorname, nachname, alter, steuerID) {
  Mensch.call(this, vorname, nachname, alter);
  this.steuerID = steuerID;
}
</code>
Die <tt>call</tt>-Methode der Oberklasse wird mit <tt>this</tt> sowie allen zu übergebenden Parametern aufgerufen. Danach sind die Werte in der Klasse <tt>Mensch</tt> gespeichert.

==Vererbung in UML==
[[Bild:Flogerlinghoff_Vererbung.png|center]]
Vererbung wird durch einen Pfeil von der erbenden zur Basisklasse dargestellt. Geerbte Methoden und Attribute werden nicht noch einmal mit aufgezählt.

==Aufgaben==
Erstelle eine geeignete Klassenhierarchie aus folgenden Klassen:
*SUV
*PKW
*Fahrzeug
*Zug
*Luftfahrzeug
*Schiff
*Flugzeug
*Landfahrzeug
*Wasserfahrzeug
*LKW
*Fahrrad
<code id="5427205403042016s">
</code>
<check>
var fahrzeug = new Fahrzeug();
var lafz = new Landfahrzeug();
var lufz = new Luftfahrzeug;
var wafz = new Wasserfahrzeug();
var pkw = new PKW();
var lkw = new LKW();
var suv = new SUV();
var zug = new Zug();
var fahrrad = new Fahrrad();
var schiff = new Schiff();
var flugzeug = new Flugzeug();

var checkA = lafz instanceof Fahrzeug;
var checkB = lufz instanceof Fahrzeug;
var checkC = wafz instanceof Fahrzeug;
var checkD = pkw instanceof Fahrzeug && pkw instanceof Landfahrzeug &&!(pkw instanceof Schiff);
var checkE = suv instanceof Landfahrzeug && suv instanceof PKW;
var checkF = zug instanceof Landfahrzeug;
var checkG = lkw instanceof Landfahrzeug;
var checkH = fahrrad instanceof Landfahrzeug;
var checkI = flugzeug instanceof Luftfahrzeug;
var checkJ = schiff instanceof Wasserfahrzeug;

return checkA && checkB && checkC && checkD && checkE && checkF && checkG && checkH && checkI && checkJ;
</check>
<run id="5426210303042016">
</run>