1
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
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.
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.
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.
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.
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.
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
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
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
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.
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:
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.
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 ...
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.
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.
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.
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.
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.
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:
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.
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.
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.
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.
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.