Zur Haupt­na­vi­ga­ti­on sprin­gen [Alt]+[0] Zum Sei­ten­in­halt sprin­gen [Alt]+[1]

Ob­jek­te und Klas­sen

Pro­gram­mier­spra­chen un­ab­hän­gig soll nun mög­lichst genau be­schrei­ben wer­den, was unter einem Ob­jekt zu ver­ste­hen ist. Dabei soll (so­weit mög­lich und sinn­voll) eine Ob­jekt-Ana­lo­gie aus der rea­len Welt be­trach­tet wer­den. Sie soll uns hel­fen, die abs­trak­ten Be­grif­fe an­schau­li­cher zu ma­chen.

Zu­nächst ist ein Ob­jekt ein Be­stand­teil des Pro­gramms. Es be­steht aus At­tri­bu­ten und Me­tho­den. In den At­tri­bu­ten ist der Zu­stand des Ob­jekts fest­ge­hal­ten, durch die Me­tho­den wird das Ver­hal­ten des Ob­jekts be­stimmt. In der Regel sind die At­tri­bu­te von außen nicht er­kenn­bar. Da­durch sind diese Zu­stands-Daten ge­schützt.

Al­ler­dings er­laubt das Ob­jekt, eine „An­fra­ge“ zu stel­len. Diese An­fra­ge ist nichts an­de­res, als dass von außen eine Me­tho­de des Ob­jekts „auf­ge­ru­fen“ wird.

Sche­ma­tisch:

Schema

Durch diese An­fra­ge wird die Me­tho­de aktiv und lie­fert dem An­fra­gen­den, ohne nach außen zu zei­gen, was im In­ne­ren des Ob­jekts vor­geht, ent­we­der als „Ant­wort“ die ge­wünsch­ten Daten oder die ge­wünsch­te Ak­ti­on wird (even­tu­ell ohne Daten-Rück­ga­be) aus­ge­führt.

Um die neuen Be­grif­fe etwas kla­rer zu ma­chen, wer­den wir nun ver­su­chen, ein rea­les Ob­jekt „(Röh­ren bzw. CRT-)Fern­seh­ap­pa­rat“ zu mo­del­lie­ren.

Zu­nächst hat der kon­kre­te CRT-Fern­se­her, 32 Zoll, (das Ob­jekt der Klas­se CRT- Fern­se­her) fest­ste­hen­de (Daten-)At­tri­bu­te. Zum Bei­spiel die Größe der Bild­schirm­dia­go­na­len, die Ge­rä­te­tie­fe, die Farbe etc. Dies sind ge­wiss Daten, die sich durch eine An­fra­ge nicht än­dern las­sen, auch wenn das man­cher gerne hätte....

Es gibt aber wei­te­re At­tri­bu­te: Ein­ge­stell­ter Kanal, Laut­stär­ke, Hel­lig­keit des Bil­des….

Häu­fig kann man hier einen be­stimm­ten Wert, sagen wir zwi­schen 0 und 100 wäh­len. Damit das klappt, muss das Ob­jekt Me­tho­den haben, wie Kanal wech­seln, Laut­stär­ke oder Hel­lig­keit ver­än­dern und so wei­ter.

Was genau an Än­de­run­gen der (phy­si­ka­li­schen) Daten innen vor­ge­nom­men wird, weiß der An­fra­gen­de nicht. Er muss es auch nicht wis­sen. At­tri­bu­te, wie „be­nö­tig­te Leis­tung“ sind pri­va­te und daher ge­kap­selt. Das be­deu­tet, dass man von außen diese Werte nicht „sehen“ und di­rekt be­ein­flus­sen kann. Die Zahl für die ein­ge­stell­te Laut­stär­ke (z.B. 45) ist pri­va­te und nur nach außen sicht­bar, wenn es eine zu­ge­hö­ri­ge get-Me­tho­de gibt.

Wenn eine Elek­tro­nik-Firma einen be­son­ders gro­ßen LCD-Fern­seh­ap­pa­rat bauen will, muss sie das Gerät dabei nicht neu er­fin­den! Auch bei dem be­son­ders gro­ßen Gerät sind doch viele Me­tho­den und At­tri­bu­te gleich oder ähn­lich wie bei den klei­ne­ren Ge­rä­ten. Daher tut man gut daran, wenn man zu­nächst mög­lichst all­ge­mein eine Be­schrei­bung (Bau­plan) für das Gerät Fern­se­her fest­schreibt. In OOP heißt eine sol­che all­ge­mei­ne Be­schrei­bung eine Klas­se.

Ein Fern­seh­ap­pa­rat be­steht im We­sent­li­chen aus einem Ge­häu­se (mit Netz­teil, Emp­fangs­teil, Ein-und Aus­gän­gen und Be­dien­ele­men­ten), der Bild­röh­re und aus dem Audio-Teil. Eine Fern­be­die­nung liegt meist eben­falls bei. Der Ein­fach­heit hal­ber wer­den zur Ver­an­schau­li­chung von Klas­sen zu­nächst nur die Bild­schir­me be­trach­tet. Es gibt zum Bei­spiel CRT-(das sind die alten Bild­röh­ren), LCD-, Plas­ma- und Am­bi­light-Bild­schir­me (Hin­ter­grund-Licht-Bild­schir­me). All diese Bild­schir­me haben Ge­mein­sam­kei­ten, wie die Tat­sa­che, dass es eine Bildschirm­diagonale (meist in Zoll) gibt. Au­ßer­dem kann man bei allen die Hel­lig­keit und den Kon­trast re­geln. Eine abs­trak­te Bild­röh­re, die alle Ge­mein­sam­kei­ten aus sich bün­delt, gibt es in Wirk­lich­keit na­tür­lich nicht. Eine abs­trak­te Klas­se Bild­schirm sehr wohl.

Mit Hilfe der UML kann man sie gra­fisch dar­stel­len. Wir ver­wen­den hier­zu, wie auch zum pro­gram­mie­ren, den Ja­va­Edi­tor von Ger­hard Röhner. Und so sieht eine Klas­se im UML-Dia­gramm aus:

Klasse im UML-Diagramm

Damit die Über­sicht­lich­keit nicht lei­det, wer­den hier nur we­ni­ge ty­pi­sche At­tri­bu­te ver­wen­det.

Der Java-Edi­tor er­zeugt den pas­sen­den Code-Rumpf selb­stän­dig. Hier wur­den nur im Kon­struk­tor die An­fangs­wer­te von kon­trast und hel­lig­keit von Hand er­gänzt:


  public Bildschirm(int diagonale) {
      this.diagonale = diagonale;
      this.helligkeit = 10;
      this.kontrast = 10;
  }

Nach De­fi­ni­ti­on nennt man eine Klas­se abs­trakt, wenn min­des­tens eine ihrer Me­tho­den nicht ex­pli­zit an­ge­ben ist. Sol­che Me­tho­den, bei denen nur der Me­tho­den­rumpf an­ge­legt ist, nennt man abs­trak­te Me­tho­den (im Bild oben kur­siv dar­ge­stellt: get­Typ():String). Mit der Klas­se Bild­schirm will man ja nur fest­hal­ten, was alle Bild­schir­me ge­mein­sam haben, ohne dabei an ein kon­kre­tes Gerät zu den­ken.

Man kann es auch so aus­drü­cken: Die Klas­se Bild­schirm ist in die­sem Sinn eine abs­trak­te Klas­se, weil sich in den „Bau­plä­nen“ für Bild­schirm le­dig­lich der Name für die Me­tho­de get­Typ() ver­merkt ist. Alles an­de­re wäre ja auch Un­sinn, denn erst in den ab­ge­lei­te­ten Klas­sen, wie Crt­Bild­schirm, Lcd­Bild­schirm etc. kann eine kon­kre­ter An­wei­sung für diese Me­tho­de for­mu­liert wer­den, denn die­ser ruft ja immer den je­wei­li­gen Typ auf.

Weil es den abs­trak­ten Bild­schirm nicht gibt, kann man sinn­vol­ler­wei­se auch kein Ob­jek­te aus die­ser Klas­se er­zeu­gen. Ein Ob­jekt wäre ja der Re­prä­sen­tant für einen rea­len Bild­schirm. Aber man kann na­tür­lich jetzt abs­trak­te Bild­schir­me, wie den Plas­ma-Bild­schirm aus der Bild­schirm-Klas­se ab­lei­ten.

abgeleitete Klassen der Bildschirm-Klasse

Die Basis-Klas­se Bild­schirm hat meh­re­re ab­ge­lei­te­te Klas­sen: Am­bi­light­Bild­schirm, Crt­Bild­schirm, Lcd­Bild­schirm und Plas­ma­Bild­schirm (letz­te­rer ist im nächs­ten Bild nicht dar­ge­stellt).

Aus die­sen las­sen sich wei­te­re Klas­sen ab­lei­ten. Zum Bei­spiel aus Crt­Bild­schirm Crt­Bild­schir­m50Hz und Crt­Bild­schir­m100Hz. Und immer erben die ab­ge­lei­te­ten Klas­sen die At­tri­bu­te und Me­tho­den der Basis-Klas­sen, d.h. ein Ob­jekt aus der ab­ge­lei­te­ten Klas­se ent­hält somit immer auch At­tri­bu­te und Me­tho­den der Ba­sis­klas­se.

abgeleitete Klassen

Im obi­gen Bild sind per Rechtsklick auf die Klas­se Am­bi­light­Bild­schirm und Lcd­Bild­schirm (Kon­text­me­nü) ein­zel­ne Ob­jek­te er­zeugt („in­stan­zi­iert“) wor­den. Die Ob­jek­te haben die Namen am­bi­light­Bild­schir­m1 und lcd­Bild­schir­m1. Per Rechtsklick auf ein Ob­jekt, kann man nun die vor­han­de­nen Me­tho­den tes­ten. So ließe sich bei­spiels­wei­se durch die Wahl von void setHel­lig­keit(int Hel­lig­keit) der Wert für die Hel­lig­keit ein­stel­len. („void“ be­deu­tet nur, dass kein Rück­ga­be­wert er­war­tet wird). So wie bei einem ech­ten Bild­schirm auch be­reits Vor­rich­tun­gen für die Hel­lig­keits­ein­stel­lung im­ple­men­tiert sind.

Das kann man di­rekt im UML-Dia­gramm tes­ten, denn da­nach soll­te der Wert der Hel­lig­keit im ent­spre­chen­den Ob­jekt den Wert an­neh­men, den man ein­ge­stellt hat.

Wird, wie im Bild oben per Rechtsklick ein Ob­jekt lcd­Bild­schir­m1 er­zeugt, so be­deu­tet dies zu­nächst, dass im „Heap“ (= be­stimm­ter Be­reich des RAM) nach Vor­ga­be der Klas­sen­de­fi­ni­ti­on durch den Kon­struk­tor kon­kre­te Werte in die vor­her un­de­fi­nier­ten Spei­cher­in­hal­te ge­schrie­ben wer­den. Die Klas­sen­de­fi­ni­ti­on kann man sich wie einen Stem­pel vor­stel­len, der bei jedem neu zu bil­den­den Ob­jekt einen neuen Ab­druck im Heap hin­ter­lässt. Die­ser Ab­druck be­inhal­tet den Spei­cher­be­darf. Jedes Ob­jekt hat auf diese Weise sei­nen „ei­ge­nen“ Spei­cher­in­halt. In den Spei­cher wer­den dann zum Bei­spiel die At­tri­bu­te ein­ge­tra­gen. Erst da­durch kön­nen kon­kre­te Be­rech­nun­gen mit dem Ob­jekt durch­ge­führt wer­den.

Klas­sen be­schrei­ben also die ge­mein­sa­men At­tri­bu­te und Me­tho­den einer Menge von gleich­ar­ti­gen Ob­jek­ten. Durch die Klas­sen­de­fi­ni­ti­on wer­den „Vor­la­gen“ (Stem­pel) für die nö­ti­gen Spei­cher­re­ser­vie­run­gen der zu er­zeu­gen­den Ob­jek­te er­stellt.

Ob­jek­te sind die kon­kre­ten er­zeug­ten Ex­em­pla­re einer Klas­se. In un­se­rem Bei­spiel ist also der reale, mit Hän­den zu grei­fen­de CRT-Fern­se­her, 32 Zoll ein Ob­jekt der Klas­se CRT-Fern­se­her. Es kann viele ver­schie­de­ne Ob­jek­te einer Klas­se geben.

Ob­jek­te be­nö­ti­gen also Platz im Spei­cher. Die­sen Platz be­sorgt der Kon­struk­tor der Klas­se. Wird das Ob­jekt nicht mehr be­nö­tigt, sorgt der De­struk­tor dafür, dass der Platz wie­der frei­ge­ge­ben wird. Ver­wen­det man als Pro­gram­mier­spra­che Java, so hat man mit den bei­den nicht viel zu tun. Der Gar­ba­ge Collec­tor sorgt von Zeit zu Zeit au­to­ma­tisch dafür, dass nicht mehr be­nö­tig­te Ex­em­pla­re ge­löscht wer­den. Ruft man in Java kei­nen ei­ge­nen Kon­struk­tor auf, so wird bei der Bil­dung eines Ex­em­plars au­to­ma­tisch ein Stan­dard-Kon­struk­tor be­nutzt. Will man al­ler­dings bei der Er­zeu­gung des Ob­jekts ei­ni­ge Ei­gen­schaf­ten in­itia­li­sie­ren, so über­schreibt man den Stan­dard-Kon­struk­tor (siehe nächs­ter Ab­schnitt).

Java-Editor

Es ist durch­aus von Vor­teil, wenn man die Klas­sen mit ihren At­tri­bu­ten und Me­tho­den im UML-Tool des Java-Edi­tors er­zeugt. Ein Bei­spiel: In dem Mo­ment, in dem man die Klas­se AmbilightBild­schirm er­zeugt, legt man im Programm­ordner eine Java-Datei glei­chen Na­mens an:

Am­bi­light­Bild­schirm.java

Im Klas­sen-Edi­tor kann man dann alle ge­wünsch­ten At­tri­bu­te und Me­tho­den ge­stal­ten. Auch die Me­tho­de Kon­struk­tor wird hier den ei­ge­nen Wün­schen an­ge­passt (siehe Bild unten). Auch hier wird der Code-Rumpf au­to­ma­tisch er­zeugt. Von Hand wer­den da­nach nur noch die Er­gän­zun­gen ge­schrie­ben, die der Edi­tor nicht er­ra­ten kann.

Java-Editor von Gerhard Röhner (javaeditor.org)

Java-Edi­tor von Ger­hard Röh­ner (ja­va­edi­tor.org)

Han­delt es sich bei der neu er­zeug­ten Klas­se um eine ab­ge­lei­te­te Klas­se, so trägt man dies unter dem Tab „Klas­se“ ein. Hier kann auch ein­ge­stellt wer­den, ob die Klas­se abs­trakt sein soll oder nicht.

UML-Klassen-Editor

Im fol­gen­den Code-Lis­ting für die Klas­se Am­bi­light­Bild­schirm sind die von Hand ein­ge­tra­ge­nen Teile durch Fett­schrift her­vor­ge­ho­ben. Die au­to­ma­ti­schen Kom­men­ta­re sind in blau­er Schrift:


  public class AmbilightBildschirm extends Bildschirm {

    // Anfang Attribute
    protected int umgebungslicht;
    // Ende Attribute

    public AmbilightBildschirm(int diagonale) {
      super(diagonale);
      this.umgebungslicht = 20;
      this.kontrast = 20;
      this.helligkeit = 18;
    }

    // Anfang Methoden

    public void setHelligkeit(int helligkeit) {
      super.setHelligkeit(helligkeit);
      this.umgebungslicht = this.helligkeit / 4 + this.kontrast /2;
    }

    public void setKontrast(int kontrast) {
      super.setKontrast(kontrast);
      this.umgebungslicht = this.helligkeit / 4 + this.kontrast /2;
    }

    public String getTyp() {
      return "AMBILIGHT";
    }

    // Ende Methoden
  } // end of AmbilightBildschirm

Ana­log zu den Bild­schirm-Klas­sen wer­den nun die Audio-Klas­sen auf­ge­baut. Die Klas­se Audio ist (wie die Klas­se Bild­schirm) abs­trakt. Für die tech­nisch we­ni­ger In­ter­es­sier­ten muss er­wähnt wer­den, dass es im Be­reich der Audio-Ver­ar­bei­tung ana­lo­ge und di­gi­ta­le Ge­rä­te gibt. Als Aus­ga­be­for­ma­te kom­men Ste­reo, Dol­by­Di­gi­tal, Di­gi­tal 5.1 und Di­gi­tal 7.1 in Frage (nur die bei­den ers­ten sind im Bild unten dar­ge­stellt).

Aufbau Audio-Klasse

Und jetzt wird zu­sam­men­ge­baut! Das Ge­häu­se mit all sei­nen Ge­rät­schaf­ten fehlt noch. Die zu­ge­hö­ri­ge Klas­se soll schlicht Fern­se­her hei­ßen. Sie be­kommt unter an­de­rem das At­tri­but kanal und die Me­tho­de na­echs­ter­Ka­nal. Neu sind dabei die Ver­bin­dun­gen zwi­schen dem Fern­se­her und dem Bild­schirm bzw. dem Audio-Teil. Klar, ein Fern­se­her hat eine Bild­röh­re und er hat ein Audio-Sys­tem. Mit die­sen (und an­de­ren) Ver­bin­dun­gen be­schäf­tigt sich der fol­gen­de Ab­schnitt. Hier schon ein­mal eine Über­sicht:

Übersicht Klassen

Im die­sem Bild des UML-Klas­sen­dia­gramms sind Ver­er­bung und Ag­gre­ga­ti­on, die im nächs­ten Ka­pi­tel be­han­delt wer­den, schon vor­han­den.

 

 

Ein­füh­rung: Her­un­ter­la­den [odt][330 KB]

 

Wei­ter zu Be­zie­hun­gen