OOP mit JavaScript
(Unterschied zwischen Versionen)
(→Methoden) |
(→Vererbung) |
||
Zeile 106: | Zeile 106: | ||
Mit JavaScript ist es möglich, alle Methoden und Attribute einer Klasse an den prototype einer anderen Klasse zu übergeben: | Mit JavaScript ist es möglich, alle Methoden und Attribute einer Klasse an den prototype einer anderen Klasse zu übergeben: | ||
<pre> | <pre> | ||
- | Point3D.prototype = | + | Point3D.prototype = Point2D.prototype; |
</pre> | </pre> | ||
+ | '''Hinweise:''' Die in der Korrektur | ||
Ohne weiteres Zutun hat man nun zweite Klasse, die eine exakte Kopie der ersten darstellt. Nun kann der prototype der zweiten Klasse beliebig verändert werden, ohne dass dies Auswirkungen auf die erste Klasse hätte: | Ohne weiteres Zutun hat man nun zweite Klasse, die eine exakte Kopie der ersten darstellt. Nun kann der prototype der zweiten Klasse beliebig verändert werden, ohne dass dies Auswirkungen auf die erste Klasse hätte: | ||
<pre> | <pre> | ||
Zeile 123: | Zeile 124: | ||
} | } | ||
- | Point3D.prototype = | + | Point3D.prototype = Point2D.prototype; |
function Point3D( x, y, z ) | function Point3D( x, y, z ) |
Version vom 14:24, 7. Sep. 2010
Inhaltsverzeichnis |
Einleitung
Dieses Tutorial basiert auf einen Artikel von Gavin Kistner und dessen Korrektur durch Shelby H. Moore III.
Deklaration von Klassen
Folgende Klasse repräsentiert einen Punkt im zweidimensionalen Raum.
function Point2D( x, y ) { this.x = x ? x : 0; this.y = y ? y : 0; }Der Ausdruck
<argument> ? <argument> : 0;sorgt dafür, dass die Variablen auch dann richtig initalisiert werden, wenn keine Argumente übergeben werden. (Default-Konstruktor).
Eine JavaScript-Klasse sieht aus wie eine gewöhnliche Funktion. Diese Funktion übernimmt aber gleichzeitig die Aufgabe einer Klassen-Deklaration und die eines Konstruktors.
Die Erzeugung einer Instanz und der Zugriff darauf geschieht wie folgt:
var p = new Point2D( 10, 15 ); alert( "x: " + p.x + ", y: " + p.y ); // x: 10, y: 15
Im Vergleich zur Deklaration erscheint die Instanziierung dann aber eher so, wie man es erwarten würde.
Methoden
Insgesamt werden drei Möglichkeiten genannt, einer Klasse Methoden hinzuzufügen:
Zuweisung von Funktionen im Konstruktor
function Point2D( x, y ) { this.x = 0; this.y = 0; this.set = function( x, y ) { this.x = x; this.y = y; } this.set( x ? x : 0, y ? y : 0 ); }
In diesem Fall wird im Konstruktor eine set()-Methode gesetzt und direkt aufgerufen. Letztendlich ist das nichts anderes als die Initialisierung einer Funktionsvariablen.
Diese Funktion ist nun auch "von außen" aufrufbar:
var p = new Point2D( 1, 3 ); p.set( 3, 1 ); alert( "x: " + p.x + ", y: " + p.y ); // x: 3, y: 1
Deklaration von Methoden über "prototype"
Eine etwas übersichtlichere und empfohlene Möglichkeit ist die nachträgliche Zuweisung von Methoden:
function Point2D( x, y ) { this.x = 0; this.y = 0; this.set( x, y ); } Point2D.prototype.set = function( x, y ) { this.x = x ? x : 0; this.y = y ? y : 0; } var p2 = new Point2D; p2.set( 30, 21 );
In diesem Beispiel wird eine function "set" dem prototype der Point2D-Klasse hinzugefügt und kann auch im Konstruktor aufgerufen werden. Tatsächlich scheint es keinen Unterschied zu machen, welche Methode gewählt wird.
Private Member und Methoden
Ein verbreiteter Irrtum ist, dass es möglich ist, private Methoden zu deklarieren:
function Point2D( x, y ) { this.x = 0; this.y = 0; function set( x, y ) { this.x = x ? x : 0; thix.y = y ? y : 0; } this.set( x, y ); }
Das funktioniert definitiv nicht, da this innerhalb der Funktion set auf window verweist. this ist nicht verfügbar, also wäre das eine ganz normale lokale Funktion, deren Sichtbarkeit sich auf den Konstruktor beschränkt. Diese Methoden sind als weder Methoden, noch sind sie privat.
Ebenso gibt es keine privaten Member. Es ist möglich, innerhalb des Konstruktors lokale Variablen anzulegen. Deren Sichtbarkeit ist aber ebenso nur auf den Konstruktor selbst beschränkt.
Vererbung
Mit JavaScript ist es möglich, alle Methoden und Attribute einer Klasse an den prototype einer anderen Klasse zu übergeben:
Point3D.prototype = Point2D.prototype;
Hinweise: Die in der Korrektur Ohne weiteres Zutun hat man nun zweite Klasse, die eine exakte Kopie der ersten darstellt. Nun kann der prototype der zweiten Klasse beliebig verändert werden, ohne dass dies Auswirkungen auf die erste Klasse hätte:
function Point2D( x, y ) { this.x = 0; this.y = 0; this.set( x, y ); } Point2D.prototype.set = function( x, y ) { this.x = x ? x : 0; this.y = y ? y : 0; } Point3D.prototype = Point2D.prototype; function Point3D( x, y, z ) { this.z = z ? z : 0; this.set( x, y ); } var p = new Point3D( 1, 2, 3 ); alert( "x: " + p.x + ", y: " + p.y + ", z: " + p.z ); // x: 1, y: 2, z: 3
Natürlich könnte nun Point3D eine eigene set()-Methode anbieten, die x, y und z als Parameter erhält:
Point3D.prototype.set = function( x, y, z ) { this.x = x ? x : 0; this.y = y ? y : 0; this.z = z ? z : 0; }
Konstruktoren
Schöner wäre es allerdings, wenn man den Konstruktor der Klasse aufrufen könnte, dessen Member und Methoden man geerbt hat.
Das ist tatsächlich einfach zu realisieren:
Point3D.prototype.set = function( x, y, z ) { Point2D.call( this, x, y ); this.z = z ? z : 0; }
Hier wird diel call()-Methode von Funktions-Objekten aufgerufen und ein Zeiger auf this samt Parameterliste übergeben. this zeigt nun tatsächlich auf ein Point3D-Objekt und der Point2D-Konstruktor initialisert die geerbten Methoden.