420 likes | 645 Views
Objektorientierte Programmierung. Ihrem Ursprung nach ist Perl eine prozedurale Programmiersprache. Mit Hilfe der „ Perlmodule “ lassen sich auch objektorientierte Konzepte verfolgen. Unterschiedliche Typen von Modulen: prozedurale Funktionsbibliotheken
E N D
Objektorientierte Programmierung • Ihrem Ursprung nach ist Perl eine prozedurale Programmiersprache. Mit Hilfe der „Perlmodule“ lassen sich auch objektorientierte Konzepte verfolgen. • Unterschiedliche Typen von Modulen: • prozedurale Funktionsbibliotheken • objektorientierte Klassenbibliotheken
Prozedurale Funktionsbibliotheken #!/usr/bin/perl # Deklaration der Funktionen sub vorstellung # Unterprogramm vorstellung { my $name = $_[0]; my $alter = $_[1]; printf (“\nHallo, ich heisse %s und bin %s \n\n“, $name, $alter); } sub seit_wann_erwachsen # Unterprogramm seit_wann_erwachsen { my $alter = $_[0]; return $alter – 18; } # Arbeitsteil des Programmes $person = “Hugo“; print “Reden wir mal ueber $person\n\n“; vorstellung ($person, 40); $erwachsen = seit_wann_erwachsen (40); print “$person ist seit $erwachsen Jahren erwachsen\n\n“;
Prozedurale Funktionsbibliotheken Mit modularer Programmentwicklung hat das noch nicht viel zu tun. Wollte man die Funktionen „vorstellung()“ und „seit_wann_erwachsen()“ auch in anderen Skripten nutzen, so müsste man zur guten alten Cut-and-Paste-Technik greifen. Besser: Funktionen mit hohem Wiederverwendungswert in separate Dateien (personal.pm) abzulegen. Die Funktionsdateien (.pm) müssen anschließend im Perl – Bibliotheksverzeichnis gespeichert werden. Bei Suse Linux müsste das Verzeichnis folgendermaßen aussehen: /usr/lib/perl5/5.005003/
Prozedurale Funktionsbibliotheken Personal.pm package Personal; sub vorstellung { my $name = $_[0]; my $alter = $_[1]; printf (“\nHallo, ich heisse %s und bin %s \n\n“, $name, $alter); } sub seit_wann_erwachsen { my $alter = $_[0]; return $alter – 18; } 1; # Rückgabe eines True Wertes
Prozedurale Funktionsbibliotheken personal.pl #!/usr/bin/perl use Personal; # Variablenzuweisung $person = “Hugo“; # Zugriff auf die Funktion Personal Personal::vorstellung ($person, 40);
Prozedurale Funktionsbibliotheken Für den Fall, dass private Moduldateien separat abgelegt werden sollen, gibt es die Möglichkeit dem Perlcompiler zusätzliche Bibliotheksverzeichnisse vorzugeben. Über die Anweisung “use lib“ im Script: #!/usr/bin/perl use Personal; use lib “/home/tom/module“; # personal.pm und personal.pl ist gespeichert unter /home/tom/module # Variablenzuweisung $person = “Hugo“; # Zugriff auf die Funktion Personal Personal::vorstellung ($person, 40);
Die Bibliothek CGI.pm formular.html <html> <head> </head> <body> <form action="formular.pl" method="get"> Herr<input type="radio" name="anrede" value="Herr" checked><br> Frau<input type="radio" name="anrede" value="Frau"><br> <input type="text" size="30" name="name"><p> <input type="submit" value="OK"> <input type="submit" value="Abbrechen"> </form></body></html>
Die Bibliothek CGI.pm formular.pl #!/usr/bin/perl use CGI; $form = new CGI; $anrede = $form->param("anrede"); $name = $form->param("name"); print "Content-Type: text/html\n\n"; print "<html><head></head><body>"; print "<h1>Hallo $anrede $name</h1>"; print "</body></html>";
Supermarkt der Module Man muss das Rad nicht immer neu erfinden! CPAN (Comprehensive Perl Archive Network) Meistens liegt die Lösung für das anstehende Programmierproblem bereits zum Download bereit! http://theoryx5.uwinnipeg.ca/CPAN/CPAN-search.html
Objektorientierung in Perl Bisher: Strukturierte Programmierung Jetzt: Objektorientierte Programmierung Ziel: Reale Welt in Programmen darzustellen! Objekte: Alle unsere Daten sind so genannte Objekte. Jedes Objekt hat stets eine eindeutige Identität sowie verschiedene Eigenschaften. Eigenschaften: - Zustand des Objekts - Verhalten des Objekts
Zustand des Objekts Zustand des Objekts kann durch mehrere Variablen dargestellt werden: Beispiel Auto: Typ, Modell, Farbe, Sitzplätze, Tankfüllung, Anzahl Gänge, Eingelegter Gang, Geschwindigkeit. Mit diesen Variablen können wir die meisten realen Zustände eines Autos darstellen: Beispiel: Ein stehender Mercedes 250TD mit vollem Tank. Alle Zustände ergeben sich je nach Belegung der Zustandsvariablen. Man nennt Variablen eines Objektes auch Eigenschaften.
Verhalten des Objekts Durch spezielle Funktionen können wir nun den Zustand des Objekts (Auto) verändern. Beispiel: gasgeben(), bremsen(), umlackieren(), tanken(). Die Funktionen die auf ein Objekt angewendet werden können, nennt man in der Objektorientierung Methoden. Merke: Wir haben es also immer mit einem Objekt zu tun, das verschiedene Eigenschaften besitzt, die den Zustand des Objekts symbolisieren, sowie verschiedene Methoden, mit denen dieser Zustand verändert werden kann.
Klassen Auf jedes Objekt können nur seine eigenen Methoden angewendet werden. Beispiel: Mit einem Auto kann man nun mal nicht einfach abheben, auch wenn es eine Funktion abheben() geben würde. Um einen solchen Missbrauch vorzubeugen, wird bei Objekten eine sog. Datenkapselung durchgeführt, das bedeutet, dass die Zustandsvariablen eines Objektes nur über die definierten Methoden des Objekts verändert werden können. Die Definition eines Objekts wird durch eine Klasse festgelegt. In dieser Klasse sind immer alle Methoden zu finden, die auf dieses Objekt angewendet werden können.
Konstruktor Um mit den definierten Klassen auch arbeiten zu können, ist es notwendig, mit einem Konstruktor Instanzen dieser Klassen zu erzeugen. Konstruktor: Methode der jeweiligen Klasse, die ein Objekt erzeugt. In vielen Programmiersprachen ist der Name des Konstruktors new().
Objektorientierung in Perl Um eine Klasse zu erzeugen, legt man ein Paket an. Pakete versammeln gleichartigen Code. Klassen besitzen ihre eigenen Namensräume unterscheiden ihren Code von anderen Paketen package Paketname;
Objektorientierung in Perl Um eine Methode zu erzeugen, schreibt man eine Subroutine. Methoden sind in Perl Subroutinen, die zu einer bestimmten Klasse gehören. Um eine Methode zu deklarieren schreibt man: package Paketname; sub subroutinenname { # Code } Man verwendet die Methode im Hauptprogramm folgendermaßen: my $variable ->subroutinenname();
Objektorientierung in Perl Um ein Objekt zu erzeugen, verbindet man eine Datenstruktur mit einer Klasse. Ein Objekt wird durch eine Referenz auf eine Datenstruktur realisiert. Mit der Funktion bless() teilt man Perl mit, dass ein Objekt zu einer Klasse gehört. bless() benötigt zwei Argumente: eine Referenz auf die jeweilige Datenstruktur und den Namen der Klasse. bless($referenz, klassenname)
Objektorientierung in Perl Erzeugen wir zuerst eine Referenz auf einen anonymen Hash: package Paketname; my $referenz = { ...=>..... } Durch bless() wird er zu einem Objekt der Klasse Paketname: bless($referenz, Paketname)
Objektorientierung in Perl Die Einträge im anonymen Hash sind die Attribute des Objekts. Da wir in unserem Programm oftmals mehrere Objekte einer Klasse verwenden wollen, umschließen wir diesen anonymen Hash mit einer Subroutine. Die Subroutine heisst Konstruktor. package Paketname; sub new { my $klassenname = shift; my $referenz = { ... => shift, ... => shift, } bless ($referenz, $klassenname); return $referenz; }
Objektorientierung in Perl Im Hauptprogramm rufen wir den Konstruktor wie eine Subroutine des Pakets Paketname auf: use Paketname; my $objekt = Paketname -> new (‘Argument1‘, ‘Argument2‘);
Objektorientierung in Perl package Paketname; sub new { my $klassenname = shift; my $referenz = { ... => shift, ... => shift, } bless ($referenz, $klassenname); return $referenz; } sub subroutinenname { my $referenz = shift return $referenz->{'Argument1'}; }
Die Klasse Schueler (OOSchueler.pm) package OOSchueler; sub new { # new-Methode (Klassenmethode) my ($class) = shift; # Klassennamen = class my ($referenz) = { # $referenz ist Verweis auf Hash 'snr' => shift, # snr = 1. Param 'name' => shift, # name = 2. Param 'punkte' => shift # punkte = 3. Param }; bless ($referenz, $class); # $self ist Objekt von $class return $referenz; # Rückgabe der erzeugten Referenz } sub getSchuelernummer { my ($referenz) = shift; # 1. Parameter ist Selbstreferenz return $referenz->{'snr'}; }
Die Klasse Schueler sub getName { my ($referenz) = shift; # 1. Parameter ist Selbstreferenz return $referenz->{'name'}; } sub getPunkte { my ($referenz) = shift; # 1. Parameter ist Selbstreferenz return $referenz->{'punkte'}; } sub printschueler { # print-Methode (Objektmethode) my ($referenz) = shift; print "$referenz->{'snr'} $referenz->{'name'} $referenz->{'punkte'}"; } return 1;
Verwendung der Klasse Schueler (Schueler.pl) use OOSchueler; # OO-Syntax $s2 = OOSchueler->new('1', ‚Maier', '90'); $s2->printschueler(); print "\n"; $s3 = OOSchueler->new('2', ‚Mueller', '100'); $s3->printschueler(); Anmerkung: Die Klassen (.pm) müssen anschließend im Perl – Bibliotheksverzeichnis gespeichert werden. Bei Suse Linux müsste das Verzeichnis folgendermaßen aussehen: /usr/lib/perl5/5.6.1/ Bei Windows müsste das Verzeichnis folgendermaßen aussehen: C:\Perl\lib\
Übungsaufgabe Schreiben Sie eine Klasse zur Speicherung von Filmen: Pflichtenheft: Filmtitel, FSK, Darsteller, Regie, Buch, Musik, Sprache, Erscheinungsdatum, ASIN.
Übungsaufgabe Verwenden Sie die Klasse: Filmtitel: Herr der Ringe – Die Gefährten FSK: Freigegeben ab 12 JahrenDarsteller:Elijah Wood, Ian McKellenRegie:Peter JacksonBuch:J. R. R. TolkienMusik:Howard Shore Infos zu diesem Titel• Sprache: Deutsch, Englisch• DVD Erscheinungstermin: 26. August 2003• ASIN: B00005U515
Vererbung Als Programmierer ist man danach bestrebt, bereits vorhandenen Code wieder zu verwenden. Vererbung ist eine Möglichkeit dazu: Eine Klasse erbt die Methoden und Eigenschaften einer anderen Klasse. Die Klasse, von der man erbt nennt man Basisklasse und die Klasse, die erbt, nennt man abgeleitete Klasse. Es wird also bereits vorhandener Code verwendet. So könnte zum Beispiel eine Klasse Fortbewegungsmittel heißen. In dieser gibt es die Methode Geschwindigkeit, etc. Will man nun eine neue Klasse Auto programmieren, dann kann man diese von Fortbewegungsmittel ableiten und die vorhandenen Methoden (z. B. Geschwindigkeit) wieder verwenden. Auch eine Klasse Fahrrad kann von Fortbewegungsmittel abgeleitet werden. Vererbung ist nichts anderes als das Angeben der Klassen, von denen geerbt werden soll. Das macht man über das Array @ISA - was von "is a" kommt: ("Auto is a Fortbewegungsmittel").
Vererbung – Fortbewegungsmittel.pm Ein Beispiel: Die Klasse Auto erbt von Fortbewegungsmittel: # Fortbewegungsmittel.pmpackage Fortbewegungsmittel; sub new { my $class = shift; my $referenz={}; bless($referenz, $class); return $referenz; } sub setGeschwindigkeit{ my $referenz = shift; $referenz ->{Geschwindigkeit} = shift; } sub getGeschwindigkeit{ my $referenz = shift; $referenz->{Geschwindigkeit}; } return 1;
Vererbung – Auto.pm # Auto.pm use Fortbewegungsmittel; package Auto; @ISA = qw( Fortbewegungsmittel ); sub new { my $class = shift; my $referenz={}; bless($referenz, $class); } sub setVerbrauch { my $referenz = shift; $referenz -> {Verbrauch} =shift; } sub getVerbrauch { my $referenz = shift; $referenz->{Verbrauch}; } return 1;
Vererbung – Auto.pm • Die Klasse Fortbewegungsmittel ist in die Klasse Auto eingebunden. Damit steht diese Klasse der Datei Auto.pm zur Verfügung. • Die Klasse Auto erbt von der Klasse Fortbewegungsmittel. Das wird mit @ISA = qw( Fortbewegungsmittel ); erreicht. Damit ist Fortbewegungsmittel die Basisklasse von Auto. Letzteren stehen alle Methoden aus Fortbewegungsmittel zur Verfügung (Hier sei erstmal new außer Acht gelassen.). • Es werden zwei neue Methoden hinzugefügt: setVerbrauch() und getVerbrauch().
Vererbung – bmw.pl # bmw.pluse Auto;my $bmw = Auto->new();$bmw->setVerbrauch(10);$bmw->setGeschwindigkeit(220);print "Verbrauch: ".$bmw->getVerbrauch."\n";print "Geschwindigkeit: ".$bmw->getGeschwindigkeit."\n";
Übungsaufgabe Programmieren Sie folgendes UML-Klassendiagramm!
boot.pm package boot;sub new {my $class = shift;my $referenz = {};bless($referenz, $class);refurn $referenz;}sub setGeschwindigkeit{my $referenz = shift;$referenz ->{Geschwindigkeit}= shift;}sub getGeschwindigkeit{my $referenz = shift;$referenz ->{Geschwindigkeit};}return1;
motorboot.pm use boot;package motorboot;@ISA = qw(boot);sub new{my $class = shift;my $referenz= {};bless($referenz, $class);}sub setLeistung {my $referenz = shift;$referenz ->{Leistung}=shift;}sub getLeistung {my $referenz = shift;$referenz ->{Leistung};}return1;
segelboot.pm use boot;package segelboot;@ISA = qw(boot);sub new {my $class = shift;my $referenz = {};bless($referenz, $class);}sub setSegelflaeche {my $referenz= shift;$referenz -> {Segelflaeche} = shift;}sub getSegelflaeche {my $referenz= shift;$referenz -> {Segelflaeche};}return1;
segel.pl use segelboot;use motorboot;my $boot1 = segelboot->new();$boot1->setGeschwindigkeit(100);$boot1->setSegelflaeche(50);print "Geschwindigkeit: ".$boot1->getGeschwindigkeit."\n";print "Segelflaeche: ".$boot1->getSegelflaeche."\n";my $boot2 = motorboot->new();$boot2->setGeschwindigkeit(120);$boot2->setLeistung(60);print "Geschwindigkeit: ".$boot2->getGeschwindigkeit."\n";print "Leistung: ".$boot2->getLeistung."\n";
Beispiel: Konto anlegen #Account.pm package Account; # Constructor. sub new { # $self is an anonymous hash. # my $self = {}; # Initialize data for this object. # $self->{USERNAME} = undef; $self->{NAME} = undef; $self->{HOMEDIR} = undef; $self->{SYSTEM} = undef; # Let the object know its class. # bless($self); return $self; } # Destructor. # sub DESTROY { print "Argh. Life was sweet.\n"; }
Konto anlegen # Data-access methods. # You can pass a parameter, in which case # the attribute gets set to the new value. # If you skip the parameter, the value is # returned. # sub username { # Extract first parameter--the object ref. # my $self = shift; # If there are any arguments left, then set value. # if (@_) { $self->{USERNAME} = shift; } return $self->{USERNAME}; }
Konto anlegen sub name { my $self = shift; # If there are any arguments left, then set value. # if (@_) { $self->{NAME} = shift; } return $self->{NAME}; } sub homedir { my $self = shift; # If there are any arguments left, then set value. # if (@_) { $self->{HOMEDIR} = shift; } return $self->{HOMEDIR}; }
Konto anlegen sub homesystem { my $self = shift; # If there are any arguments left, then set value. # if (@_) { $self->{HOMESYSTEM} = shift; } return $self->{HOMESYSTEM}; } # General methods. # Create a new user account. This is probably # the main reason to use this class. # sub create { # Fill in with code for UNIX or Windows NT. }
Konto anlegen # # Debugging methods. # sub print { my $self = shift; print "User: $self->{NAME}\n"; print "User name: $self->{USERNAME}\n"; print "Home machine: $self->{HOMESYSTEM}\n"; print "Home directory: $self->{HOMEDIR}\n"; } # By convention, end a package file with 1, # so the use or require command succeeds. 1;
Konto anlegen # # Use Account class. # use Account; # # Create new object. # $account = new Account; # # Set data into object. # $account->username("erc"); $account->homedir("/usr2/erc"); $account->homesystem("yonsen"); $account->name("Eric Foster-Johnson"); # Print out object data. $account->print; # useacnt2.pl