1

cover-image

4Objective-C und Cocoa

Band 1: Grundlagen

Amin Negm-Awad

Image
Image

5Objective-C und Cocoa – Band 1: Grundlagen

Bibliografische Information der Deutschen Nationalbibliothek

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen National-bibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.

Copyright © 2012 dpunkt.verlag GmbH, Ringstr. 19B, 69115 Heidelberg

ISBN:
Buch 978-3-908498-08-7
PDF 978-3-944165-92-9
ePub 978-3-944165-93-6

3., überarbeitete Auflage 2012

Projektleitung und Lektorat:

Gabriel Neumann

Lektorat

Horst-Dieter Radke

Korrektorat:

Dr. Anja Stiller-Reimpell/Horst-Dieter Radke

Layout und Satz:

Susanne Streicher

Covergestaltung:

Johanna Voss, Florstadt

Foto Cover:

istockphoto.com

Illustrationen:

© Peter Galbraith - Fotolia.com

Druck und Bindung:

M. P. Media-Print Informationstechnologie GmbH, 33100 Paderborn

Trotz sorgfältigem Lektorat schleichen sich manchmal Fehler ein. Autoren und Verlag sind Ihnen dankbar für Anregungen und Hinweise!

SmartBooks

Ein Imprint der dpunkt.verlag GmbH

Ringstr. 19B - 69115 Heidelberg - Deutschland

http://www.smartbooks.de

E-Mail: info@smartbooks.de

Alle Rechte vorbehalten. Die Verwendung der Texte und Bilder, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und strafbar. Das gilt insbesondere für die Vervielfältigung, Übersetzung, die Verwendung in Kursunterlagen oder elektronischen Systemen. Der Verlag übernimmt keine Haftung für Folgen, die auf unvollständige oder fehlerhafte Angaben in diesem Buch oder auf die Verwendung der mitgelieferten Software zurückzuführen sind. Nahezu alle in diesem Buch behandelten Hard- und Software-Bezeichnungen sind zugleich eingetragene Warenzeichen oder sollten als solche behandelt werden.

Besuchen Sie uns im Internet!

www.smartbooks.de

www.smartbooks.ch

6Svea Frieda

7Vorwort zur dritten Auflage

Liebe Leserin, lieber Leser,

zunächst möchte ich mich dafür bedanken, dass Sie das Buch gekauft haben. Schon eine ganze Weile ist die vorhergehende Auflage vergriffen und vieles hat sich bei Apple auch hinsichtlich der Programmiererei getan. Da war eine neue Auflage erforderlich, die nun — manch einer im Verlagshause wird »endlich« schreien – vorliegt.

Ausdrücklichen Dank schulde ich erneut meiner Freundin Anja Désirée Toboll, die mich wegen der Arbeit an diesem Werk häufig entbehren musste. Allerdings fanden wir dennoch irgendwie die Zeit, für unsere Tochter Svea Frieda zu sorgen, die leider in der heißen Phase des Buches den Ausspruch »Papa arbeiten« gelernt hat und ihn innig mit meinem MacBook Air verbindet.

Es gab einige Gründe, auch konzeptionell an dem Werk etwas zu tun: Zum einen verändern sich Objective-C, Cocoa und Xcode ständig, zuletzt mit Mountain Lion. Zum anderen will ich auch immer größere Bereiche der Thematik besprechen.

Natürlich stand wieder die Frage nach der richtigen Betriebssystemversion an. Das zentrale Problem dürfte darin liegen, dass sich die Entwicklungsumgebung, insbesondere der Interface Builder, dramatisch weiterentwickelt haben. Außerdem wurde Objective-C um Sprachmittel erweitert, die die Lesbarkeit der Programme deutlich erhöht haben. Inhaltlich hat sich bei der von Apple gelieferten Bauteilkiste (Cocoa) zwar auch einiges getan. Aber das ist für diesen ersten Band gar nicht einmal so entscheidend.

Gliederung und Konzeption

Womit wir bei der Konzeption wären: Wie Sie vielleicht bei genauer Betrachtung des Einbandes gesehen haben, ist dies der erste von zwei Bänden. Dieser erste Band adressiert vor allem Einsteiger. Und dies ist gleich mit einer dringenden Bitte verbunden: Auch Leute, die jahrelang in C++ oder Java programmiert haben, sind Einsteiger bei Objective-C. Die Sprache funktioniert nämlich grundlegend anders. Ich kann daher nur immer und immer wieder empfehlen, keine Konzepte von anderen Programmiersprachen mit in dieses Buch zu nehmen. Fangen Sie wieder bei Null an! Es ist besser für Ihren Code. Das gilt übrigens auch für diejenigen, die bereits auf Objective-C umgestiegen sind und sich fragen, warum es keine Generics wie bei C++ und Java gibt. Sie sind noch nicht bei Objective-C angekommen.

Dieses Buch ist nicht primär als Nachschlagewerk, sondern als Lehrbuch konzipiert. Es soll vielmehr wie in einem Roman das Wissen rund um Objective-C und Cocoa vermitteln. Gerade für den Anfänger ist es daher wichtig, die Kapitel in der angegebenen Reihenfolge durchzuarbeiten. Ich weiß, die Neugier ist groß und man schaut gerne nach vorne. Aber die einzelnen Kapitel setzen aufeinander auf.

8Ich habe jedoch auch von Auflage zu Auflage darauf geachtet, dass das Werk stärker strukturiert wird. Einschübe sind selten vorhanden und der Anlaufpunkt sollte stets das entsprechende Kapitel sein, welches sich nach der Struktur von Cocoa und den von Ihnen entwickelten Programmen richtet. Natürlich führt dies umgekehrt zu mehr Querverweisen. Ich denke, diese im Rahmen gehalten zu haben.

Die beiden ersten Kapitel dienen dem Kennenlernen vor allem für Anfänger. Kapitel 1 erläutert die grundsätzlichen Bestandteile und Konzeptionen sowohl der Programmiersprache Objective-C und des Frameworks Cocoa als auch der Bestandteile der Entwicklungsumgebung Xcode, mit der wir uns im Laufe des Buches befassen werden.

In Kapitel 2 werden Sie eine kleine Applikation schreiben, um die Handhabung der Entwicklungsumgebung Xcode zu erlernen. Gleichzeitig erhalten Sie einen Einsteig in Objective-C.

In den Kapiteln 3 und 4 werden die gewonnenen Kenntnisse von Objective-C und Cocoa vertieft. Sie erhalten einen detaillierten Blick in allgemeine Themen, die Sie zur weiteren Arbeit benötigen. Mir ist bekannt, dass dies der langweiligste, weil abstrakteste Teil des Buches ist. Irgendwann muss man durch dieses Stahlbad. Ich habe dies an eine frühe Stelle des Buchs gesetzt, damit Sie den nachfolgenden Teil mit tieferem Verständnis durcharbeiten können. Aber auch umgekehrt: Sicherlich kann man sich nicht alles aus Kapitel 3 und 4 sofort merken, weshalb es ein guter Rat ist, dort immer wieder mal nachzuschauen.

Wie Sie gelernt haben werden, strukturiert man eine Anwendung mit graphischem User-Interface (GUI) in drei Ebenen: View — Controller — Model. Diese werden in den Kapitel 5 bis 7 genauer besprochen.

Kapitel 8 enthält zusätzliche Hinweise zum Arbeiten mit der Entwicklungsumgebung und schließt damit den Kreis.

Aktualität

Dieses Buch setzt — was die Entwicklungsumgebung angeht — auf OS X 10.8 Mountain Lion mit Xcode 4.5 auf. Dies hat leider zu einer weiteren Verzögerung geführt, da zahlreiche Textstellen und Screenshots angepasst werden mussten. Gerade die Übernahme von Xcode 4 war wichtig, da sich hier vieles getan hat.

Die zeitgleich mit Mountain Lion erschienenen Erweiterungen von Objective-C sind ebenfalls eingearbeitet, so dass das Buch hoch aktuell ist. Allerdings mag man das »zeitgleich« ernst nehmen: Sie können ohne Weiteres mit OS X 10.7 Lion arbeiten, da auch dort die Neuerungen der Programmiersprache Einzug erhielten. Letztlich sind die Unterschiede zwischen den beiden Betriebssystemen nicht tragend für dieses Buch.

Auch bereits mit Lion wurde ein neues Speicherverwaltungsmodell, Automatic Reference Counting, in Cocoa und Objective-C eingeführt, welches die Arbeit deutlich vereinfacht. Damit ist ein älteres (keinesfalls das älteste) Speicherverwaltungsmodell, Garbage-Collection, obsolet geworden. Es wird nicht mehr besprochen und in diesem Buch nicht benutzt.

9Automatic Reference Counting wird allerdings von mir in allen Sourcen eingesetzt, es sei denn, ich bespreche gerade manuelles Reference-Counting. An kniffligen Stellen gibt es auch kurze Hinweise für manuelles Reference-Counting. Ich rate aber von der Verwendung ab.

Bei Objective-C habe ich mich für die neueste Version entschieden, zeige aber auf, wie Sie das in altes Objective-C übersetzen können. Sie lässt aber prägnantere Formulierungen zu, was einfach zur klareren Verständlichkeit und zu Seitenersparnis führt.

Weiterführende Informationen

Auf meiner Webseite zum Buch

www.cocoading.de

sollten Sie immer einmal vorbeischauen. Zwar finde ich nur noch wenig Zeit, dort Artikel zu veröffentlichen, aber es findet sich dort der Code zum Buch wie Anmerkungen, Fehler usw. Sie können mich auch über meine E-Mail-Adresse ansprechen:

negm-awad@cocoading.de

Ich bemühe mich, auf alle Fragen einzugehen. Es kann eben bloß auch mal eine Woche dauern, bis ich die Zeit finde, einen komplizierten Sachverhalt anzuschauen. Erinnern Sie mich ruhig!

Für Freunde des kurzen Textes ist vielleicht mein Twitter-Account interessant.

cocoading

Des Weiteren existiert, betrieben von Kay Löhmann, das wichtigste deutschsprachige Forum für Cocoa-Entwickler (aber nicht nur Cocoa-Entwickler) unter der Domain

www.osxentwicklerforum.de

Hier können Sie Einzelfragen stellen, die von einer Horde hilfsbereiter Entwickler sicherlich schnell beantwortet wird. Kay Löhmann hat dankenswerterweise in der Diskussionsgruppe Cocoa eine Untergruppe für dieses Buch mit dem Namen »Fragen zum Buch Objective-C und Cocoa« eingerichtet. Ich bin dort — wie generell auf dem Forum — (fast) täglich zu erreichen.

Ich werde an einigen Stellen in diesem Buch auf Band 2 verweisen. Dies dient nicht der Werbung — die Existenz des 2. Bandes werden Sie ohnehin bemerkt haben. Vielmehr gelange ich zuweilen an Stellen, bei denen ich Erweiterungen, Hintergrundinformationen, vertieftes Wissen usw. aufzeigen möchte, ohne dies bereits in diesem Band besprechen zu können. Ich will es aber auch nicht verschweigen, da dies Wissen vielleicht für Ihre geplante Applikation wichtig ist und Sie daher wissen wollen, ob etwas, das sie beabsichtigen, möglich ist. Bei einem riesigen Framework wie Cocoa läuft man sonst schnell in die verkehrte Richtung und verirrt sich.

Überhaupt Apple-Dokumentation: Sie sollten die in dem Buch angesprochenen Dinge auch parallel in der Dokumentation nachschlagen und sich ruhig ein wenig umschauen. Auch in 10zwei Bänden kann man allenfalls die wichtigsten Punkte ansprechen. Ich habe aber die Links in die Apple-Dokumentation auf der Webseite zum Buch eingefügt, so dass Sie dort nachschauen können. Die Liste im Internet erweitere und aktualisiere ich zudem ständig auf der Webseite.

Programmlistings und Screenshots

In diesem Buch sind freilich zahlreiche Listings enthalten, die den von Ihnen einzugebenden Text darstellen. Ich habe mir Mühe gegeben, zu ändernde oder in Bezug genommene Stellen durch Fettschrift hervorzuheben. Sind Auszüge dargestellt, so befindet sich an den ausgelassenen Stellen ein Ellipsenzeichen („...“). Der Umbruch der Codezeilen orientiert sich an dem Layout, wie es in einem gedruckten Werk erforderlich ist. Da mir hier nur 80 Zeichen pro Zeile zur Verfügung stehen, ist dies zuweilen etwas gewöhnungsbedürftig. Sie können bei eigener Eingabe deutlich breiter setzen. Als Merkregel gilt: Immer wenn ein Leerzeichen oder ein Zeilenumbruch erfolgt, können Sie dies gegeneinander austauschen. Sie können also Teile, die auf mehrere Zeilen verteilt sind, bei sich wieder zusammenfügen, wenn dazwischen ein Leerzeichen getippt wird.

Auch bei Screenshots habe ich, soweit erforderlich, Hervorhebungen durch Rahmen vorgenommen. Bitte beachten Sie diese, wenn Sie in Dialogen verschiedene Einstellmöglichkeiten suchen.

Leider kann es vorkommen, dass das von Ihnen verwendete Programm Xcode Fehler hat. In diesen Fällen funktioniert dann »auf einmal« gar nichts mehr. Schauen Sie im Zweifel auf die Webseite zum Buch, ob ich dort etwas dazu publiziert habe. Ansonsten empfiehlt es sich, zuweilen Xcode neu zu starten.

Überhaupt können Sie den von Ihnen einzugebenden Code auch von der Webseite herunterladen. Es wird allerdings eher nicht funktionieren, diese eins-zu-eins mit Ihrer Eingabe zu vergleichen, da sich doch immer wieder minimale Unterschiede ergeben, die sich im Laufe der Zeit summieren. Mit etwas Verständnis kann das aber eine wichtige Hilfe zur Fehlersuche sein.

Fehlersuche und -meldung

Zuweilen macht man einen Fehler, der so offensichtlich ist, dass man ihn gar nicht sieht. Auch, wenn man sich die entsprechende Stelle 283981237 Mal angeschaut hat, gelingt dies nicht. Da hilft nur eines: Besuchen Sie das vorgenannte Forum und schildern Sie das Problem. Es besteht eine hohe Wahrscheinlichkeit, dass jemand anderes dies sehr schnell sieht, einfach weil er weiter von der Thematik entfernt ist. Ich selbst habe bei einem Fehler im Code für die letzte Auflage stundenlang gesessen, um nach Rückfrage innerhalb kürzester Zeit von Manfred Kress auf das Unsichtbar-Offensichtliche hingewiesen zu werden. Danke noch einmal, Manfred! Ich wäre mutmaßlich über diesen Fehler verstorben.

Ich hoffe, dass Sie beim Lesen des Buches so viel Spaß haben, wie ich beim Schreiben hatte.

Amin Negm-Awad
Köln, im September 2012

11Übersicht

Kapitel 1     Einführung

Kapitel 2     Umrechner – Die erste Applikation

Kapitel 3     Objective-C

Kapitel 4     Foundation

Kapitel 5     Die Viewschicht

Kapitel 6     Die Controllerschicht

Kapitel 7     Die Modelschicht

Kapitel 8     Xcode & Co

                     Index

12Inhaltsverzeichnis

Vorwort zur dritten Auflage

Kapitel 1     Einführung

1.1       Die Sprache und das Framework

1.1.1    Objective- ...

Nachrichten

Objekte

Klassen und Klassenobjekte

Ableitung und Vererbung

Überschreiben und Polymorphie

Erweiterung oder Spezialisierung

Delegieren: alternative Spezialisierungen

1.1.2    ... C ...

1.1.3    ... und Cocoa

Cocoa als Library

Cocoa als Umgebung

1.2       Xcode Developer-Tools

1.2.1    Installation der Developer-Tools

1.2.2    Xcode Integrated Developer Envirement

1.2.3    Compiler, Linker und Build

1.2.4    Debugger

1.3       Zusammenfassung und Ausblick

Kapitel 2     Umrechner – Die erste Applikation

2.1       Xcode und das Projekt

2.1.1    Projekt anlegen

2.1.2    Die Bereiche des Projektfensters

2.1.3    Die Symbolleiste

2.1.4    Die Navigatoren

Der Projektnavigator

Symbolnavigator

Search-Navigator

Sonstige

2.2       Xib-Editor: das User-Interface

2.2.1    Die Objektliste

Placeholder

Objects

2.2.2    Die Library im Interface Builder

2.2.3    Der Inspector für die Einstellungen

2.3       Outlets, Actions und Targets

2.3.1    Der Button als Anfang allen Übels

2.3.2    Die Klasse Controller, ...

2.3.3    ... und das Instanzobjekt

2.3.4    Outlets: Verbindungen zum User-Interface

Outlet graphisch erzeugen

Outlet selbst programmieren

Letztes Textfeld

Outlets kontrollieren

132.3.5    Action-Target: Verbindungen vom User-Interface

Manuell: Action schreiben und Target setzen

Automatisch Methode erzeugen lassen und setzen

Action kontrollieren

2.3.6    Konsole

2.4       Source-Editor: erste Schritte des Programmierens

2.4.1    Nachrichten – Wir beginnen zu sprechen

2.4.2    Variablen und Returnwerte – Fragen und Antworten

2.4.3    Dokumentation und Quick-Help

Vollständige Dokumentation

Kurzdokumentation

2.4.4    Fehleranzeige

2.4.5    Lesen — Denken – Schreiben

2.5       Der Debugger

2.5.1    Breakpoints

2.5.2    Angezeigte Informationen

Editor

Debugger

Navigationsleiste

2.5.3    Durchlaufen

2.6       Das letzte Drittel: Das Model

2.6.1    Amin’s next top model: äußere Ansichten ...

2.6.2    ... und innere Werte

Modelbeschreibung und -editor

2.6.3    Verbindungen schaffen

2.7       Zusammenfassung und Ausblick

Kapitel 3     Objective-C

3.1       Kleinkram

3.1.1    Typen

Einfache Datentypen

Strukturen

C-Arrays

Zeiger

Objektvariablen

3.1.2    Objektarten

Klassen- und Instanzobjekte

Entitäten und Container

Swinger-Club für Objekte — Attribute und Beziehungen

3.1.3    Mathematische Operationen

3.1.4    Kontrollstrukturen

Verzweigungen

Schleifen

Bedingungen

3.1.5    Ausführungseinheiten

Blöcke

Funktionen

Methoden

Closures (Objective-C-Blocks)

Konzept

Syntax im Einzelnen

Praktische Anwendung in Cocoa

143.2       Klasse

3.2.1    Interface (Beschreibung)

Die Klasse und ihre Basisklasse

Instanzvariablen

Eigenschaften (Declared-Propertys)

Methodenliste

3.2.2    Class-Continuation

Möglichkeiten

Zweck

3.2.3    Implementierung (Funktionalität)

Eigenschaften

Weitere Methoden

3.2.4    Verwendung

Erzeugung einer Instanz

Benutzen der Instanz

3.2.5    Instanzvariablen

3.2.6    copy und strong (und weak)

3.3       Eine Subklasse als Spezialisierung

3.4       Eine Subklasse als Erweiterung

3.5       Kategorien

3.5.1    Erweiterung

3.5.2    Strukturierung

3.5.3    Kapselung

3.5.4    Informelle Protokolle

3.6       Protokolle

3.6.1    Definition

3.6.2    Übernahme in Klassen

3.6.3    Verwendung

Required-Methoden

Optional-Methoden

Protokolltypisierung

Protokollabfrage

3.7       Zusammenfassung

Kapitel 4     Foundation

4.1       Objekterzeugung

4.1.1    Allokation

4.1.2    Initialisierung

Designated-Initializer

Secondary-Initializer

Ererbte Initialisierer

Zusammenfassung

Initialisierung von Klassenobjekten

4.1.3    Convenience-Allocators und +new...

4.1.4    Kopien: Objektorientiertes Plagiieren

Kopien, Identität, Dasselbe, Das Gleiche

Implementierung

Convenience-Copy

Gleichheit

4.1.5    Zusammenfassung

4.2       Speicherverwaltung

154.2.1    Das Konzept anhand von Automatic Reference Counting

Vernetztes Denken

Anker

Löschwelle

Weak – Zyklen und der Softie unter den Settern

Autorelease-Pools und die Rückgabe von Objekten

Zusammenfassung

4.2.2    Manuelle Speicherverwaltung

Grundregel

Lokale Variablen

Accessoren und Instanzvariablen

Rückgabe

Objektvernichtung

Zusammenfassung

4.2.3    Automatische vs. Manuelle Speicherverwaltung

4.3       Container

4.3.1    Arten von Containern

4.3.2    Skalare Container

Formatter

Werte

Zahlen

Dezimalbrüche

Zeichenketten

Date und Calendar

Binäre Daten

4.3.3    Collections

Elemente und Speicherverwaltung

Erzeugung

Keine Collection, leere Collection und leeres Element

Abzählung

Sets

Counted-Sets

Ordered-Sets

Arrays

NSDictionary

4.3.4    Property Lists

Struktur

Umwandlung von Entitäten in Property-Lists

XML-Property-Lists

4.4       Zusammenfassung

Kapitel 5     Die Viewschicht

5.1       Grundlagen

5.1.1    Responder als Basisklasse

Fenster

Views

Die Aufgabenteilung zwischen Fenstern und Views

5.1.2    Views und Cells

5.1.3    Nib-Files

5.2       Menüs

5.3       Fenster

5.3.1    Wichtige Eigenschaften

165.3.2    Delegate

5.3.3    Sheets

Synchrone Alerts

Asynchrone Alerts

Synchrone, applikationsmodale Fenster

Asynchrone, fensterlokale Sheets

5.3.4    Drawers

5.3.5    Toolbars

Toolbar-Struktur

Eigene Toolbar erstellen

5.4       Views und Controls

5.4.1    Wichtige Eigenschaften

5.4.2    Autolayout

Constraints

Ungleichungssystem

Nutzung aus dem Code

5.4.3    Buttons

Aktionsbuttons

Umschaltbuttons

5.4.4    Imageviews

5.4.5    Boxen

5.4.6    Tabviews

5.4.7    Splitviews

5.4.8    Progressindicator

5.4.9    Textfelder

5.4.10  Pop-up-Buttons

5.4.11  Scrollviews

5.4.12  Tableviews

Struktur

Content-Mode

Data-Source

Sourceview

Selection

5.4.13  Outlineviews

5.4.14  Weitere Views und Eigenschaften

5.5       Animation

5.6       Zusammenfassung

Kapitel 6     Die Controllerschicht

6.1       Bindings-Controller, KVC, KVV und KVO

6.1.1    Grundlagen

Key und Key-Path

Key-Value-Coding

Key-Value-Validation

Key-Value-Observation

Cocoa-Bindings (Key-Value-Bindings)

176.1.2    Key-Value-Coding

Funktionsweise

Einfache Accessoren (Getter und Setter)

Ungeordnete To-many-Relationships (Sets)

Geordnete To-many-Relationships (Arrays, Ordered-Sets)

Zusammenfassung:

Fehlermethoden

6.1.3    Key-Value-Validation

6.1.4    Key-Value-Observing

6.1.5    Bindings

Bindbare Eigenschaften

Bindings-Optionen

Value-Transformer

6.1.6    Der Arraycontroller

Einstellungen im Attributes-Inspector

Observierbare Eigenschaften

6.1.7    Der Tree-Controller

6.1.8    Der Dictionary-Controller

6.1.9    Der Defaults-Controller und Voreinstellungen

Defaultssystem

Registrationdefaults und Application-Delegate

6.1.10  Komplexe Bindings

Bindingsketten

Selektions-Bindings

6.2       Windowcontroller und Viewcontroller

6.2.1    Aufgabe und Stellung

6.2.2    Fenstertyp

6.2.3    Dokumentenwindowcontroller

Der eigene Windowcontroller

Document-Bindings

Outlets

Actions und First Responder

6.2.4    Infowindowcontroller

6.2.5    Inspector-Windowcontroller

Erstellen

Synchronisation

6.2.6    Viewcontroller

6.3       Notifications

6.3.1    Lokale Notifications

Notification definieren

Notification auslösen

Notification fangen

6.3.2    Als Observer anmelden

Notifications und Delegating

6.3.3    Distributed-Notifications

6.4       Data-Sources

6.4.1    Bindings einreißen und Data-Source vorbereiten

6.4.2    Die Urgründe

6.4.3    Manuelle Synchronisation der Auswahl

6.4.4    Personen zum Outlineview hinzufügen

6.4.5    Gruppen und ihre Elemente

6.4.6    Ansichten tauschen

186.4.7    Manuelle Synchronisation der Attribute

6.4.8    Key-Loop

6.5       Drag-and-drop-Controller, Pasteboards

Dragging

Dropping

6.6       Zusammenfassung

Kapitel 7     Die Modelschicht

7.1       Grundlagen

7.1.1    Inhalt

Informationen

Fähigkeiten

7.1.2    Modellierung

Problemstellung

Modellierungsregeln

7.2       Dokumente eigener Klassen

7.2.1    Modellimplementierung

7.2.2    Anbindung

7.2.3    Laden und Speichern

Methodensatz

Serialisierung mit Codern

Serialisieren

Deserialisierung

Handwerksregeln

7.2.4    Undo

Undo-Manager

Undo-Stack

Undo implementieren

Undo deaktivieren

Handwerksregeln

7.3       Core Data

7.3.1    Grundlagen

Aufgabe von Core Data

Was ist Core Data?

Aufbau

7.3.2    Modelbeschreibung

Entitätsbeschreibung

Eigenschaftsbeschreibungen

Klassen und Entitäten

7.3.3    Instanzverwaltung

Objekt-ID

Instanzerzeugung

Speicherverwaltung

Instanzvernichtung

Abweichungen zwischen Store und Kontext

7.3.4    Anpassung

Accessoren

Klasseneigenschaften

Eigene Attributtypen

7.3.5    Fetch-Requests

197.3.6    Prädikate

Eigenschaft (Key)

Wert

Operator

To-many-Beziehungen und Aggregate

Prädikaterzeugung

7.3.7    Sortierung

Möglichkeiten der Sortierung

Sort-Deskriptoren

Reihenfolgeeigenschaft im Model

Reihenfolgeeigenschaft per Drag-and-Drop und die Objekt-ID

7.4       Applikationsmodelle

7.4.1    Zugriff

7.4.2    Ohne Core-Data-Support

Im Code

Im Nib

7.4.3    Mit Core-Data-Support

7.4.4    Undo-Management

7.4.5    Laden und Speichern

7.5       Versions und Autosave

7.6       Zusammenfassung

Kapitel 8     Xcode & Co

8.1       Workspace, Projekt und Target

8.1.1    Übersicht

8.1.2    Workspaces

Workspace erzeugen

Projekte erzeugen

Mit Workspace arbeiten

8.1.3    Projekt

8.1.4    Target

8.1.5    Schemes

8.1.6    Configurations

8.2       Projektdateien

8.2.1    Datei hinzufügen

8.2.2    Dateien finden

8.3       Target

8.3.1    Summary

8.3.2    Info

8.3.3    Build-Settings

8.3.4    Build-Phasen

8.4       Lokalisierung

8.4.1    Ressourcen und Lokalisierung

Lokalisierte Dateien

Auswahl der Lokalisierung

Lokalisierung hinzufügen

Lokalisierung im Code

8.4.2    Das »Über«-Fenster

8.5       Texteditor und Code-Generierung

208.5.1    Texteditor und Preferences

Textvervollständigung

Code-Folding

Navigation

Kodierung

Bezeichnernutzung

Einrückung

Key Bindings

8.5.2    Code-Generierung

Core-Data

Interface Builder

8.5.3    Refaktorierung

Umbenennen

Auslagern

Klassenhierarchie

Konvertierung zu ARC

8.6       Codeanalyse

8.7       Die erste eigene Applikation

8.7.1    Leistungsumfang

8.7.2    Arbeitsabläufe

8.7.3    User-Interface

8.7.4    Model

8.7.5    Controller aufbauen

8.7.6    Testen und Fehlersuche

8.7.7    Anwendung publizieren

Archive-Build

Archive

8.8       Zusammenfassung

                      Index

Verzeichnis der Schlüsselwörter und Bezeichner

Stichwortverzeichnis

21Kapitel 1 Einführung

Image

Gleich herein: Ich habe mir das allgemein übliche Herumgerede am Anfang eines Lehrbuches gespart. Sie sollen hier einen Überblick über die verschiedenen Elemente erhalten, die Sie zur Programmierung erlernen müssen, damit Sie erst einmal eine Grundstruktur des Wissens haben.

22Sie haben es als Programmierer mit zahlreichen neuen Dingen zu tun. Das verwirrt häufig und führt zu Missverständnissen. Meist sind es nur Begriffsverwechslungen, die nicht wirklich schlimm sind. Wenn Sie dann aber im Internet nachforschen wollen oder Fragen in Foren stellen, ist es schwierig, an die richtige Information zu kommen. Daher hier erst einmal die Grundstruktur und wesentliche Gedanken:

Jeder Handwerker hat zwei Dinge in seiner Werkstatt: das Material, das er bearbeitet, und die Werkzeuge, mit denen er es bearbeitet. Und Programmieren ist viel, viel Handwerksarbeit. Daher will ich mit Ihnen zunächst einen kleinen Rundgang durch die von Ihnen neu erworbene Werkstatt machen.

Das Material, die Programmiersprache »Objective-C« und das Framework »Cocoa« bespreche ich als Erstes, wobei ich ganz abstrakt bleibe, also nur die Grundkonzepte vorstelle.

Danach geht es an die Aufgabengebiete der Werkzeuge, der sogenannten Developer-Tools.

1.1 Die Sprache und das Framework

Computer werden mit Programmiersprachen programmiert. Die Programmiersprachen stellen also das Material dar, aus dem wir später unser Programm bauen. Aber bei modernen Programmiersprachen verhält es sich so, dass sie gleichermaßen nur eine leere Hülle bilden. Inhaltliche Funktionalität gibt erst das »Framework«, eine Art Grabbelkiste vorgefertigter Elemente. Man kann also vereinfachend die Programmiersprache Objective-C als »Grammatik« und das Framework Cocoa als »Vokabular« bezeichnen. Dabei können Sie an der Programmiersprache nichts ändern. Ihre Programmiertätigkeit liegt vielmehr darin, das Vokabular ständig zu erweitern.

Der Buchtitel »Objective-C und Cocoa« vermittelt dabei eine Zweiteilung. In Wahrheit geht es aber um drei Komponenten:

1.1.1 Objective- ...

Die Programmiersprache, mit der wir hier programmieren werden, nennt sich »Objective-C«. Das steht ja auch auf dem Buchdeckel. Daher hier ein paar einleitende Worte zur Sprache und ihren Konzepten:

Bei Objective-C handelt es sich um eine sogenannte objektorientierte Sprache. Die Technologie bezeichnet man als »objekt-orientierte Programmierung« (OOP). Da der Begriff eine ganze Zeit ein Modewort war, ist er leider versaubeutelt worden. Objective-C verdient jedoch den Namen OOP so, wie er ursprünglich von Alan Kay Ende der 70er-Jahre 23erfunden wurde, als dieser die Programmiersprache Smalltalk-80 entwickelte, den Vorläufer von Objective-C.

Kay arbeitete am Xerox Palo Alto Research Center (Xerox-PARC). Richtig, Xerox-PARC, das war das Forschungsinstitut, von dem auch Apple die ersten Ideen für eine graphische Benutzeroberfläche bekam. (Später arbeitete übrigens Kay eine Zeit lang für Apple.) Und diese Idee der graphischen Benutzeroberfläche revolutionierte nicht nur die Bedienung von Computern, sondern auch ihre Programmierung. Denn für diese neue Art des User-Interfaces waren bisherige Programmiersprachen unbequem. Um das zu verstehen, muss man sich erinnern (wenn man alt genug ist) oder lernen, wie man damals mit Computern arbeitete:

Grundsätzlich gab das Programm dem Benutzer in einem Raster vor, was wann zu tun war. Wir schreiben gleich ein Umrechnungsprogramm. Eine Sitzung mit einem solchen Programm hätte damals vermutlich wie folgt ausgesehen:

Geben Sie den Ausgangswert ein: 3[Enter]
Geben Sie den Umrechnungsfaktor ein: 2.54[Enter]
Das Ergebnis ist 7,62
Möchten Sie noch eine Umrechnung vornehmen (j/n):n[Enter] 

Hier werden also 3 Zoll in 7,62 cm umgerechnet. Der Punkt ist, dass das Programm vorgibt, wann was getan wird: Ausgangswert eingeben — Umrechnungsfaktor eingeben — Ergebnis berechnen und ausgeben — Ende des Programms abfragen. Das Programm hat also gewissermaßen vier Arbeitsschritte, die im festen Raster abgearbeitet wurden.

Image

Eine moderne Anwendung legt Sie nicht fest.

Stellen Sie sich mal eine Anwendung für OS X vor: Hier gäbe es zwei Felder zur Eingabe der Werte (Ausgangswert und Umrechnungsfaktor), einen Button oder einen Menüeintrag Umrechnen und einen Menüeintrag Beenden. Und für Sie wäre es völlig klar, dass Sie jeden dieser Arbeitsschritte in beliebiger Reihenfolge ausführen können. So könnten Sie etwa den Umrechnungsfaktor 2,54 vor dem Ausgangswert eingeben. Sie könnten jederzeit das Programm beenden. Natürlich würden Sie ganz häufig beim zweiten Mal nur noch den Ausgangswert eingeben und auf Umrechnen klicken, da sich der Umrechnungsfaktor nicht ändert, wenn Sie etwa eine ganze Zahlenkolonne von Zoll nach cm umrechnen. Wieso jedes Mal den Umrechnungsfaktor neu eingeben? Dann wäre also die Reihenfolge der Arbeitsschritte wieder eine andere.

24Lange Rede, kurzer Sinn: Mit der Erfindung der graphischen Benutzeroberfläche gibt nicht mehr das Programm dem Benutzer die Abfolge der Arbeitsschritte vor, sondern der Benutzer dem Programm. Die Leute, die die graphische Benutzeroberfläche entwickelten, nannten diesen ersten Lehrsatz: »Don’t mode me!«, übersetzt vielleicht: »Zwinge mich nicht dazu, eine bestimmte Abfolge einzuhalten.«

Und dies war für bisherige Programmiersprachen unbequem zu formulieren. Grundsätzlich denkt man beim Programmieren in Schritten, die nacheinander ausgeführt werden. Als Vergleich werden hier gerne Kochrezepte herangezogen: ein Arbeitsschritt nach dem anderen. Sie kämen ja auch nicht auf den Gedanken, zuerst die Pizza zu belegen und dann den Teig zu machen. Geht irgendwie nicht ...

Nachrichten

Versetzen wir uns also in Alan Keys Situation: Er kannte Programmiersprachen, die eine feste Abfolge von Arbeitsschritten wollten, und er hatte im Nebenzimmer Gestalter sitzen, die sagten, dass der Benutzer eine freie Abfolge von Arbeitsschritten will. Und er musste das irgendwie zusammenbringen.

Der erste Schritt zur Lösung besteht darin, die Aktionen des Benutzers (Drücken einer Taste, Klicken auf einen Button oder einen Menüeintrag usw.) als Nachricht des Benutzers an das Programm aufzufassen. Schauen Sie sich oben noch einmal den Ablauf eines »herkömmlichen« Programms an: Dort schickt das Programm Nachrichten an den Benutzer, was er jetzt zu tun habe. Jetzt machen wir es genau umgekehrt: Wir schicken Nachrichten an das Programm, was es zu tun habe. Also etwa: »Taste gedrückt: 3.«

Jeder dieser Nachrichten wird dann vom Programmierer ein Stück Programm zugeordnet. Also, es gibt etwa einen Programmteil, der ausgeführt wird, wenn eine Nachricht »Taste gedrückt: 3« eintrifft. Dann wird der Programmteil tasteGedrückt: ausgeführt.

Objekte

Jetzt gibt es da aber ein Problem: Wohin mit der 3? Die könnte ja im ersten Eingabefeld (Ausgangswert) oder im zweiten Eingabefeld (Umrechnungsfaktor) gedrückt worden sein. Und was soll mit der 3 geschehen? Sie muss ja irgendwie in den bereits bestehenden Text im Eingabefeld angehängt oder eingefügt werden oder was auch immer.

25Image

Erhält ein Objekt eine Nachricht, so führt es ein kleines Stück Programm aus.

Hier kommt das zweite Konzept zum Tragen: Jede Nachricht hat einen Adressaten. Und diesen Adressaten nennt man »Objekt«. In unserem Beispiel wäre jedes Eingabefeld ein Objekt, eben ein Eingabefeldobjekt. Und so ein Objekt zeichnet sich durch zwei Dinge aus: Zum einen kann es aufgrund einer Nachricht ein bisschen Programm ausführen, wie bereits oben angedeutet. Man bezeichnet dieses bisschen Programm als »Methode«. In unserem Beispiel könnten die beiden Objekte also die Methode tasteGedrückt: ausführen. Dort wäre dann ein bisschen Programm, welches die Taste entgegennimmt und in den Text einfügt.

Das Zweite ist, dass ein Objekt Daten speichern kann. Nehmen Sie an, dass im ersten Eingabefeld schon der Wert 7 steht, im zweiten 2,5. Dies bedeutet, dass das erste EingabefeldObjekt den Wert 7 gespeichert hat und das zweite den Wert 2,5.

Wird jetzt eine Taste im ersten Eingabefeld gedrückt, so erhält dieses erste Eingabefeld-Objekt die Nachricht »tasteGedrückt: 3« und führt daraufhin seine Methode tasteGedrückt: aus. Daraufhin fragt es sich selbst, welcher Wert denn bisher gespeichert ist, und erkennt 7.

26Image

Jedes Objekt kennt zudem seine Werte.

An diese 7 hängt es die 3 an und speichert 73 als neuen Wert.

Drückt der Benutzer demgegenüber die Taste, während der Cursor im zweiten Eingabefeld ist, so erhält das zweite Eingabefeld-Objekt die Nachricht »Taste gedrückt: 3« und führt die Methode tasteGedrückt: aus. Dort sieht die Methode, dass bisher der Wert 2,5 gespeichert ist, hängt eine 3 an und speichert das wieder als Wert 2,53.

Wieso machte das Kay auf diese Weise? Nun, wenn früher das Programm die Arbeitsschritte festlegte, konnte es keine Missverständnisse geben: Der erste Wert, der vom Benutzer eingegeben wurde, war der Ausgangswert. Der zweite Wert, der eingegeben wurde, der Umrechnungsfaktor. Die Zuordnung der Benutzereingabe zu den Speicherstellen des Programms war also fest. Jetzt jedoch ging das ja alles durcheinander. Und daher musste eine Zuordnung der Nachricht und des Speichers erfolgen.

Zusammengefasst: Ein Objekt ist eine Einheit, die Daten speichern kann und aufgrund einer Nachricht eine Operation (Methode) ausführt.

Klassen und Klassenobjekte

Ihre Arbeit als Programmierer besteht nun darin, diese Objekte zu programmieren. Nein, ganz richtig ist das nicht. Objective-C ist auch eine sogenannte klassenbasierte Programmiersprache.

27Schauen wir noch einmal auf unser Programm, das wir gleich programmieren werden. Ich hatte Ihnen gesagt, dass beide Eingabefelder Objekte sind, weil sie einerseits Nachrichten empfangen können, andererseits Werte speichern.

Aber auch der weiter unten liegende Button ist ein Objekt. Er kann auch Nachrichten empfangen, etwa, wenn der Benutzer auf ihn klickt. Auch kann er Werte speichern, etwa seine Beschriftung »Umrechnen«. Also auch ein Objekt.

Aber ich muss Ihnen nicht erklären, dass die beiden Eingabefelder sehr ähnlich sind, der Button demgegenüber etwas ganz anderes. Überlegen wir uns mal, warum das richtig ist, was wir bereits ganz intuitiv fühlen:

Zum einen können beide Eingabefelder die gleiche Art von Daten speichern, nämlich den Wert, der gespeichert ist. Klar, der Wert kann in jedem Eingabefeld anders sein. Aber was überhaupt gespeichert wird, ist bei beiden Eingabefeldern gleich. Beim Button dagegen wird etwas anderes gespeichert, nämlich seine Beschriftung. Jeder Button kann wiederum eine andere Beschriftung haben. Aber die Art der Daten, die gespeichert wird, ist eben Beschriftung.

Ebenso verhält es sich bei den Nachrichten und Methoden: Beide Eingabefelder können auf die Nachricht »tasteGedrückt:« reagieren und dementsprechend die Methode -tasteGedrückt: ausführen. Der Button dagegen kann die Methode -klick ausführen.

Der Trick besteht jetzt darin, dass man gleichartige Objekte wie unsere Eingabefeldobjekte zusammenfasst zu einer Klasse. Ein ganz anderes Objekt (wie unser Button) gehört dagegen zu einer anderen Klasse. Also:

Das erste Eingabefeldobjekt ist von der Klasse Eingabefeld.

Das zweite Eingabefeldobjekt ist von der Klasse Eingabefeld.

Das Buttonobjekt ist von der Klasse Button.

Und Ihre Aufgabe als Programmierer ist es jetzt, diese Klassen zu programmieren. Das sieht dann etwa so aus:

Eingabefeld
    Hat folgende Eigenschaften:
    Wert
    Textfarbe

    Hat folgende Fähigkeiten:
    tasteGedrückt:

28Button
    Hat folgende Eigenschaften:
    Beschriftung

    Hat folgende Fähigkeiten:
    klick:

Dabei legen Sie also fest, welche Eigenschaften (Zahlen, Texte, Farbe usw.) das Objekt hat und welche Methoden aufgrund einer Nachricht ausgeführt werden können.

Später, wenn das Programm gestartet wird, liest der Computer diese Beschreibung und erstellt entsprechende Objekte in der gewünschten Zahl. Man kann also sagen, dass die Klasse eine Beschreibung der Objekte ist, deren Bauplan. Und man sagt, dass es den Typen festlegt. »Typ«, das ist das Fachwort.

Image

Die Klasse enthält die Beschreibung, das Objekt den konkreten Wert.

Wenn man die drei Kreise vergleicht, stellt man etwas fest: Die Eingabefeldklasse beschreibt einmalig die bei den Eingabefeldern vorhandenen Eigenschaften und Methoden. Dies ist daher bei beiden Eingabefeldobjekten gleich, Der einzige Unterschied besteht darin, dass die konkret gespeicherten Werte (7 bzw. 2,5) voneinander abweichen. Daher reicht es aus, wenn bei einem Objekt nur dieser Wert gespeichert wird, bei der Klasse der Rest. Für Sie ist es aber wichtig zu sehen, dass die Methode tasteGedrückt: eine Methode des Objektes, nicht der Klasse ist. Und Wert ist die Bezeichnung einer Eigenschaft des Objektes, nicht der Klasse. Deutlich wird das, wenn wir unser Modell erweitern:

29Weil aber die Klasse der Hohe Wächter des Bauplanes ist, hat sie noch eine zweite wichtige Funktion: Sie stellt die Objekte her. Hierzu erhält sie eine Nachricht der Art: »Erzeuge mir ein Objekt nach dem bei dir gespeicherten Bauplan.« Und jetzt wird es schwierig: Wenn eine Nachricht an die Klasse geschickt wird, dann muss diese Klasse ja auch ein Objekt sein. Denn Objekte sind die Empfänger von Nachrichten. Und es muss bei der Klasse also auch eine entsprechende Methode vorhanden sein, die bei jeder Nachricht ein neues Objekt erzeugt.

Und so ist es auch: Jede Klasse wird gleichzeitig durch ein sogenanntes Klassenobjekt repräsentiert. Dieses Klassenobjekt ist, vereinfacht gesagt, bei Start des Programms einfach da, muss also nicht erst erzeugt werden. Und weil es einfach da ist, können wir es ohne weiteres benutzen. Nur eine Nachricht hinschicken, das war’s. Dafür haben die Klassenobjekte einen Nachteil: Man kann in ihnen keine Daten speichern. Das ist für ihre Aufgabe aber auch nicht erforderlich.

Um das Ganze unterscheiden zu können, nennen wir die erzeugten Objekte »Instanzobjekte« oder kurz »Instanzen« und die Klassenobjekte eben so oder »Klassen«. Wobei man begrifflich schon unterscheiden sollte, dass Klasse den Typen eines Instanzobjektes bezeichnet, während Klassenobjekt den Empfänger einer Nachricht meint. Wir können unsere Graphik jetzt verfeinern:

Image

Klassenobjekte haben auch Methoden, mit denen sich Instanzobjekte erzeugen lassen.

30Um einem Missverständnis gleich vorzubeugen: Klassenmethoden müssen nicht zwingend Instanzobjekte erzeugen. Sie können auch andere Aufgaben wahrnehmen. Das ist aber seltener der Fall und hier nicht von Interesse.

Ableitung und Vererbung

Warum macht man das aber mit den Klassen? Es hat einen einfachen Grund, den man »Ableitung und Vererbung« nennt.

Nehmen wir ein Beispiel, welches wir uns im Kapitel 3 über Objective-C programmieren werden. Dort werden wir es mit Musikinstrumenten zu tun haben, mit Klavieren und Gitarren. Beide Instrumente haben Gemeinsamkeiten, nämlich etwa Preis und Alter. Das liegt daran, dass sie Instrumente sind und jedes Instrument einen Preis und ein Alter hat. Daneben haben Klaviere und Gitarren aber auch unterschiedliche Eigenschaften: Klaviere haben die Eigenschaft Tastenanzahl. Gitarren haben die Eigenschaft Saitenanzahl. Wenn wir also nach dem obigen System die Klassen für Klaviere und Gitarren schreiben, sähe das in etwa so aus:

Gitarre
   Hat folgende Eigenschaften:
   Alter
   Preis
   Saiten

   Hat folgende Fähigkeiten:

   ...

Klavier
   Hat folgende Eigenschaften:
   Alter
   Preis
   Tasten

   Hat folgende Fähigkeiten:

   ...

Fällt Ihnen etwas auf? Da ist etwas doppelt. Man kann das strukturieren, indem man eine Klasse Instrument erstellt.

Instrument
   Hat folgende Eigenschaften:
   Alter
   Preis

   Hat folgende Fähigkeiten:

   ...

31und dann sagt, dass Gitarren und Klaviere eine besondere Art von Instrumenten sind:

Gitarre ist ein Instrument
   Hat folgende zusätzliche Eigenschaften:
   Saiten

   Hat folgende Fähigkeiten:

   ...

Klavier ist ein Instrument
   Hat folgende zusätzliche Eigenschaften:
   Tasten

   Hat folgende Fähigkeiten:

   ...

Man sagt, dass die Klassen Gitarre und Klavier von Instrument abgeleitet sind. Die Klasse Instrument bezeichnet man als »Basisklasse«, Gitarre und Klavier als »Subklassen«. (Oder ausgehend von Gitarre wäre diese die Basisklasse und Instrument die Superklasse. Eine Frage des Startpunktes der Betrachtung.) Der Witz ist übrigens, dass auch eine nachträgliche Erweiterung der Basisklasse Instrument zu einer Erweiterung der abgeleiteten Klassen Gitarre und Klavier führt. Füge ich etwa in Instrument eine neue Eigenschaft Farbe ein, so haben auch die Subklassen Gitarre und Klavier diese Eigenschaften.

Das Ganze gilt übrigens nicht nur für Eigenschaften, sondern auch für Methoden. Wir können also etwa bereits Instrument eine Methode spielen geben. Diese Methode hätten dann auch automatisch die Subklassen Gitarre und Klavier. Und man kann ebenso die Subklassen mit Methoden erweitern, etwa der Gitarrenklasse eine weitere Methode gezupftSpielen geben.

Wir lernen also, dass man durch Ableitung Eigenschaften und Fähigkeiten strukturieren und erweitern kann.

Überschreiben und Polymorphie

Jetzt mögen Sie sich gefragt haben, wieso es überhaupt sinnvoll sein kann, bereits der Basisklasse Instrument eine Methode spielen zu geben, weil man ja nun Gitarren und Klaviere auf ganz unterschiedliche Weise spielt. Gut, ich kann einwenden, dass dennoch diese Methode logisch vorhanden ist, weil jedes Instrument gespielt werden kann und es sich daher um eine Fähigkeit bereits des Instrumentes handelt. Aber das wird Sie wenig beruhigen, weil man einfach nicht das Programm für diese Methode schreiben kann, also abstrakt, ohne Rücksicht auf die Subklasse: Es gibt keine Musiklehrer für »Instrumente spielen«. Es gibt nur Lehrer für bestimmte Instrumente.

Und hier kommen wir zu einem weiteren Punkt: Methoden, also die Fähigkeiten, kann man in einer Subklasse nicht nur erweitern, sondern auch ändern. Der übliche Grund 32dafür ist, dass zwar die Basisklasse ein sinnvolles Verhalten aufweist, man aber dennoch in einer Subklasse ein geeigneteres programmieren will.

Konzentrieren wir uns zunächst nur auf die Gitarre. Sie werden mir Recht geben, dass man die Methode spielen sinnvollerweise für eine Gitarre programmieren könnte. Das wäre dann das Standardgeklimper auf einer Gitarre. Wenn man jetzt eine Subklasse Jimi-Hendrix-Gitarre programmiert, so wird die Art des Spielens der Gitarre doch änderungsbedürftig. Niemand spielt so Gitarre wie Jimi Hendrix. Und jetzt schreiben wir uns einfach eine neue Methode spielen, die eben anders funktioniert. Die Methode spielen in der Klasse Jimi-Hendrix-Gitarre überschreibt dann die Methode spielen in der Klasse Gitarre.

Ähnlich verhält es sich bei Instrument und dessen Subklassen. Ich kann vermutlich gar keine sinnvolle Methode schreiben. Das ist aber nicht schlimm. Ich lasse sie einfach leer und übertrage damit den Subklassen Gitarre und Klavier die Verantwortung, dort etwas Sinnvolles hinein zu schreiben. Man nennt eine solche Methode wie spielen in der Klasse Instrument eine »virtuelle Methode«. Sie gehört zwar logisch zum Instrument, weil man jedes Instrument spielen kann, aber ist inhaltlich noch nicht da, man kann die konkreten Schritte zum Spielen eines Instrumentes eben nur in Bezug auf ein bestimmtes Instrument programmieren.

Nun stellt sich aber die Frage, welche Methode ausgeführt wird, wenn eine Nachricht spielen an ein Objekt geschickt wird. Die einfache Antwort: die desjenigen Objektes, das Empfänger ist. Empfängt also ein Instanzobjekt der Klasse Gitarre diese Nachricht, so führt es die Methode aus, die in seiner Klasse Gitarre vorgegeben ist. Erhält ein Instanzobjekt der Klasse Jimi-Hendrix-Gitarre diese Nachricht, so wird die Methode ausgeführt, die bei der Klasse Jimi-Hendrix-Gitarre angegeben ist. Dieselbe Nachricht kann also in Abhängigkeit vom Empfänger zu verschiedenen Methoden, Programmstücken führen. Diesen Effekt bezeichnet man als »Polymorphie« (Vielgestaltigkeit).

Wenn übrigens eine Klasse nicht von der Möglichkeit Gebrauch macht, eine Methode zu überschreiben, so wird einfach in der übergeordneten Klasse nach einer passenden Methode gesucht. Gibt es dort keine entsprechende Methode, dann bei der nächsthöheren und so weiter. Hat man sich auf diese Weise bis zur höchsten Klasse gehangelt und diese verfügt immer noch über keine entsprechende Methode, so erzeugt das Computerprogramm einen Fehler.

Dabei ist aber ein Aspekt wichtig, den wir später noch besprechen werden: Derjenige, der die Nachricht versendet, weiß möglicherweise gar nicht, dass er es mit einer Subklasse zu tun hat. Stellen Sie sich eine Schreckenscombo vor, die aus einem Klavier und einer Gitarre besteht. Bei der Erzeugung der Instanzen muss natürlich angegeben werden, was ich will:

Instrument1 ist ein Instrument
Speichere in Instrument 1 eine Gitarre
Instrument2 ist ein Instrument
Speichere in Instrument2 ein Klavier

33Sie sehen hier schon, dass ich ohne Weiteres eine Gitarre bzw. ein Klavier in einer Speicherstelle ablegen darf, die Instrumente speichert. Klar: Gitarren und Klaviere sind ja Instrumente. Wieso sollte das verboten sein? Und ein ganz anderer Programmteil, der von all diesen Subklassen nichts weiß, startet jetzt das Konzert:

Instrument1 spielen
Instrument2 spielen

Im ersten Fall wird eine Gitarre gespielt, im zweiten ein Klavier, obwohl dort nichts von Gitarren und Klavieren steht. Die in Instrument1 gespeicherte Instanz hat sich gemerkt, dass sie eine Gitarre ist, und führt daher die Methode spielen von Gitarre aus. Entsprechendes gilt für das Klavier.

Also, zusammengefasst: Eine Subklasse kann bestehende Methoden einer Basisklasse überschreiben, was bedeutet, dass bei Empfang einer entsprechenden Nachricht anstelle des Programmteiles in der Basisklasse der Programmteil in der Subklasse ausgeführt wird. Wird sie nicht überschrieben, so wird die Methode aus der Basisklasse gewählt. Gibt es in der gesamten Ahnengalerie keine passende Methode, so erzeugt dies einen Fehler.

Erweiterung oder Spezialisierung

Widersprechen sich die Begriffe Spezialisierung und Erweiterung in einer Subklasse eigentlich nicht? Ist es nicht vielmehr so, dass eine Erweiterung etwas allgemeiner macht, also das Gegenteil von einer Spezialisierung ist?

Kommt drauf an, und zwar letztlich darauf, dass die Erweiterung eine Spezialisierung ist: Stellen Sie sich die Klasse Arzt vor. Die Objekte dieser Klasse hätte Fähigkeiten, die jeder Arzt hat, die man so in einem medizinischem Grundstudium erlernt. Dann gibt es Fachärzte als Spezialisten. Die können mehr auf ihrem Spezialgebiet, haben zusätzliches Wissen. Ihre Spezialisierung liegt also gerade in dem Mehr. Sie stimmen mir sofort zu, dass das logisch ist: Sie sind Spezialfälle, weil sie eine Erweiterung sind.

Jetzt haben Mediziner aber eine geniale Idee gehabt: den Facharzt für Allgemeinmedizin. Ist das nicht irre? Ein Spezialist für das Allgemeine! Ideen haben die Leute ... Ist das jetzt ein allgemeiner Arzt (Basisklasse Arzt), wie das Wort Allgemeinmedizin vermittelt? Oder ist das ein Spezialist (Subklasse von Arzt) wie das Wort Facharzt vermittelt? Überlegen wir uns das einmal: Auch ein Facharzt für Allgemeinmedizin kann mehr als andere Ärzte, wenn auch auf breitem Gebiet. Es gibt sicherlich Dinge, mit denen er sich auskennt, die ein Facharzt für Chirurgie nicht einmal mit der Zange anfassen würde. Er ist also ein Spezialist. Und daher bildet er nicht die Basisklasse Arzt, sondern davon eine Subklasse Allgemeinmediziner, wie die anderen Fachärzte auch.

34Image

Behauptungen über das Mindestwissen von Ärzten werden in der Subklasse bestätigt.

Es gibt ein System, um zu überprüfen, ob die Anordnung von Klassen untereinander rich-tig ist. Sie müssen dazu einfach Behauptungen über die Basisklasse aufstellen. Hier etwa: »Hat medizinisches Wissen aus dem Grundstudium.« Und dann müssen Sie in einem zweiten Schritt überprüfen, ob jede einzelne dieser Behauptungen auch für die Subklassen gilt. Das wäre hier der Fall. Denn bei beiden Subklassen liegt in allen Bereichen mindes-tens das Wissen der Basisklasse vor.