3. Was ist ein objektorientiertes Programm?
Im vorhergehenden Kapitel wurden Klassen erstellt - in UML und in 3 Programmiersprachen. Diese Klassen sind aber keine Programme (wenngleich man beim Erstellen der Klassen natürlich "programmiert")! Tatsächlich erzeugt man nichts anderes als neue (abstrakte) Datentypen, die man dann später in Programmen verwenden kann (genauso wie z.B. den Datentyp "ganze Zahl" (integer)). Ein Programm nennt man auch Anwendungsprogramm, Anwendungsskript oder Applikation.
Ein objektorientiertes Programm besteht aus einer Menge von Objektinstanzen (den Variablen), die durch Definitionen erzeugt werden, und aus einer Folge von Nachrichten, die an diese Objektinstanzen gesendet werden und die den Programmablauf steuern.
- Für die Definitionen stehen dem Programm viele Klassen zur Verfügung. Etliche dieser Klassen stammen aus bereits bestehenden Klassenbibliotheken, können aber auch zuvor erstellt worden sein.
- Alle Daten (Attribute) sind in Objektinstanzen versteckt, Zugriffsmethoden garantieren eine kontrollierte Änderung.
- Die Objektinstanzen kooperieren durch Senden von Nachrichten.
- Das Senden von Nachrichten aktiviert Methoden.
- Methoden starten das definierte Verfahren.
- In diesen Verfahren werden Attributwerte verwendet und wiederum Nachrichten an (andere) Instanzen versendet.
Variablenarten und -typen:
- In Smalltalk gibt es nur Klassen und Objekte. Alle Variablen sind Referenzen auf Objekte.
- In Java gibt es neben Klassen zusätzlich noch die elementaren Datentypen
byte
,short
,int
,long
,float
,double
,char
undboolean
, die jedoch in entsprechende Hüllklassen eingebettet werden können.
Variable von elementaren Datentypen sind Wertetypen, aber keine Objekte! Alle anderen Variablen sind immer Referenzen auf Objekte. - In C# gibt es Strukturen und Klassen.
Variablen von Strukturen sind Wertetypen, jene von Klassen sind Referenztypen. Jeder Typ ist ein Objekt.
Wie wird ein OO-Programm gestartet?
Ein Programm ist ein Objekt - man definiert also eine Klasse (z.B. die Klasse "Programm
"), erzeugt eine erste Instanz und sendet an diese eine erste Nachricht, die eine Methode anfordert (z.B. die Methode "main
"), die den Programmablauf steuert.
- In Java und C# ist ein Programm ein Klassenobjekt mit einer öffentlichen Klassenmethode ohne Rückgabewert und der Signatur "
main(String[ ])
" (bzw. "Main(String[ ])
" in C#).
Es ist keine Programminstanz notwendig - nach dem Laden der Programmklasse sendet das System die Nachricht "main
" (bzw. "Main
") direkt an die Programmklasse. - In Smalltalk wird in der Entwicklungsumgebung VisualWorks ein Programm einfach in einen sogenannten Workspace geschrieben und mit dem Menüpunkt "
doIt
" durchgeführt (der Workspace kann als Programmklasse und "doIt
" als "main
"-Methode aufgefasst werden).
In Java und C# könnte man aus Bequemlichkeitsgründen in jeder Klasse eine main
- (bzw. Main
-)Methode zum Testen der Klasse definieren (man bräuchte dann keine eigene Programmklasse zum Testen). Diese Vorgangsweise widerspricht aber sämtlichen OOP-Kriterien und sollte daher unbedingt vermieden werden! Methoden beschreiben ja das Verhalten eines Objekts - was hat also beispielsweise in einer Klasse "Person
", die eine natürliche Person (einen Menschen) beschreibt, eine Ablaufsteuerungsmethode für ein Computerprogramm zu suchen?
- Bem.:
- Man kann in einer OO-Sprache natürlich auch prozedural programmieren und so keinen einzigen Vorteil der OO-Konzepte realisieren. Ein prozedurales Beispiel ist eine Programmklasse, in der alle Variablen, die das Programm braucht, Attribute sind und in der es nur 1 (öffentliche) Methode gibt, die die gesamte Funktionalität realisiert (d.h. in dieser Methode werden alle Algorithmen definiert).
- Umgekehrt kann man aber auch in Nicht-OO-Sprachen viele OO-Konzepte realisieren! Voraussetzung ist dabei eine strenge Programmierdisziplin, weil diese Sprachen die OO-Konzepte ja nicht unterstützen - man vergleiche dies mit dem strukturierten Programmieren in einer Assembler-Sprache. In Kap.12 wird dies am Beispiel von PL/I gezeigt.
3.1 Einfache Programmbeispiele für "Zähler", "Datum", "Auto"
Die nachfolgenden Programme verwenden die in Kap.2.5 definierten Klassen.
- Zu den Java-Programmen:
- ProgrammZaehler
- ProgrammZaehler2
- AutoTesten
- ProgrammAutoTesten
- DatumTesten
- ProgrammDatumTesten
- ProgrammZaehler2
- Zu den C#-Programmen:
- ProgrammZaehler
- ProgrammZaehler2
- AutoTesten
- ProgrammAutoTesten
- DatumTesten
- ProgrammDatumTesten
- ProgrammZaehler2
- Zu den Smalltalk-Programmen:
- ZaehlerProgramm
- Zaehler2Programm
- AutoProgramm
- DatumProgramm
- Zaehler2Programm
Java
Programmklasse ProgrammZaehler |
---|
/* * ProgrammZaehler.java */ package at.beringer.oopBuch.einfacheBsp; /** Applikation zum Testen der Klasse 'Zaehler'. <p> Hinweis: Diese Programmklasse beinhaltet die Applikation zum Testen - besser ist es, eine eigene Applikationsklasse zu definieren. </p> <hr /> @since August 1999 @see Zaehler @see ProgrammZaehler2 @see Zaehler3Testen @author Beringer Alfred */ public class ProgrammZaehler { // ------------------------------------------------------------------------- /** Der Einstiegspunkt für die Anwendung. @param args Kommandozeilenparameter */ public static void main(String[ ] args) { Zaehler z; z = new Zaehler(); z.erhoehen(); System.out.println(z.getWert()); } } |
Java
Programmklasse ProgrammZaehler2 |
---|
/* * ProgrammZaehler2.java */ package at.beringer.oopBuch.einfacheBsp; /** Applikation zum Testen der Klasse 'Zaehler2'. <p> Hinweis: Diese Programmklasse beinhaltet die Applikation zum Testen - besser ist es, eine eigene Applikationsklasse zu definieren. </p> <hr /> @since August 1999 @see Zaehler2 @see ProgrammZaehler @see Zaehler3Testen @author Beringer Alfred */ public class ProgrammZaehler2 { // ------------------------------------------------------------------------- /** Der Einstiegspunkt für die Anwendung. @param args Kommandozeilenparameter */ public static void main(String[ ] args) { Zaehler2 z; z = new Zaehler2(); z.erhoehen(); System.out.println("Wert = " + z.getWert()); // liefert 1 for (int k = 1; k <= 3; k++) { for (int i = 1; i <= 80; i++) { z.erhoehen(); } System.out.println("Wert = " + z.getWert()); // liefert 81,61,41 } // Zugriff auf Klassenvariable: System.out.println("Endwert = " + Zaehler2.getEndwert()); // liefert 99 Zaehler2.setEndwert(40); System.out.println("Endwert = " + Zaehler2.getEndwert()); // liefert 40 } } |
C#
Programmklasse ProgrammZaehler |
---|
/* * ProgrammZaehler.cs */ using System; namespace Beringer.oopBuch.EinfacheBsp { /** <summary> Programmklasse (Applikation) zum Testen der Klasse 'Zaehler'. <p> Seit: November 2004 </p> <seealso cref="Zaehler" /> <seealso cref="ProgrammZaehler2" /> <seealso cref="Zaehler3Testen" /> Autor: Beringer Alfred </summary> <remarks> Diese Programmklasse beinhaltet die Applikation zum Testen - besser ist es, eine eigene Applikationsklasse zu definieren. </remarks> */ public class ProgrammZaehler { /** -------------------------------------------------------------------- <summary> Der Einstiegspunkt für die Anwendung. </summary> <param name="args"> Kommandozeilenparameter </param> */ public static void Main(String[] args) { Zaehler z; z = new Zaehler(); z.Erhoehen(); Console.WriteLine(z.Wert); #if DEBUG Console.ReadLine(); #endif } } } |
C#
Programmklasse ProgrammZaehler2 |
---|
/* * ProgrammZaehler2.cs */ using System; namespace Beringer.oopBuch.EinfacheBsp { /** <summary> Programmklasse (Applikation) zum Testen der Klasse 'Zaehler2'. <p> Seit: November 2004 </p> <seealso cref="Zaehler2" /> <seealso cref="ProgrammZaehler" /> <seealso cref="Zaehler3Testen" /> Autor: Beringer Alfred </summary> <remarks> Diese Programmklasse beinhaltet die Applikation zum Testen - besser ist es, eine eigene Applikationsklasse zu definieren. </remarks> */ public class ProgrammZaehler2 { /** -------------------------------------------------------------------- <summary> Der Einstiegspunkt für die Anwendung. </summary> <param name="args"> Kommandozeilenparameter </param> */ public static void Main(String[ ] args) { Zaehler2 z; z = new Zaehler2(); z.Erhoehen(); Console.WriteLine("Wert = " + z.Wert); // liefert 1 for (int k = 1; k <= 3; k++) { for (int i = 1; i <= 80; i++) { z.Erhoehen(); } Console.WriteLine("Wert = " + z.Wert); // liefert 81,61,41 } // Zugriff auf Klassenvariable: Console.WriteLine("Endwert = " + Zaehler2.Endwert()); // liefert 99 Zaehler2.Endwert(40); Console.WriteLine("Endwert = " + Zaehler2.Endwert()); // liefert 40 #if DEBUG Console.ReadLine(); #endif } } } |
Smalltalk (Workspace)
Programm Zaehler (Workspace) |
---|
| z | z := Zaehler new. z erhoehen. z wert. "<printIt> liefert 1" |
Smalltalk (Workspace)
Programm Zaehler2 (Workspace) |
---|
| z | z := Zaehler2 new. z erhoehen. 1 to: 3 do: [ :k | 1 to: 80 do: [ :i | z erhoehen. ]. Transcript cr; show: z wert printString. ]. |
Die Ausgabe des ersten Programms (Zaehler) liefert:
1
Die Ausgabe des zweiten Programms (Zaehler2) liefert:
81 61 41
Da in Java und C# die main
- (bzw. Main
-)Methode eine Klassenmethode ist, müssen eventuelle Programmeigenschaften als Klassenattribute definiert werden. Daher ist es üblich (und guter OO-Programmierstil), eine eigene Applikationsklasse mit einer Instanzmethode zum Starten der Applikation zu definieren. Die Programmklasse erzeugt nur mehr eine Applikationsinstanz und ruft für diese die Startmethode auf. In Smalltalk steht die Anwendung im Workspace. Die nachfolgenden Beispiele zeigen diese Vorgangsweise:
Java - Testklasse
Klasse AutoTesten |
---|
/* * AutoTesten.java */ package at.beringer.oopBuch.einfacheBsp; /** Applikation zum Testen der Klasse 'Auto'. <hr /> @since Jänner 2002 @version August 2007 (eigene Programmklasse) @version <br />Juli 2012 (PKW-Klasse umbenennen auf 'Auto') @see Auto @see Person @see ProgrammAutoTesten @author Beringer Alfred */ public class AutoTesten { // ------------------------------------------------------------------------- // Instanzmethoden // ------------------------------------------------------------------------- /** Start-Methode zum Testen der Applikation. */ public void start() { Auto herbie; // Referenz für Auto-Instanz definieren herbie = new Auto(); // Auto-Instanz erzeugen herbie.setBesitzer(new Person(1980, 'M')); herbie.setFarbe("blau"); // Farbe ändern herbie.raufschalten(); // 2. Gang herbie.zeigeInhalt(); Auto.setMwstSatz(20); // Mehrwertsteuersatz ändern herbie.getBesitzer().aendernVorname("Hugo"); // Vorname Besitzer ändern herbie.raufschalten(); // 3. Gang herbie.raufschalten(); // 4. Gang herbie.zeigeInhalt(); herbie.runterschalten(); // 3. Gang herbie.beschleunigen(); herbie.zeigeInhalt(); herbie.bremsen(); herbie.zeigeInhalt(); System.out.println( "--------------------------------------------------------"); System.out.println( "Auto-Daten mit Hilfe der Methode 'toString()' anschauen:"); System.out.println(herbie); } } |
Java - Programmklasse
Programmklasse ProgrammAutoTesten |
---|
/* * ProgrammAutoTesten.java */ package at.beringer.oopBuch.einfacheBsp; /** Programmklasse (Applikation) zum Testen der Klasse 'AutoTesten'. <hr /> @since August 2007 @version Juli 2012 (PKW-Klasse umbenennen auf 'Auto') @see AutoTesten @author Beringer Alfred */ public class ProgrammAutoTesten { // ------------------------------------------------------------------------- /** Der Einstiegspunkt für die Anwendung. @param args Kommandozeilenparameter */ public static void main(String[ ] args) { AutoTesten test = new AutoTesten(); test.start(); } } |
C# - Testklasse
Klasse AutoTesten |
---|
/* * AutoTesten.cs */ using System; namespace Beringer.oopBuch.EinfacheBsp { /** <summary> Applikation zum Testen der Klasse 'Auto'. <p> Seit: November 2004 <br /> Version: Juli 2012 (PKW-Klasse umbenennen auf 'Auto') </p> <seealso cref="Auto" /> <seealso cref="Beringer.oopBuch.EinfacheBspProgramme.ProgrammAutoTesten"/> Autor: Beringer Alfred </summary> */ public class AutoTesten { /** -------------------------------------------------------------------- <summary> Start-Methode zum Testen der Applikation. </summary> */ public void Start() { Auto herbie; // Referenz für Auto-Instanz definieren herbie = new Auto(); // Auto-Instanz erzeugen herbie.Besitzer = new Person(1980, 'M'); herbie.Farbe = "blau"; // Farbe ändern herbie.Raufschalten(); // 2. Gang herbie.ZeigeInhalt(); Auto.MwstSatz(20); // Mehrwertsteuersatz ändern herbie.Besitzer.AendernVorname("Hugo"); // Vorname Besitzer ändern herbie.Raufschalten(); // 3. Gang herbie.Raufschalten(); // 4. Gang herbie.ZeigeInhalt(); herbie.Runterschalten(); // 3. Gang herbie.Beschleunigen(); herbie.ZeigeInhalt(); herbie.Bremsen(); herbie.ZeigeInhalt(); Console.WriteLine( "--------------------------------------------------------"); Console.WriteLine( "Auto-Daten mit Hilfe der Methode 'ToString()' anschauen:"); Console.WriteLine(herbie); #if DEBUG Console.ReadLine(); #endif } } } |
C# - Programmklasse
Programmklasse ProgrammAutoTesten |
---|
/* * ProgrammAutoTesten.cs */ using System; namespace Beringer.oopBuch.EinfacheBsp { /** <summary> Programmklasse (Applikation) zum Testen der Klasse 'AutoTesten'. <p> Seit: August 2007 <br /> Version: Juli 2012 (PKW-Klasse umbenennen auf 'Auto') </p> <seealso cref="AutoTesten" /> Autor: Beringer Alfred </summary> */ public class ProgrammAutoTesten { /** -------------------------------------------------------------------- <summary> Der Einstiegspunkt für die Anwendung. </summary> <param name="args"> Kommandozeilenparameter </param> */ public static void Main(String[] args) { AutoTesten test = new AutoTesten(); test.Start(); } } } |
Smalltalk (Workspace)
Programm AutoTesten (Workspace) |
---|
| herbie | "Referenz definieren" herbie := Auto new. "Auto-Instanz erzeugen" herbie besitzer: (Person newGeburtsjahr: 1980 geschlecht: 'M'). herbie farbe: 'blau'. "Farbe ändern" herbie raufschalten. "2. Gang" herbie zeigeInhalt. Auto mwstSatz: 20. "Mehrwertsteuersatz ändern" herbie besitzer aendernVorname: 'Hugo'. "Vorname Besitzer ändern" herbie raufschalten. "3. Gang" herbie raufschalten. "4. Gang" herbie zeigeInhalt. herbie runterschalten. "3. Gang" herbie beschleunigen. herbie zeigeInhalt. herbie bremsen. herbie zeigeInhalt. Transcript clear; show: '-----------------------------------------------------'. Transcript cr; show: 'Auto-Daten mit Hilfe der Methode "printOn" anschauen:'. Transcript cr; show: herbie printString |
Java - Testklasse
Klasse DatumTesten |
---|
/* * DatumTesten.java */ package at.beringer.oopBuch.einfacheBsp; /** Applikation zum Testen der Klasse 'Datum'. <hr /> @since August 1999 @version August 2007 (eigene Programmklasse) @see Datum @see ProgrammDatumTesten @author Beringer Alfred */ public class DatumTesten { // ------------------------------------------------------------------------- // Instanzmethoden // ------------------------------------------------------------------------- /** Start-Methode zum Testen der Applikation. */ public void start() { int jj = 2000; Datum today = new Datum(), hdat, dat = new Datum(1950,4,25); if (Datum.istSchaltjahr(jj)) { System.out.println(jj + " = Schaltjahr"); } else { System.out.println(jj + " = kein Schaltjahr"); } System.out.println(); System.out.println("today = " + today); if (today.istSchaltjahr()) { System.out.println(today.jj() + " ist ein Schaltjahr"); } else { System.out.println(today.jj() + " ist kein Schaltjahr"); } System.out.println("Lfd. Tag des Jahres = " + today.lfdTagDesJahres()); System.out.println(); System.out.println("dat = " + dat); System.out.println(); System.out.println("heutiger Tag = " + Datum.heute().tt()); System.out.println("aktueller Monat = " + Datum.heute().monatsname()); hdat = Datum.heute(); System.out.println("hdat = " + hdat); hdat = (Datum)dat.clone(); System.out.println("hdat = " + hdat); } } |
Java - Programmklasse
Programmklasse ProgrammDatumTesten |
---|
/* * ProgrammDatumTesten.java */ package at.beringer.oopBuch.einfacheBsp; /** Programmklasse (Applikation) zum Testen der Klasse 'DatumTesten'. <hr /> @since August 2007 @see DatumTesten @author Beringer Alfred */ public class ProgrammDatumTesten { // ------------------------------------------------------------------------- /** Der Einstiegspunkt für die Anwendung. @param args Kommandozeilenparameter */ public static void main(String[ ] args) { DatumTesten test = new DatumTesten(); test.start(); } } |
C# - Testklasse
Klasse DatumTesten |
---|
/* * DatumTesten.cs */ using System; namespace Beringer.oopBuch.EinfacheBsp { /** <summary> Applikation zum Testen der Klasse 'Datum'. <p> Seit: November 2004 </p> <seealso cref="Datum" /> <seealso cref="Beringer.oopBuch.EinfacheBspProgramme.ProgrammDatumTesten"/> Autor: Beringer Alfred </summary> */ public class DatumTesten { /** -------------------------------------------------------------------- <summary> Start-Methode zum Testen der Applikation. </summary> */ public void Start() { int jj = 2000; Datum today = new Datum(), hdat, dat = new Datum(1950,4,25); if (Datum.IstSchaltjahr(jj)) { Console.WriteLine(jj + " = Schaltjahr"); } else { Console.WriteLine(jj + " = kein Schaltjahr"); } Console.WriteLine(); Console.WriteLine("today = " + today); if (today.IstSchaltjahr()) { Console.WriteLine(today.JJ + " ist ein Schaltjahr"); } else { Console.WriteLine(today.JJ + " ist kein Schaltjahr"); } Console.WriteLine("Lfd. Tag des Jahres = " + today.LfdTagDesJahres()); Console.WriteLine(); Console.WriteLine("dat = " + dat); Console.WriteLine(); Console.WriteLine("heutiger Tag = " + Datum.Heute().TT); hdat = Datum.Heute(); Console.WriteLine("hdat = " + hdat); hdat = (Datum)dat.Clone(); Console.WriteLine("hdat = " + hdat); #if DEBUG Console.ReadLine(); #endif } } } |
C# - Programmklasse
Programmklasse ProgrammDatumTesten |
---|
/* * ProgrammDatumTesten.cs */ using System; namespace Beringer.oopBuch.EinfacheBsp { /** <summary> Programmklasse (Applikation) zum Testen der Klasse 'DatumTesten'. <p> Seit: August 2007 </p> <seealso cref="DatumTesten" /> Autor: Beringer Alfred </summary> */ public class ProgrammDatumTesten { /** -------------------------------------------------------------------- <summary> Der Einstiegspunkt für die Anwendung. </summary> <param name="args"> Kommandozeilenparameter </param> */ public static void Main(String[ ] args) { DatumTesten test = new DatumTesten(); test.Start(); } } } |
Smalltalk (Workspace)
Programm DatumTesten (Workspace) |
---|
| jj today dat | jj := 2000. today := Datum heute. dat := Datum newJahr: 1950 monatsNummer: 4 tag: 25. Datum istSchaltjahr: jj. Transcript show: 'today = '; show: today tt printString; show: '.'; show: today mm printString; show: '.'; show: today jj printString; cr. today istSchaltjahr. today lfdTagDesJahres. Transcript show: 'dat = '; show: dat tt printString; show: '.'; show: dat mm printString; show: '.'; show: dat jj printString; cr. Transcript show: 'heutiger Tag = '; show: Datum heute tt printString; cr. |
- Weiter
- zu den Klassenbeispielen von Kapitel 4
- zu den Java-Klassenbeispielen von Kapitel 5.19.1 (Exceptions)
- zu den Java-Klassenbeispielen von Kapitel 6 (Ein-/Ausgabe von Daten)
- zu den Java-Klassenbeispielen von Kapitel 7 (GUI)
- zu Kapitel 8 (JDBC)
- zu den C#-Klassenbeispielen von Kapitel 9.19.1 (Exceptions)
- zu den C#-Klassenbeispielen von Kapitel 10 (Ein-/Ausgabe von Daten)
- zu Kapitel 12 (PL/I)
- zu Kapitel 13 (Reservierte Worte)
- zu den Java-Klassenbeispielen von Kapitel 5.19.1 (Exceptions)
- Zurück
- zum Anfang dieses Kapitels
- zum Inhaltsverzeichnis
- zu Kapitel 1
- zu den Klassenbeispielen von Kapitel 2
- zur Parameterübergabe (Kapitel 2.7.1)
- zum Inhaltsverzeichnis
- Zur
- Java-Dokumentation der Java-Beispiele