File: objekte.htm

package info (click to toggle)
selfhtml 8.1.2-1
  • links: PTS
  • area: non-free
  • in suites: bullseye, buster, jessie, jessie-kfreebsd, squeeze, stretch, wheezy
  • size: 28,076 kB
  • ctags: 4,161
  • sloc: xml: 614; java: 375; makefile: 8
file content (401 lines) | stat: -rw-r--r-- 37,984 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>SELFHTML: Perl / Perl-Sprachelemente / Objektorientiertes Programmieren</title>
<link rel="stylesheet" type="text/css" href="../../src/selfhtml.css">
<meta name="description"    content="Was objektorientierte Programmierung auszeichnet, und wie sie in Perl funktioniert.">
<meta name="keywords"       content="SELFHTML, Perl, OOP, objektorientierte Programmierung, Objekte, Klassen, Instanzen, Eigenschaften, Methoden, Objekteigenschaften, Objektdaten, Konstruktorfunktion, Destruktorfunktion">
<meta name="author"         content="Redaktion SELFHTML, selfhtml81@selfhtml.org">
<meta name="robots"         content="noindex, nofollow">
<meta name="DC.Publisher"   content="SELFHTML e. V.">
<meta name="DC.Date"        content="2005-11-09T00:29:27+01:00">
<meta name="DC.Identifier"  content="http://de.selfhtml.org/perl/sprache/objekte.htm">
<meta name="DC.Language"    content="de">
<meta name="DC.Rights"      content="../../editorial/copyright.htm">
<meta name="DC.Date.created" content="2001-10-27T08:00+01:00">
<meta name="SELF.Pagetype"  content="page">
<link rel="alternate" type="application/atom+xml" title="SELFHTML-Weblog (Atom, gesamt)" href="http://aktuell.de.selfhtml.org/weblog/atom-feed">
<link rel="alternate" type="application/rss+xml" title="SELFHTML-Weblog (RSS, Auszge)" href="http://aktuell.de.selfhtml.org/weblog/rss-feed">
<link rel="shortcut icon" type="image/x-icon" href="../../src/favicon.ico">
<link rel="author" title="Impressum" href="../../editorial/impressum.htm">
<link rel="contents" title="Inhaltsverzeichnis" href="../../navigation/inhalt.htm">
<link rel="index" title="Stichwortverzeichnis" href="../../navigation/stichwort.htm">
<link rel="search" title="Suche" href="../../navigation/suche/index.htm">
<link rel="help" title="Hilfe" href="../../editorial/index.htm">
<link rel="copyright" title="Urheberrecht" href="../../editorial/copyright.htm">
<link rel="top" title="SELFHTML" href="../../index.htm">
<link rel="up" title="Perl-Sprachelemente" href="index.htm">
<link rel="next" title="CGI-typische Aufgaben in Perl" href="cgitypisch.htm">
<link rel="prev" title="Tokens" href="tokens.htm">
<link rel="first" title="CGI-notwendige Anweisungen in Perl" href="cginotwendig.htm">
<link rel="last" title="CGI-typische Aufgaben in Perl" href="cgitypisch.htm">
</head>
<body>

<table cellpadding="4" cellspacing="0" border="0" width="100%">
<tr>
<td colspan="2" class="nav"><a class="an" name="top"><img src="../../src/refkap.gif" width="16" height="13" alt="Teil von"></a> <a href="../../index.htm">SELFHTML</a>/<a href="../../navigation/index.htm" target="_parent" class="navh">Navigationshilfen</a> <img src="../../src/refkap.gif" width="16" height="13" alt="Teil von">&nbsp;<a href="../index.htm">Perl</a> <img src="../../src/refkap.gif" width="16" height="13" alt="Teil von">&nbsp;<a href="index.htm">Perl-Sprachelemente</a></td>
</tr>
<tr>
<td class="doc" width="110"><a href="../../index.htm"><img src="../../src/logo.gif" width="106" height="109" border="0" alt="SELFHTML"></a></td>
<td class="docbot" width="100%"><h1 class="ph1">Objektorientiertes Programmieren</h1></td>
</tr>
<tr>
<td class="doctop">
<img src="../../src/dokx.gif" width="30" height="20" vspace="6" alt="Informationsseite">
</td>
<td valign="top" nowrap="nowrap">
<p>
<img src="../../src/down.gif" width="14" height="10" alt="nach unten">&nbsp;<a href="#oop">Objektorientierte Programmierung (OOP)</a><br>
<img src="../../src/down.gif" width="14" height="10" alt="nach unten">&nbsp;<a href="#oop_perl">Objektorientierte Programmierung in Perl</a><br>
<img src="../../src/down.gif" width="14" height="10" alt="nach unten">&nbsp;<a href="#htmlprint_beispiel">Einfaches Beispiel: das HTMLprint-Objekt</a><br>
<img src="../../src/down.gif" width="14" height="10" alt="nach unten">&nbsp;<a href="#vcard_beispiel">Beispiel mit Objektdaten: das VCard-Objekt</a><br>
</p>
</td>
</tr><tr><td colspan="2" class="doc">&nbsp;<a href="#bottom"><img src="../../src/down.gif" width="14" height="10" border="0" alt="nach unten"></a>&nbsp;</td></tr>
</table>



<h2><a class="an" name="oop">Objektorientierte Programmierung (OOP)</a></h2>

<p>Vor allem bei greren Programmiervorhaben ist es wichtig, nicht einfach draufloszuprogrammieren, sondern sich vorher darber Gedanken zu machen, was die Anwendung knnen, in welcher Form sie Daten speichern soll, welche Benutzerschnittstellen erforderlich sind usw. In dieser Phase ist es gar nicht wichtig und eher hinderlich, dauernd irgendwelche Quellcode-Fetzen im Kopf zu haben. Besser ist es, vom natrlichen Denken ausgehend die Anwendung zu modellieren.</p>

<p>Das natrliche Denken des modernen Menschen ist aber nicht so "prozedural" ausgerichtet wie die klassische Programmierung. Es vollzieht sich nicht in Sprungadressen und Kontrollstrukturen, sondern wird an grere eigenstndige Einheiten (Menschen, Maschinen usw.), die in der Lage sind, Informationen und Fhigkeiten beizusteuern, miteinander zu kommunizieren und dadurch etwas Neues zu schaffen, gebunden.</p>

<p>Auch ein CGI-basiertes Gstebuch lsst sich so denken. Da gibt es beispielsweise einen Formular-Manager, der sich um die Auswertung ausgefllter HTML-Formulare kmmert, einen Daten-Manager, dessen Aufgabe das zuverlssige und einheitliche Speichern und Einlesen von Daten ist, und einen Konfigurations-Manager, der entscheidet, welche Mglichkeiten des Gstebuchs im konkreten Fall genutzt werden und in welcher Form. Dabei muss der Konfigurations-Manager beispielsweise den Daten-Manager um das Einlesen bestimmter Konfigurationsdaten bitten. Selber darf er das nicht, das ist nun mal Aufgabe des Daten-Managers. Genausowenig darf der Daten-Manager sich einfach die HTML-Formulare holen, die vom Anwender abgesendet wurden. Dafr ist der Formular-Manager zustndig, der dann vielleicht wieder beim Konfigurations-Manager nachfragen muss, wie die Daten weiterzugeben sind, und der Antwort entsprechend die Daten an den Daten-Manager zum Abspeichern weitergibt.</p>

<p>Solche teamfhigen Einheiten werden in der objektorientierten Programmierung als Objekte bezeichnet. Ein Objekt hat Eigenschaften und kann etwas tun. Einige der Eigenschaften und Fhigkeiten stammen von anderen Objekten, die das Objekt selbst eingebunden und damit geerbt hat, und andere wiederum sind ganz eigene und besondere Eigenschaften und Fhigkeiten dieses Objekts.</p>

<p>Diese Dokumentation ist allerdings nicht der Rahmen, um die Theorie der objektorientierten Programmierung auszubreiten. Ein paar wichtige Begriffe sollten Sie trotzdem kennen:</p>

<p><strong>Klasse:</strong><br>
Eine Klasse ist die Summe der programmierten Fhigkeiten eines Objekts. Alles, woraus ein Objekt besteht und was es kann, muss irgendwo programmiert sein. Eine Klasse ist aber "abstrakt" programmiert, sie fhrt noch keinen konkreten Code aus. So wie man, wenn man an "Handy" denkt, einen bestimmten Begriff von so einem Gert hat, ist ein konkretes Objekt in der objektorientierten Programmierung nur von seiner Klasse ableitbar. Ein konkretes Objekt hat die Eigenschaften und Fhigkeiten seiner Klasse, so wie man von einem Handy, den man in der Hand hat, sagt, dass es ein Handy ist, weil er die Eigenschaften und Funktionen eines Handys hat, also dem Begriff des Handys entspricht. In einer objektorientierten Anwendung knnen Sie sagen: fr die Aufgabe, die ich lsen mchte, brauche ich erst mal eine bestimmte Klasse, so wie man sagen knnte: fr diese Aufgabe brauche ich einen Handy.</p>

<p><strong>Instanz:</strong><br>
Eine Instanz ist ein konkretes Objekt einer bestimmten Klasse. Mit dem Begriff vom Handy allein knnen Sie noch keine Aufgaben lsen. Sie brauchen ein ganz reales Handy dazu. Genauso brauchen Sie eine ganz reale Instanz einer Klasse, um eine Aufgabe innerhalb Ihrer Anwendung objektorientiert anzupacken. Ihr konkretes Objekt erhlt einen individuellen Namen, unter dem Sie es ansprechen knnen.</p>

<p><strong>Eigenschaften und Methoden:</strong><br>
Von einer Objektinstanz knnen Sie nicht mehr verlangen als das, wozu das Objekt aufgrund seiner Klasse in der Lage ist. Das, wozu ein Objekt in der Lage ist, ist dadurch festgelegt, was in seiner Klasse programmiert ist. Eigenschaften (auch Attribute genannt) sind Variablen, die Ihnen zur Verfgung stehen, wenn Sie eine Instanz eines Objekts erzeugt haben. Methoden sind Funktionen, die Ihnen eine Objektinstanz zur Verfgung stellt. Eine Instanz der Klasse "Formular-Manager" knnte beispielsweise als Eigenschaft eine Datenstruktur anbieten, in der sie eingelesene Formulardaten bequem zur Verfgung stellt. Als Methoden knnte diese Instanz zum Beispiel Filterfunktionen enthalten, um etwa nur die Daten aus versteckten Formularfeldern anzubieten. In Ihrer Anwendung knnen Sie dann Eigenschaften und Methoden verwenden, indem Sie auf deren Namen innerhalb einer konkreten Instanz "zeigen". Das ist so, als ob Sie an dem Laptop, den Sie vor sich haben, die Funktion "suche den nchsten ausreichend starken WLAN-Hotspot" anstoen (eine Methode) und bei gefundenem Hotspot am Display dessen Standort ablesen knnen (eine Eigenschaft).</p>

<p><strong>Konstruktor- und Destruktor-Funktion:</strong><br>
Eine Konstruktorfunktion bernimmt die Handlung, eine Instanz eines Objektes zu erzeugen. Sie macht gewissermaen aus dem Begriff von einem Handy ein reales Handy. Nun sind Sie damit unterwegs, und irgendwann brauchen Sie das Handy nicht mehr. Dann ist es nur unntiges Gepck. Deshalb knnen Sie es dann abschalten. Zumindest im Computer ist das sinnvoll, denn dadurch werden wieder Speicher-Ressourcen frei. Zum Abschalten (Zerstren) von Objektinstanzen gibt es daher eine Destruktor-Funktion.</p>



<p class="doc"><a href="#top"><img src="../../src/up.gif" width="14" height="10" border="0" alt="nach oben"></a><a href="#bottom"><img src="../../src/down.gif" width="14" height="10" border="0" alt="nach unten"></a></p>



<h2><a class="an" name="oop_perl">Objektorientierte Programmierung in Perl</a></h2>

<p>Der Perl-Interpreter untersttzt objektorientiertes Programmieren seit der Version 5.0. Um eine Klasse zu programmieren, also das, wovon sich eine Objektinstanz ableiten lsst, brauchen Sie in Perl ein eigenes <strong>Package</strong>, also einen eigenen Namensraum. <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="subroutinen.htm">Subroutinen</a>, die innerhalb des Packages notiert sind, sind die Methoden von Objekten dieser Klasse. Auch Objekteigenschaften knnen Sie innerhalb solcher Methoden auf bestimmte Weise definieren. Packages lassen sich zwar auch innerhalb eines Perl-Scripts definieren (siehe Beispiel zur Perl-Funktion <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="../funktionen/module.htm#package">package</a>), aber im Normalfall ist ein Package eine separate Perl-Datei, die keine andere Aufgabe hat als die, in Perl-Scripts "eingebunden" zu werden. Kurzum: ein Package ist in Perl meist ein <img src="../../src/kap.gif" width="15" height="13" alt="Kapitel">&nbsp;<a href="../module/index.htm">Modul</a> mit der entsprechenden Dateiendung <code>.pm</code>. Von daher haben in Perl modul-orientiertes Programmieren und objektorientiertes Programmieren viel miteinander zu tun.</p>

<p>Ein Package ist allerdings noch nicht automatisch eine Klasse fr Objekte. Packages sind lediglich Namensrume und damit das "Klima, in dem Objektklassen gedeihen knnen". Damit Perl eine Klasse fr Objekte als solche erkennt, muss sie als solche definiert und erstellt werden.</p>

<p>Ebenso ist es mit den Objektinstanzen. Zunchst mssen Sie Perl mitteilen, dass Sie eine Instanz eines Objekts erzeugen mchten. Ist das gelungen, knnen Sie anschlieend Eigenschaften und Methoden dieses Objekts ber eine bestimmte Syntax ansprechen.</p>

<h3 class="inf">Beachten Sie:</h3>

<p>Perl bietet auch weitere Features der objektorientierten Programmierung an, etwa Vererbung und Methodenbindung an Variablen. In diesem einfhrenden Abschnitt werden solche weiteren Features jedoch nicht behandelt.</p>



<p class="doc"><a href="#top"><img src="../../src/up.gif" width="14" height="10" border="0" alt="nach oben"></a><a href="#bottom"><img src="../../src/down.gif" width="14" height="10" border="0" alt="nach unten"></a></p>



<h2><a class="an" name="htmlprint_beispiel">Einfaches Beispiel: das HTMLprint-Objekt</a></h2>

<p>In diesem Beispiel wird gezeigt, wie Sie ein Modul als Objektklasse erstellen, in einem Perl-Script eine Instanz dieses Objekts erzeugen und mit Methoden des Objekts arbeiten. Das Beispiel realisiert ein einfaches Objekt fr HTML-Ausgaben.</p>

<h3 class="xmp">Beispiel der Moduldatei <var>HTMLprint.pm</var>:</h3>
<pre>
package HTMLprint;

sub new {
 my $Objekt = shift;
 my $Referenz = {};
 bless($Referenz,$Objekt);
 return($Referenz);
}

sub Anfang {
  my $Objekt = shift;
  my $Titel = shift;
  print "Content-type: text/html\n\n";
  print '&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;', "\n";
  print "&lt;html&gt;&lt;head&gt;&lt;title&gt;$Titel&lt;/title&gt;&lt;/head&gt;&lt;body&gt;\n";
}

sub Titel {
  my $Objekt = shift;
  my $Ausgabetext = shift;
  print "&lt;h1&gt;$Ausgabetext&lt;/h1&gt;\n";
}

sub Text {
  my $Objekt = shift;
  my $Ausgabetext = shift;
  print "&lt;p&gt;$Ausgabetext&lt;/p&gt;\n";
}

sub Ende {
  my $Objekt = shift;
  print "&lt;/body&gt;&lt;/html&gt;\n";
}

1;
</pre>

<h3 class="xmp"><a class="an" name="beispiel">Beispiel eines vollstndigen CGI-Scripts in Perl:</a></h3>

<p><img src="../../src/dokf.gif" width="15" height="10" alt="Beispiel-Seite">&nbsp;<a href="http://de.selfhtml.org/cgi-bin/812/objekte.pl">Anzeigebeispiel: So sieht's aus</a> (Zum Aufruf des Scripts ist eine Internet-Verbindung erforderlich)</p>

<pre>
#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);
use HTMLprint;

my $html = HTMLprint -&gt; new();
$html-&gt;Anfang("Ganz elegantes Perl");
$html-&gt;Titel("Ganz elegantes Perl");
$html-&gt;Text("Popeliges HTML, aber sehr modern programmiert!");
$html-&gt;Ende();
</pre>

<h3 class="xpl">Erluterung:</h3>

<p>Die Moduldatei beginnt einfach mit einer <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="../funktionen/module.htm#package">package</a>-Anweisung, die den Namen des Moduls nennt. Der Name sollte identisch mit dem Vornamen der Moduldatei sein. Wenn die Moduldatei also wie im Beispiel <var>HTMLprint.pm</var> heit, sollte die Anweisung <code>package&nbsp;HTMLprint;</code> lauten.</p>

<p>Die Moduldatei im Beispiel enthlt insgesamt fnf Subroutinen. Die erste davon ist die Konstruktorfunktion. Sie erhlt blicherweise den Namen <code>new</code>, knnte aber theoretisch auch einen anderen Namen erhalten. Wie eine Konstruktorfunktion aufgebaut ist, kann von Fall zu Fall variieren. In jedem Fall muss die Konstruktorfunktion jedoch einen Aufruf der Funktion <code>bless</code> enthalten. Diese bindet eine Referenz (einen Zeiger) an eine Klasse, sodass anschlieend ber diese Referenz auf das Objekt zugegriffen werden kann. Die im obigen Beispiel gezeigte Konstruktorfunktion leistet zwar schon ein wenig mehr als fr das Beispiel bentigt wird, doch sie eignet sich in dieser Form einfach gut als Standard-Konstruktorfunktion, bei der man wenig falsch machen kann.</p>

<p>Mit <code>my $Objekt = shift;</code> wird einfach der erste Parameter eingelesen, den die Konstruktorfunktion <code>new</code> bergeben bekommt. Sie bekommt nmlich, wenn sie aufgerufen wird, automatisch als ersten Parameter den Klassennamen bergeben, im Beispiel also den Namen <code>HTMLprint</code>. Das ist im Beispiel der Wert, der anschlieend in <code>$Objekt</code> steht.<br>
Mit <code>my $Referenz = {};</code> wird eine <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="referenzen.htm">Referenz</a>, also ein Zeiger deklariert. Dieser Zeiger wird bentigt, damit die Funktion <code>bless</code> korrekt bedient werden und den Zeiger an das Objekt binden kann. Nun ist die Frage, wie aus der skalaren Variable <code>$Referenz</code> eine Referenz werden soll. Sie muss sich ja auf irgendetwas beziehen, worauf sie zeigt. Ideal ist fr diesen Zweck die Zuweisung <code>{}</code>. Dies ist einfach eine Referenz auf einen leeren unbenannten <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="hashes.htm">Hash</a>. Ideal ist das deshalb, weil dieser Hash auch fr die Definition von Objektdaten geeignet ist - was allerdings in diesem ersten einfachen Beispiel noch nicht geschieht. So bleibt es bei dem leeren Hash, und <code>$Referenz</code> ist ein Zeiger.<br>
Mit <code>bless($Referenz,$Objekt);</code> wird die ntige Verbindung zwischen Referenz und Objekt hergestellt. Anschlieend wird <code>$Referenz</code> zurckgegeben.</p>

<p>Die vier brigen Subroutinen in der Moduldatei <var>HTMLprint.pm</var> sind sich alle recht hnlich. Sie erzeugen mit Hilfe von <code>print</code>-Anweisungen HTML-Code. Die Subroutine <code>Anfang</code> schreibt zudem zunchst den ntigen HTTP-Header fr HTML-Ausgaben.</p>

<p>Fr alle Subroutinen, die als Methoden eines Objekts fungieren, gilt: sie bekommen automatisch mindestens einen Parameter bergeben, und zwar den Zeiger auf das Objekt, der in der Konstruktor-Funktion erzeugt und an das Objekt gebunden wurde. Die Subroutinen im Beispiel bentigen diesen Zeiger nicht. Aber <code>Anfang</code>, <code>Titel</code> und <code>Text</code> erwarten noch einen zweiten ganz gewhnlichen Parameter, nmlich den Inhalt, den sie in HTML ausgeben sollen. Nun knnten sich die Routinen den Inhalt dieses zweiten Parameters auch direkt mit <code>$_[1]</code> holen. Aber die Notation mit dem Aufruf der <code>shift</code>-Funktion hat den Vorteil, dass die Parameterliste dabei sauber abgearbeitet und der Reihe nach gelscht wird. Mit dem jeweils zweiten Aufruf von <code>shift</code> kommen die drei erwhnten Subroutinen also an den zweiten Parameter.</p>

<p>Wichtig zu erwhnen ist noch, dass <var>pm</var>-Moduldateien am Ende stets eine einsame Anweisung <code>1;</code> (oder etwas hnliches) enthalten mssen. Das bedeutet, die Moduldatei gibt einen wahren Wert zurck. Andernfalls wrde der Perl-Interpreter einen Fehler melden.</p>

<p>Das eigentliche Perl-Script ist im Beispiel recht einfach. Mit der Funktion <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="../funktionen/module.htm#use">use</a> und der Anweisung <code>use&nbsp;HTMLprint;</code> bindet es die Moduldatei <var>HTMLprint.pm</var> ein. In dieser Form eingebunden, muss sich die <var>HTMLprint.pm</var> entweder im gleichen Verzeichnis befinden wie das Script, oder in einem der zentralen Verzeichnisse, in denen Perl nach Modulen sucht (mehr darber im Abschnitt <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="../module/intro.htm#speicherorte_inc">Speicherorte fr Module und die Liste @INC</a>).</p>

<p>Mit <code>my $html = HTMLprint -> new();</code> wird die Konstruktorfunktion der Moduldatei aufgerufen. Dies ist die entscheidende Anweisung, mit der eine neue Istanz des HTMLprint-Objekts erzeugt wird! Die Anweisung besteht darin, dass ein Skalar, der im Beispiel den Namen <code>$html</code> erhlt, deklariert und mit einem Wert initialisiert wird. Der zugewiesene Wert besteht darin, dass der Name der gewnschten Objektklasse, also <code>HTMLprint</code>, mit Hilfe des Zeigeoperators <code>-&gt;</code> auf die Konstruktorfunktion <code>new</code> zeigt. Da die Konstruktorfunktion eine Referenz zurckgibt, die durch den <code>bless</code>-Aufruf an das Objekt gebunden ist, wird <code>$html</code> automatisch zu einer Referenz, also zu einem Zeiger auf die neu erzeugte Objektinstanz. ber <code>$html</code> und den Zeigeoperator <code>-&gt;</code> kann das Script fortan auf die Subroutinen des eingebundenen Moduls zugreifen. Im Objektzusammenhang spricht man allerdings nicht mehr von Subroutinen, sondern von Methoden.<br>
Mit einer Anweisung wie <code>$html-&gt;Anfang("Ganz elegantes Perl");</code> greift das Script also auf eine Methode des <code>HTMLprint</code>-Objekts zu, und zwar auf die Objektinstanz, die an den Zeiger <code>$html</code> gebunden ist.</p>



<p class="doc"><a href="#top"><img src="../../src/up.gif" width="14" height="10" border="0" alt="nach oben"></a><a href="#bottom"><img src="../../src/down.gif" width="14" height="10" border="0" alt="nach unten"></a></p>



<h2><a class="an" name="vcard_beispiel">Beispiel mit Objektdaten: das VCard-Objekt</a></h2>

<p>Das folgende Beispiel zeigt, wie sich Daten mit Objekten verwalten lassen. Es handelt sich dabei um Adressdaten im international standardisierten <img src="../../src/de.gif" width="16" height="10" alt="deutschsprachige Seite">&nbsp;<a target="_top" href="http://de.wikipedia.org/wiki/VCard">VCard-Format</a> (typische Dateiendung: *.vcf), wie es vom <img src="../../src/en.gif" width="16" height="10" alt="englischsprachige Seite">&nbsp;<a target="_top" href="http://www.imc.org/">Internet Mail Consortium (IMC)</a> entwickelt und in der <img src="../../src/en.gif" width="16" height="10" alt="englischsprachige Seite">&nbsp;<a target="_top" href="http://tools.ietf.org/html/rfc2426">RFC 2426</a> beschrieben wird. In der Moduldatei <var>VCard.pm</var> wird die VCard-Klasse mit den Objektdaten und Methoden definiert. Im Hauptscript werden dann zwei Objektinstanzen dieser Klasse angelegt, und die Methoden des Objekts werden ausprobiert.</p>

<h3 class="xmp">Beispiel der Moduldatei <var>VCard.pm</var>:</h3>
<pre>
package VCard;

$Objekte = 0;

sub new {
 my $Objekt = shift;
 my $Version = shift;
 my $Referenz = {};
 bless($Referenz,$Objekt);
 $Objekte += 1;
 $Referenz-&gt;VCinit($Version);
 return($Referenz);
}

sub VCinit {
  my $Objekt = shift;
  my $Version = shift;
  $Objekt-&gt;{BEGIN} = "VCARD";
  $Objekt-&gt;{VERSION} = $Version;
  $Objekt-&gt;{END} = "VCARD";
}

sub VCset {
  my $Objekt = shift;
  my $Schluessel = shift;
  my $Wert = shift;
  $Objekt-&gt;{$Schluessel} = $Wert;
}

sub VCget {
  my $Objekt = shift;
  my $Schluessel = shift;
  return($Objekt-&gt;{$Schluessel});
}

sub VCsave {
  my $Objekt = shift;
  my $Datei = shift;
  open(DATEI, "&gt;$Datei") or return(-1);
  print DATEI "BEGIN:VCARD\nVERSION:$Objekt-&gt;{VERSION}\n";
  while ((my $Schluessel, my $Wert) = each %{ $Objekt } ) {
    next if ($Schluessel eq 'BEGIN' or $Schluessel eq 'VERSION' or $Schluessel eq 'END');
    $Schluessel =~ s/_/\;/g;
    print DATEI "$Schluessel:$Wert\n";
  }
  print DATEI "END:VCARD\n";
  close(DATEI);
  return($Datei);
}

sub VCopen {
  my $Objekt = shift;
  my $Datei = shift;
  $Objekt-&gt;VCreset();
  open(DATEI, "&lt;$Datei") or return;
  my @Zeilen = &lt;DATEI&gt;;
  close(DATEI);
  foreach (@Zeilen) {
   (my $Schluessel, my $Wert) = split(/:/);
    $Schluessel =~ s/\;/_/g;
    $Objekt-&gt;{$Schluessel} = $Wert;
  }
  return( %{ $Objekt } );
}

sub VCreset {
  my $Objekt = shift;
  %{ $Objekt } = ();
}

1;
</pre>

<h3 class="xmp">Beispiel eines vollstndigen CGI-Scripts in Perl:</h3>

<pre>
#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);
use VCard;

print "Content-type: text/html\n\n";
print '&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;', "\n";
print "&lt;html&gt;&lt;head&gt;&lt;title&gt;Testausgabe&lt;/title&gt;&lt;/head&gt;&lt;body&gt;\n";
print "&lt;h1&gt;Tests mit dem VCard-Objekt&lt;/h1&gt;\n";

my $Thilo = VCard-&gt;new("3.0");
my $Ina = VCard-&gt;new("3.0");

print "&lt;p&gt;&lt;b&gt;Wert der im Modul erzeugte Objekteigenschaft BEGIN:&lt;/b&gt; $Ina-&gt;{BEGIN}&lt;br&gt;\n";
my $Sicherung = $Ina-&gt;{BEGIN};
$Ina-&gt;{BEGIN} = "fangen wir an";
print "&lt;b&gt;BEGIN nach der Wert&amp;auml;nderung:&lt;/b&gt; $Ina-&gt;{BEGIN}&lt;br&gt;\n";
$Ina-&gt;{BEGIN} = $Sicherung;
print "Da dies aber Unsinn ist, wurde der Wert wieder auf '$Ina-&gt;{BEGIN}' gesetzt.&lt;/p&gt;\n";

$Thilo-&gt;VCset("FN","Thilo Teufel");
$Thilo-&gt;VCset("TEL_CELL_VOICE","(0170) 398373740");
$Ina-&gt;VCset("FN","Ina Bikina");
$Ina-&gt;VCset("EMAIL_PREF_INTERNET","bikina\@example.org");

print "&lt;p&gt;&lt;b&gt;Name:&lt;/b&gt; ",$Thilo-&gt;VCget('FN'),"&lt;br&gt;\n";
print "&lt;b&gt;Handy:&lt;/b&gt; ",$Thilo-&gt;VCget('TEL_CELL_VOICE'),"&lt;/p&gt;\n";
print "&lt;p&gt;&lt;b&gt;Name:&lt;/b&gt; ",$Ina-&gt;VCget('FN'),"&lt;br&gt;\n";
print "&lt;b&gt;Handy:&lt;/b&gt; ",$Ina-&gt;VCget('EMAIL_PREF_INTERNET'),"&lt;/p&gt;\n";
print "&lt;p&gt;&lt;b&gt;Anzahl angelegter Objekte:&lt;/b&gt; $VCard::Objekte &lt;/p&gt;\n";


if(my $Datei = $Thilo-&gt;VCsave("/daten/vcard/teufel.vcf")) {
 print "&lt;p&gt;VCard von Thilo Teufel in &lt;tt&gt;$Datei&lt;/tt&gt; gespeichert!&lt;br&gt;"
}
else {
 print "VCard von Thilo Teufel konnte nicht gespeichert werden!";
}
$Thilo-&gt;VCreset();
print "&lt;p&gt;&lt;b&gt;Name von Thilo nach Objekt-Reset:&lt;/b&gt; ",$Thilo-&gt;VCget('FN'),"&lt;br&gt;\n";
print "&lt;b&gt;Handy von Thilo nach Objekt-Reset:&lt;/b&gt; ",$Thilo-&gt;VCget('TEL_CELL_VOICE'),"&lt;/p&gt;\n";

if($Thilo-&gt;VCopen("/daten/vcard/teufel.vcf")) {
 print "VCard von Thilo Teufel wieder ge&amp;ouml;ffnet!&lt;br&gt;";
 print "&lt;p&gt;&lt;b&gt;Name von Thilo nach Datei&amp;ouml;ffnen:&lt;/b&gt; ",$Thilo-&gt;VCget('FN'),"&lt;br&gt;\n";
 print "&lt;b&gt;Handy von Thilo nach Datei&amp;ouml;ffnen:&lt;/b&gt; ",$Thilo-&gt;VCget('TEL_CELL_VOICE'),"&lt;/p&gt;\n";
}
else {
 print "VCard von Thilo Teufel konnte nicht ge&amp;ouml;ffnet werden!";
}

print "&lt;/body&gt;&lt;/html&gt;\n";
</pre>

<h3 class="xmp">Beispiel der erzeugten Datei <var>teufel.vcf</var>:</h3>
<pre>
BEGIN:VCARD
VERSION:3.0
TEL;CELL;VOICE:(0170) 398373740
FN:Thilo Teufel
END:VCARD
</pre>

<h3 class="xpl">Erluterung:</h3>

<p>Im Prinzip funktioniert dieses Beispiel genauso wie das Beispiel mit dem <img src="../../src/up.gif" width="14" height="10" alt="nach oben">&nbsp;<a href="#htmlprint_beispiel">HTMLprint-Objekt</a> - deshalb interessieren an dieser Stelle nur diejenigen Dinge, die anders sind als im ersten Beispiel.</p>

<p>Objektdaten (oder die Eigenschaften eines Objekts) sind Variablen. Es gengt jedoch nicht, solche Variablen einfach irgendwo in der Moduldatei zu deklarieren. Eine Variable wie der Skalar <code>$Objekte</code>, der im Beispiel zu Beginn der Moduldatei <var>VCard.pm</var> deklariert wird und als Zhler fr Objektinstanzen dient, gehrt <strong>nicht</strong> zu den Objektdaten! Solche Variablen sind so genannte Klassenvariablen, da sie nur einmal fr die gesamte Klasse und fr jede Objektinstanz zur Verfgung stehen. Da das Modul genau einmal im Hauptscript eingebunden wird, stehen diese Variablen auch nur in einer einzigen Ausfhrung zur Verfgung. Das Hauptscript kann mit der Syntax <code>$VCard::Objekte</code> sehr wohl auf den Wert des Skalars <code>$Objekte</code> zugreifen. Aber trotzdem gehrt diese Variable nicht zum Objekt. Objektdaten sind vielmehr solche, die bei jeder neuen Instanz eines Objekts immer wieder neu zur Verfgung stehen.</p>

<p>Die einfachste Lsung fr Objektdaten ist ein <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="hashes.htm">Hash</a>. In der Konstruktorfunktion <code>new</code> wird ein solcher Hash definiert - mit der Anweisung <code>my&nbsp;$Referenz&nbsp;=&nbsp;{};</code>. Viel zu sehen ist dabei nicht von einem Hash. Doch die leeren geschweiften Klammern symbolisieren einen leeren so genannten anonymen Hash. Dieser Hash ist damit eine Art leerer Behlter, der spter Objektdaten aufnehmen kann. Der Grund dafr, dass man in der Regel einen Hash fr Objektdaten whlt, ist der, dass ein Hash eine dynamische Anzahl von Daten speichern kann. Ein solcher Hash erlaubt es, Objektdaten sowohl im Modul selbst vorzudefinieren, wie auch Objektdaten im Hauptscript zu definieren (im obigen Beispiel passiert beides). Ein Array knnte das zwar theoretisch auch, aber dann wre im Hauptscript die Suche nach einem gewnschten Objektdatum schwieriger. Hashes erleichtern den Direktzugriff auf Daten durch die benannten Schlssel. Durch die Zuweisung des anonymen Hashes an einen Skalar - im Beispiel an <code>$Referenz</code> - wird dieser Skalar eine <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="referenzen.htm">Referenz</a>, also ein Zeiger auf den anonymen Hash. ber diesen Zeiger ist der Zugriff auf den anonymen Hash mglich.</p>

<p>Objektdaten werden erzeugt, indem der zunchst anonyme Hash der Konstruktorfunktion mit Daten angefllt wird. Im Beispiel geschieht das erstmals in der Subroutine bzw. Methode <code>VCinit</code>. Diese Methode wird bereits in der Konstruktorfunktion <code>new</code> aufgerufen, nmlich mit <code>$Referenz->VCinit($Version);</code>. Da <code>$Referenz</code> innerhalb der Konstruktorfunktion der Objektzeiger ist, knnen Sie dort ber das Schema <code>$Referenz->Methode()</code> andere Subroutinen aufrufen, die dadurch an das Objekt gebunden werden. Durch diese Form des Aufrufs bekommen die Subroutinen auch stets automatisch als ersten Parameter einen Zeiger auf das Objekt bergeben, mit dem sie dann arbeiten knnen. So auch die Methode <code>VCinit</code> im Beispiel. ber den Objektzeiger, den sie sich mit <code>my $Objekt = shift;</code> aus der bergebenen Parameterliste holt, kann sie auf das Objekt und damit auch auf den anonymen Hash zugreifen.</p>

<p>Mit einer Anweisung wie <code>$Objekt-&gt;{BEGIN} = "VCARD";</code> wird eine vorgegebene Objekteigenschaft erzeugt. <code>$Objekt-&gt;{BEGIN}</code> zeigt auf den anonymen Hash und sagt so viel wie: "hiermit erhlt der anonyme Hash einen Schlssel mit Namen <code>BEGIN</code>". Auerdem wird diesem Schlssel bereits ein Wert zugewiesen, nmlich <code>VCARD</code>. Auf die gleiche Weise werden in <code>VCinit</code> insgesamt drei Objekteigenschaften erzeugt. Die beiden anderen heien <code>VERSION</code> und <code>END</code>. Der Grund fr diese Namen ist im Beispiel, dass diejenigen Namen von Eigenschaften als Schlsselnamen verwendet werden, die eine Datei vom Typ <var>.vcf</var> enthalten knnen. Wie so eine Datei aussieht, sehen Sie in der dargestellten vom Beispiel erzeugten Datei <var>teufel.vcf</var>. Alle Zeilen einer VCard-Datei bestehen aus einer Eigenschaft und ihrem Wert, getrennt durch einen Doppelpunkt. Drei Zeilen sollten in jeder vcf-Datei vorkommen: <code>BEGIN:VCARD</code>, <code>VERSION:[Versionsangabe]</code> und <code>END:VCARD</code>. Fr diese drei Standardzeilen werden im Beispiel die drei gleichnamigen Objekteigenschaften erzeugt.</p>

<p>Weitere Objekteigenschaften werden im Beispiel im Hauptscript erzeugt. Zunchst muss dazu wieder eine Instanz der VCard-Klasse erzeugt werden. Im Beispiel werden zwei Instanzen erzeugt:<br>
<code>my $Thilo = VCard-&gt;new("3.0");<br>
my $Ina = VCard-&gt;new("3.0");</code><br>
Beim Aufruf der Konstruktorfunktion wird die Versionsnummer fr das gewnschte VCard-Format bergeben. Derzeit ist da die Version 3.0 zu notieren.</p>

<p>Nachdem die beiden Objektinstanzen angelegt sind, ist der Zugriff auf smtliche Objektdaten mglich. Im Hauptscript wird dies zunchst mit dem Objekt fr Ina demonstriert. ber den Objektzeiger <code>$Ina</code> ist es mglich, mit <code>$Ina-&gt;{BEGIN}</code> auf den Wert der Objekteigenschaft <code>BEGIN</code> zuzugreifen. Das Script zeigt auch, wie sich der Wert einer solchen vorgegebenen Objekteigenschaft ndern lsst. Das Konstrukt <code>$Ina-&gt;{BEGIN}</code> kann wie ein ganz normaler Skalar behandelt werden.<br>
Da bei der objektorientierten Programmierung das Objekt eine abstrakte Einheit ist, dessen Interna Sie als Benutzer des Objekts eigentlich nichts angehen, sollten Sie darauf verzichten, direkt auf Objekteigenschaften zuzugreifen. Erstens ist nmlich nicht gesagt, dass bei einem (beliebigen) Objekt die Daten berhaupt in einem Hash gehalten werden, und zweitens kann sich die interne Datenhaltung ber die verschiedenen Versionen des Moduls hinweg ndern.</p>

<p>Das Hauptscript erzeugt aber auch noch weitere neue Objekteigenschaften und versorgt diese mit Werten. Denn eine VCard-Datei soll ja diverse Adressdaten enthalten. Dies ist im Beispiel durch Aufruf der Methode <code>VCset</code> mglich, die in der Moduldatei definiert ist. Mit einer Anweisung wie:<br>
<code>$Thilo-&gt;VCset("FN","Thilo Teufel");</code><br>
wird fr das Objekt von Thilo eine neue Objekteigenschaft namens <code>FN</code> angelegt, die den Wert <code>Thilo Teufel</code> zugewiesen bekommt. Im Beispiel sehen Sie, dass sowohl das Objekt von Thilo als auch das Objekt von Ina die Objekteigenschaft <code>FN</code> erhalten, jeweils mit eigenen Werten. Daran ist sehr schn erkennbar, dass es sich tatschlich um verschiedene Instanzen des Objekts <code>VCard</code> handelt, wobei jede Instanz ihre eigene Datenwelt hat, ohne dass es Kollisionen mit anderen gleichzeitig existierenden Objektinstanzen gibt.</p>

<p>Whrend der Aufruf der Methode <code>VCset</code> so weit gut nachvollziehbar ist, ist das, was in der Moduldatei innerhalb dieser Methode geschieht, nicht so leicht zu verstehen. Auch <code>VCset</code> bekommt - wie alle Methoden - als ersten Parameter automatisch den Objektzeiger bergeben. <code>VCset</code> tut nun nichts anderes, als mit <code>$Objekt-&gt;{$Schluessel}&nbsp;=&nbsp;$Wert</code> dem anonymen Hash des Objekts einen Schlsselnamen und einen zugehrigen Wert hinzuzufgen. Beides, also den Schlsselnamen und den Wert, erwartet die Methode als Parameter - daher auch die voranstehenden Anweisungen wie <code>$Schluessel&nbsp;=&nbsp;shift;</code>. Die Aufrufe dieser Methode im Hauptscript bergeben ja auch die geforderten beiden Parameter.</p>

<p>Die brigen Methoden der Moduldatei sind ganz hnlich aufgebaut. Sie bernehmen verschiedene Aufgaben, was man mit VCard-Daten so alles anstellen kann:<br>
<code>VCget</code> liefert zu einem Schlssel den zugehrigen Wert. Gut fr Abfragen. Genaugenommen ist eine Abfrage im Hauptscript wie <code>$Thilo-&gt;VCget('FN')</code> das gleiche, als ob dort stehen wrde <code>$Thilo-&gt;{FN}</code>. Entscheidungen, ob man solche Methoden braucht, gehren einfach zum Design eines Objekts. Um die Programmpflege zu erleichtern, sollten Sie jedoch immer Methoden dafr bereitstellen.<br>
<code>VCsave</code> speichert die Daten eines Objekts in eine vcf-Datei nach dem VCF-Standard. Im Script wird diese Funktion einmal aufgerufen und schreibt dabei die Datei <var>teufel.vcf</var>, deren Inhalt ja dargestellt ist.<br>
<code>VCopen</code> liest eine beliebige VCF-Datei und speichert deren Inhalt im zugeordneten Objekt. Diese Methode knnen Sie also etwa verwenden, wenn Sie existierende VCF-Dateien haben, z.B. durch Export aus den Adressdaten eines VCard-fhigen E-Mail-Programms.
<code>VCreset</code> lscht alle Daten eines Objekts. Es stellt also den Ursprungszustand des anonymen Hashes wieder her. Bentigt wird diese Methode innerhalb der Moduldatei von <code>VCopen</code>. Aber Sie knnen diese Methode natrlich auch aus dem Hauptscript aufrufen, um eine Objektinstanz wieder in ihren jungfrulichen Zustand zu versetzen. Im Hauptscript des obigen Beispiels wird dies am Objekt von Thilo demonstriert.</p>

<p>Wenn Sie das VCard-Objekts des Beispiels in der Praxis einsetzen wollen, mssen Sie die VCard-Eigenschaftsnamen kennen. Diese sind beim Internet Mail Consortium dokumentiert. Wichtig ist, dass Sie ein Semikolon immer durch Unterstrich ersetzen. So wird eine VCard-Eigenschaft wie <code>TEL;CELL;VOICE</code> bei einem Methodenaufruf wie <var>VCset</var> als <code>TEL_CELL_VOICE</code> notiert. Einige der mglichen VCard-Eigenschaften enthalten auch noch andere Zeichen wie <code>=</code> und <code>-</code>. Um diese korrekt zu verarbeiten, mssen Sie die Methoden <code>VCopen</code> und <code>VCsave</code> des Objekts vermutlich noch erweitern, worauf im Beispiel der Einfachheit halber verzichtet wurde.</p>



<table cellpadding="4" cellspacing="0" border="0" width="100%">
<tr><td colspan="2" class="doc">
&nbsp;<a href="#top"><img src="../../src/up.gif" width="14" height="10" border="0" alt="nach oben"></a>
</td></tr>
<tr><td class="doc"><a href="cgitypisch.htm"><img src="../../src/next.gif" width="10" height="10" border="0" hspace="10" alt="weiter"></a></td>
<td width="100%"><img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="cgitypisch.htm">CGI-typische Aufgaben in Perl</a>
</td></tr>
<tr>
<td class="doc"><a href="tokens.htm"><img src="../../src/prev.gif" width="10" height="10" border="0" hspace="10" alt="zurck"></a></td>
<td><img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="tokens.htm">Tokens</a>
</td>
</tr>
<tr><td colspan="2" class="doc">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="nav"><a class="an" name="bottom"><img src="../../src/refkap.gif" width="16" height="13" alt="Teil von"></a> <a href="../../index.htm">SELFHTML</a>/<a href="../../navigation/index.htm" target="_parent" class="navh">Navigationshilfen</a> <img src="../../src/refkap.gif" width="16" height="13" alt="Teil von">&nbsp;<a href="../index.htm">Perl</a> <img src="../../src/refkap.gif" width="16" height="13" alt="Teil von">&nbsp;<a href="index.htm">Perl-Sprachelemente</a></td>
</tr>
</table>

<p>&copy; 2007 <img src="../../src/dok.gif" width="15" height="10" alt="Seite">&nbsp;<a href="../../editorial/impressum.htm">Impressum</a></p>

</body>
</html>