Objective-C

Programmiersprache
Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 27. Mai 2005 um 19:44 Uhr durch 80.130.140.44 (Diskussion) (fluechtigkeitsfehler berichtigt (variable heisst objekt)). Sie kann sich erheblich von der aktuellen Version unterscheiden.

Objective-C, oft auch kurz Obj-C genannt, erweitert die Programmiersprache C um Eigenschaften, welche die objektorientierte Programmierung unterstützen.

Objective-C verwendet eine an Smalltalk angelehnte Syntax zur Beschreibung der objektorientierten Erweiterungen. Im Gegensatz zu C++ sind die objektorientierten Erweiterungen strikt von der normalen C-Syntax getrennt. Diese strikte Trennung erlaubt es das gleiche Konzept zur Erweiterung auf andere imperative Sprachen anzuwenden; so existiert z.B. ebenfalls Objective Pascal.

Deutlich wird dies etwa bei der Versendung von Nachrichten, die mit [] geklammert werden. Außerdem verwendet man sog. "named parameters":

Programmbeispiel

id *aDictionary = [[NSMutableDictionary alloc] init];

[aDictionary setObject:@"eier" forKey:@"egg"];
[aDictionary setObject:@"auto" forKey:@"car"];
[aDictionary setObject:@"Hallo Welt!" forKey:@"hello world!"];

NSLog([aDictionary objectForKey:@"hello world!"]);

Geschichte

Objective-C wurde hauptsächlich von Brad Cox in den 80er Jahren bei Stepstone entwickelt, später dann von NeXT in die GNU Compiler Collection integriert um als Basis für NextStep zu dienen. Objective-C konnte sich gegenüber C++ niemals wirklich durchsetzen, ist aber bis heute die präferierte Sprache für Cocoa-Programmierung unter Mac OS X.

Wesentliche Eigenschaften

Objective-C ist aufgrund seiner im Gegensatz zu C++ anderen Entwicklungsgeschichte hiervon ganz wesentlich zu unterscheiden. Dies mag an typischen Eigenschaften erläutert werden:

Klassenobjekte: Objective-C besitzt sog. Klassenobjekte. Dies bedeutet, das sowohl die Klasse als auch ein von ihr instantiiertes Objekt (sog. Instanzobjekte), Objekte sind. Dies führt dazu, dass es für die Konstruktion von Instanzobjekten (also Objekten im C++-Sinne) keiner Sonderrolle der Creatoren bedarf und auch ein gesondertes Schlüsselwort new überflüssig ist. Vielmehr funktioniert in der Regel die Erzeugung von Instanzen über mehrere Methoden der Klasse. Da dies im Gegensatz zum Schlüsselwort new jedoch der eigenen Implementierung zugänglich ist, besteht eine größere Flexibilität: Es können etwa "in Wahrheit" Subklassen zur Objekterzeugung verwendet werden, es können bereits erstellte Instanzobjekte wiederverwendet werden. Die gesamte Objekterzeugung ist also programmierbar. Die Grenzen bestimmt lediglich die konkrete Implementierung der Methode und ihre Deklaration. In C++ lässt sich dieser Effekt über zusätzliche Objekte, sog. Factories größtenteils nachbilden.

Spätes Binden (late binding, dynamic binding): Objective-C bindet einen Methodenaufruf erst zur Laufzeit an eine Methode. Grundsätzlich ist dies auch in C++ so. Jedoch muss in C++ bereits zur Übersetzungszeit sichergestellt sein, dass eine Methode existiert, weil sie zu der Klassenhierarchie gehört. C++ ist also nur bereit, innerhalb eines Zweiges einer Hierarchie spät zu binden, während Objective-C dies unabhängig von der Stellung einer Klasse in einem Hierarchiebaum macht. Dies soll an einem syntax-neutralem Beispielcode verdeutlicht werden:

Klasse A
  methode()
Klasse B von Klasse A
  methode()
Klasse C
  methode()
...
// Spätes binden in C++
A* objekt = new B;
objekt->methode();  // Ruft in Wahrheit B::methode auf
objekt = new C;     // Führt zu Fehlern, da typfremd.
objekt->methode();  // Auch mit casting geht dies nicht, weil methode()
                    // in einem anderen Zweig des Baumes auftaucht, 
                    // obwohl C::methode() sehr wohl existiert
// Spätes binden in oC
id objekt = new B;  // id bedeutet "Irgend ein Objekt"
objekt->methode();  // Funktioniert, weil B methode() kennt
objekt = new C;
objekt->methode(); // Funktioniert auch, weil C die methode() kennt
                    // Wo sie in der Klassenhierarchie bekannt ist,
                    // spielt keinerlei Rolle

Zu diesem Zweck führt Objective-C zur Laufzeit umfangreiche Informationen über ein Objekt mit, was über RTTI hinausgeht.

Aus dem letztlich gleichen Grunde ist es auch ohne weiteres möglich, zur Laufzeit erst eine Methode zu bestimmen. Die Methode kann sich ähnlich wie bei einem Methodenzeiger in einer Variablen befinden, die erst zur Laufzeit mit einem Wert besetzt wird:

SEL methode;
methode = @selector( eineMethode );
[objekt performSelector:methode]; // Ruft die Methode eineMethode auf
methode = @selector( andereMethode );
[objekt performSelector:methode]; // Ruft andereMethode auf

Von dieser Technik macht etwa Cocoa bei der Bindung von Interface-Elementen an Methoden regen Gebrauch. Die Bestimmung der Methode kann auch durch ihren Klarnamen erfolgen.

Typkonzept: Auf den ersten Blick unterschiedlich ist das Typkonzept. Objective-C kennt den Typen id, der nicht mit void* verwechselt werden darf. Ein Objekt von dem Typen id ist irgendein Objekt. Was mit diesem Objekt angefangen werden kann, wird erst zur Laufzeit bestimmt. Hierzu existieren Methoden, etwas über das Objekt zu erfahren. Wichtig sind:

  • [obj class] // bestimmt die Klasse
  • [obj respondsToSelector:] // bestimmt, ob eine Methode vorhanden ist
  • [obj conformsProtocol:] // bestimmt, ob ein Protokoll implementiert ist

Das Typkonzept erlaubt zudem die Typisierung des allgemeinen Objektes oder anderer Objekte durch (formale) Protokolle. Diese legen einen Satz von Methoden fest. Auch diese Protokolle müssen nicht in einem Hierarchiebaum einheitlich sein, werden aber vererbt.

Die Typfreiheit erlaubt die Erstellung allgemeiner Container, die anders als templates auch typgemischt sein können.

NSMutableDictionary* meineWelt;
// Eine Map mit einem String, einer URL und einem Wert
[meineWelt setObject:@"Ein Text" forKey:"Text"];
[meineWelt setObject:[NSURL urlWithString:@"www.prikalneg.de"]  forKey:"URL"];
[meineWelt setObject:[NSNumber numberWithInt:3] forKey:"Zahl"];
// Alle Objekte implementiern die Methode description
NSLog( @"%@", [[meineWelt objectForKey:@"Text"] description] );
NSLog( @"%@", [[meineWelt objectForKey:@"URL"] description] );
NSLog( @"%@", [[meineWelt objectForKey:@"Zahl"] description] );
Ausgabe:
Ein Text
www.prikalneg.de
3