Werbung einblenden Werbung ausblenden


Home / Tutorials / JavaScript Handbuch / Eigene Objekte mit JavaScript


Was sind Objekte?
Umsetzung der objektorientierten Programmierung in JavaScript

Vererbung

Was sind Objekte?

Wer noch nie was über objektorientierte Programmierung gelesen hat, kann sich das durchlesen, wer weiss, was es ist, sollte gleich weiter zum Beispiel hopsen. In gewisser Weise ist JavaScript eine 100 % objektorientierte Sprache, allerdings mit der Besonderheit, dass man in der Regel keine Objekte selbst generiert, sondern auf fertige Objekte wie images, document, window, array etc. etc. zugreift. Man kann aber, wenn das auch die wenigsten tun, mit JavaScript selber Objekte kreieren. Wir verweisen hier bewusst nicht auf die Perl und PHP Handbücher, wo unter objektorientierte Programmierung mit Perl bzw. objektorientierte Programmierung mit PHP einiges Grundsätzliches zur objektorientierten Programmierung gesagt wird. Wir ziehen es vor, nochmal Grundsätzliches dazu zu sagen. Im Prinzip funktionniert der objektorientierte Ansatz in allen Programmiersprachen ähnlich, die Idee dahinter ist immer die gleiche. Hinter der objektorientierten Programmierung steht immer das Bemühen, grosse Softwarepakete zu kapseln, das heisst dem Programmierer kleine Softwarepakete zur Verfügung zu stellen, die bestimmte Aufgaben lösen und die er nutzen kann, wenn ihm die Schnittstelle zu diesen Paketen, und nur diese bekannt ist. Wer will kann sich das auf einem hohen Abstraktionsniveau so klar machen. In der objektorientierten Programmierung gibt es Substantive und konkrete Dinger, auf die diese Substantive verweisen. Das ist ja bekanntlich das Prinzip jeder natürlichen Sprache. Man hat ein Substantiv, ein Dingwort, und das Dingwort bezeichnet einen konkreten Gegenstand (Auto -> mein Auto, Banane->Die Banane des Gorillas etc. etc.) Substantive sind ein Konzept eines konkreten Dinges. Mit konkretem Ding ist jetzt etwas gemeint, wo man sich z.B. den Schädel daran anstossen kann, zum Beispiel ein Betonpfeiler. An dem Konzept eines Betonpfeilers, dem Wort, kann man sich den Schädel ja nicht anstossen. Was heisst hier Konzept eines konkreten Dinges, bzw. Konzept einer Gruppe von konkreten Dingen ? Wenn wir Auto sagen, haben wir ein Konzept im Kopf. Es ist ein Ding, das mindestens drei Räder hat und sich aus eigener Kraft von A nach B bewegen kann. Dieses Konzept ist aber noch kein konkretes Ding. Meinen wir aber ein konkretes Auto, z.B. mein Auto, dann haben wir es im Vokabular der objektorientierten Programmierung mit einer Instanz zu tun. Volkswagen instanziiert täglich ein paar tausend davon, das heisst, die bauen Autos. Substantive sind in der objektorientierten Programmierung Klassen, das heisst, abstrakte Baupläne für konkrete Dinge. In diesen Bauplänen sind Methoden und Eigenschaften definiert. Methoden sind bei der Klasse Auto z.B. fahren, bremsen, hupen. Eigenschaften sind die Farbe des Autos, die Marke, Alter etc. etc. Eine Methode ist jetzt das gleiche wie eine Funktion und eine Eigenschaft ist das gleiche wie eine Variable. Durch die Einführung der neuen Begriffe Methode und Eigenschaften bringt man lediglich zum Ausdruck, dass man es mit Funktionen und Variablen zu tun hat, die nur im Zusammenhang mit einem Objekt auftreten können. Ein Objekt kann nämlich nur die Eigenschaften und Methoden haben, die im Bauplan festgelegt sind. Wir wären ja auch alle echt verblüfft, wenn ein Auto Milch gibt, denn das tut ja eigentlich eine Kuh. In der objektorientierten Programmierung verhält es sich nun ähnlich wie in natürlichen Sprachen, bzw. eine Kommunikation wäre nicht möglich, wenn die Sprache nicht objektorientiert wäre, nicht aus Klassen (Substantiven) bestünde, die auf konkrete Dinge verweisen. Ein harmloser Satz wie "ich habe ihm eine Uhr zum Geburtstag geschenkt" wäre sinnlos, wenn wir nicht wüssten, welche Eigenschaften und Methoden eine Uhr hat und welche Eigenschaften Geburtstag hat. Wir müssen nur eine Schnittstelle finden zum Ohr desjenigen, mit dem wir uns unterhalten, also den Schall, um uns verständlich zu machen. Es interessiert uns nicht weiter, wie der dann in seinem Gehirn eine Uhr vor seinem geistigen Auge entstehen lässt. Wir erwarten dann eine Reaktion von unserem Gesprächspartner, z.B. "wozu braucht der Penner eine Uhr, der kommt doch eh immer zu spät". Wir interessieren uns nicht dafür , wie er intern arbeitet und wie er die Information verwertet, Hauptsache er produziert einen Output. Wir interessieren uns auch in der objektorientierten Programmierung nicht dafür, wie die Werte, die wir übergeben, intern verarbeitet werden. Hauptsache wir sind in der Lage, etwas zu übergeben und Hauptsache wir kriegen was zurück. Es ist wohl jedem klar, dass der Ansatz, den natürliche Sprachen verfolgen, der einzig machbare ist. Hätten wir das nicht, dann bräuchten wir, um der Tatsache Ausdruck zu verleihen, dass Maria, David und Ernst eine Uhr haben, jedesmal eine komplette Beschreibung. Maria hat ein Ding, das macht tick-tack und hat zwei Zeiger und........, David hat ein Ding, das macht tick-tack und... , Ernst hat ein Ding, das macht tick-tack etc. etc. Also die Angelegenheit wäre hoffnungslos. (Sie wäre übrigens auch deswegen hoffnunglos, weil Zeiger selber eine Klasse ist, den man dann auch erklären müsste). Wenn man also gelegentlich die Behauptung findet, dass der Mensch eigentlich objektorientiert denkt, dann ist das vielleicht sogar richtig, was allerdings nichts an der Tatsache ändert, dass die technische Umsetzung der objektorientierten Programmierung wesentlich komplizierter ist, als die prozedurale Programmierung.

Umsetzung der objektorientierten Programmierung in JavaScript

Die Umsetzung der objektorientierten Programmierung in JavaScript weicht ab, von anderen Programmiersprachen wie C++, C, Perl, PHP, Java. Alle diese Programmiersprachen bilden Klassen, die alle Eigenschaften und Methoden einer Klasse kapseln. Von dieser Klasse wiederum werden dann Instanzen, also konkrete Objekte gebildet, die als Kinder der Klasse all das können, was die Klasse kann. Die Idee ist in JavaScript diesselbe, die konkrete technische Umsetzung allerdings ist anders. Betrachten wir folgendes Beispiel. Wir betrachten den Fall, dass das Objekt nur eine Methode hat, dann ist es nämlich erstmal besonders einfach.

<html><head><title>Klassen und Objekte</title>
<script language="JavaScript">
function initio(a,b,c)
{
this.zahl1=a;
this.zahl2=b;
this.text=c;
this.summe=this.zahl1+this.zahl2;
}
var objekt1=new initio(4,20,"Das Ergebnist ist");
alert(objekt1.text + " " + objekt1.summe);
var objekt2=new initio(5,30,"Die Addition dieser beiden Zahlen ergibt");
alert(objekt2.text + " " + objekt2.summe);
</script>
</head>
<body>
mein erstes Objekt
</body>
</html>

Wer wissen will, was passiert, der muss hier clicken. Was passiert ? Die Funktion initio() sieht erstmal aus, wie eine ganz normale Funktion. Im Prinzip ist sie das auch, es ist eine Funktion, die ein Objekt kreiert. Das Besondere liegt weniger an der Funktion initio(), als an der Art und Weise, wie sie aufgerufen wird.

var objekt1=new initio(4,20,"Das Ergebnist ist");

Wir rufen hier nicht einfach eine Welt, Wald und Wiesen Funktion auf, deren Rückgabewert wir an eine Variable übergeben. Tatsächlich rufen wir eine Funktion auf und sorgen dafür, dass die Parameter, die wir übergeben, an ein Objekt gebunden werden. Wenn wir eine Funktion mit new Name_der_Funktion() aufrufen, wird ein Zeiger auf das Objekt mitübergeben und andereseits ist der Rückgabewert dieser Funktion eben dieser Zeiger auf das Objekt. Der Zeiger auf das Objekt, steckt in this. Folglich sind haben this und objekt1 bzw. this und objekt2 denselben Wert. Wenn wir also this.zahl1 schreiben, dann ist es die erste Zahl unseres ersten Objektes, this und objekt1 bezeichnen ja dasselbe Objekt, mit objekt1.zahl1 auch wieder rausfischen können. Nach diesem Schema können wir dann beliebig viele Objekte generieren, von denen jedes individuelle Eigenschaften hat, wie man ja deutlich sieht, da jedes alert Fenster die Objetkeigenschaften des jeweiligen Objektes zeigt. Wie man an diesem einfachen Beispiel auch sieht, ist es weniger Schreibarbeit, objektorientiert zu programmieren. In diesem Falle rufen wir ja lediglich zweimal (dreimal, viermal, fünfmal...) die Funktion initio() auf und übergeben dann gleich die jeweiligen Werte, ohne jedes mal den ganzen Code neu einzutippen. Der Einwand, der jetzt vorgebracht werden kann ist klar. Man hätte das gleiche auch mit einer normalen Funktion machen können, die man eben zweimal aufruft. Wir werden sehen, dass sich mit dem objektorientierten Ansatz Dinge realisieren lassen, die nur mit einem größeren Aufwand möglich sind, wenn man nur mit Funktionen arbeitet. Zuerst einmal überlegen wir uns jetzt aber, sie wir unserem Objekt nicht nur Eigenschaften, sondern auch Methoden zuweisen können. Wass wir in unserem Beispiel spätestens dann wollen, wenn wir nicht nur addieren sondern auch subtrahieren, multiplizieren, dividieren wollen. Machen wir uns das anhand dieses Skriptes klar.

<html><head><title>Klassen und Objekte</title>
<script language="JavaScript">
function initio(a,b,c)
{
this.zahl1=a;
this.zahl2=b;
this.text=c;
this.multiplikation=function() { this.summe=this.zahl1*this.zahl2;}
this.division=function(){ this.summe=this.zahl1/this.zahl2;}
this.substraktion=function() {this.summe=this.zahl1-this.zahl2;}
}
var objekt1=new initio(4,20,"Das Ergebnis ist");
objekt1.multiplikation();
alert(objekt1.text + " " + objekt1.summe);
var objekt2=new initio(5,30,"Die Substraktion dieser beiden Zahlen ergibt");
objekt2.substraktion();
alert(objekt2.text + " " + objekt2.summe);
</script>
</head>
<body>
mein erstes Objekt
</body>
</html>

Vielleicht ist es auch hier wieder günstig, sich zuerst mal klar zu machen, was passiert, indem man hier clickt. Innerhalb der Funktion initio() haben wir, und das ist gewöhnungsbedürftig, drei weitere Funktionen definiert, nämlich multiplikation(), division() und substraktion() von denen wir dann anschliessend auch zwei Funktionen, nämlich multiplikation() und substraktion() auch tatsächlich nutzen. Nun lösen wir, nachdem wir das Objekt initialisiert haben, die Funktion multiplikation() bzw. substraktion() aus.

objekt1.multiplikation();
objekt2.substraktion();

Da wir sie in der objektorientierten Schreibweise auslösen, wird der Zeiger auf das Objekt ( objekt1 bzw. objekt2) mit übergeben. Damit hat bei jedem Aufruf this einen Wert, der auf das jeweilige Objekt zeigt, was wiederum bewirkt, dass die Substraktion bzw. die Multiplilkation mit den Werten durchgeführt wird, die zu diesem Objekt gehören. Wir sehen also, dass JavaScript das Klassenkonzept ungewöhnlich umsetzt. Alle Methoden des Objektes werden innerhalb der Funktion deklariert, die auch das Objekt instanziiert. In anderen Programmiersprachen werden alle Methoden zu einer Klasse zusammengefasst. Von der Idee her, ist es aber dasselbe.

Vererbung

Unter Vererbung versteht man die Tatsache, dass eine Unterklasse alle Eigenschaften einer Klasse erben kann, so dass die Eigenschaften der Oberklasse nicht mehr neu definiert werden müssen. Es wurde schon an vielen Stellen bemerkt, dass erben der falsche Ausdruck ist, den vererben kann nur jemand, der bereits tot ist, was bei einer Klasse nicht der Fall ist, diese reicht ihre Eigenschaften und Methoden lediglich an die Unterklasse weiter. Untechnisch betrachtet ist das einfach einzusehen. Ein Sportauto ist eben ein Auto (ein Ding auf drei oder vier Rädern, dass von A nach B fährt), welches alle Eigenschaften von Auto hat und noch ein paar spezifische des Sportautos. Der Ansatz, mit dem Vererbung in JavaScript umgesetzt wird, weicht erheblich von der Art ab, wie es in Perl, PHP, C#, Java, C++ etc. umgesetzt wird. In JavaScript verwendet man zur Implementierung des Vererbungsmechanismus prototype. Am besten wir machen uns das an einem Beispiel klar. Nehmen wir an, wir wollen mit unseren zwei Zahlen nicht nur eine der vier Grundrechenarten durchführen, sondern auch die Umsatzsteuer berechnen (a ist also die Summe und b der Umsatzsteuersatz). In diesem Fall müssten wir die Funktion initio() erweitern, weil wir eine Funktion() zur Durchführung der Umsatzsteuer im Moment nicht im Angebot haben. Das Beispiel unten erweitert unser Programm um diese Funktion.

<html><head><title>Klassen und Objekte</title>
<script language="JavaScript">
function initio(a,b,c)
{
this.zahl1=a;
this.zahl2=b;
this.text=c;
this.summe=this.zahl1+this.zahl2;
}

initio.prototype.Umsatzsteuer=function()
{
this.steuer=this.zahl1*this.zahl2/100;
}

Finanzamt=new initio(100,15,"Die Umsatzsteuer beträgt");
Finanzamt.Umsatzsteuer();
alert(Finanzamt.steuer);
</script>
</head>
<body>
mein erstes Objekt
</body>
</html>

Das funzt, wovon man sich überzeugen kann, wenn man hier clickt. Wir erhalten 15, was korrekt ist, den 15 % von 100 sind 15. Entscheidend sind hierbei die Zeilen

initio.prototype.Umsatzsteuer=function()
{
this.steuer=this.zahl1*this.zahl2/100;
}

mit denen wir unsere Funktion um die Funktion Umsatzsteuer erweitern. Wenn wir jetzt, wie gehabt, mit

Finanzamt=new initio(100,15,"Die Umsatzsteuer beträgt");

ein Objekt Finanzamt instantiieren, dann hat dieses Objekt Finanzamt auch eine Methode Umsatzsteuer, die wir in der Zeile

Finanzamt.Umsatzsteuer();

auch anprechen. Nachem diese Funktion aufgerufen wurde, haben wir eine Objektvariable steuer, die wir uns mit

alert(Finanzamt.steuer);

anzeigen lassen.

vorhergehendes Kapitel