Objective-C: Klassen (1) - die Grundlagen



  • 1 Klassen in Objective-C

    Vorwort

    C++ ist nicht der einzige Ansatz gewesen, um der Sprache C die Möglichkeiten objektorientierter Programmierung einzuhauchen. Es gab die Entwicklung von Objective-C, die ebenfalls diese Möglichkeiten ergänzte, und gleichzeitig eine Kompatibilität zu C erhielt. Die Sprache war in der Breite wenig bekannt, da sie vor allem auf den Mac-Systemen zur Applikationsentwicklung benutzt wurde und wird. Durch den Boom von Mac, iPhone und wohl bald auch iPad wird die Sprache allerdings zusehends wichtiger werden, daher gibt es im Magazin nun eine einführende Artikelserie zu Objective-C (kurz: ObjC).

    Dieser Artikel ist von http://www.cocoa-coding.de übernommen und behandelt wie Klassen und Objekte in Objective-C aufgebaut sind.

    1.1 Grundlagen

    Die wichtigsten Bausteine bei der objektorientierten Programmierung sind Klassen, denn von Klassen kann man Instanzen erzeugen, sogar beliebig viele.

    Und jetzt das ganze ohne Fachchinesisch:

    Stellen Sie sich Klassen als eine Art Bauplan vor, ein Bauplan nach dem Objekte erzeugt werden, Objekte im Speicher Ihres Computers. Sie haben schon Klassen kennengelernt. Klassen des Foundation-Framework wie NSString oder auch Klassen, die von Ihnen erstellt wurden, wie die MyController -Klassen für Ihre Anwendungen.

    Klassen bestehen im wesentlichen aus zwei Arten von Code: Variablen, also Objekte, um Informationen zu speichern, und Methoden, um eben diese Informationen zu manipulieren.

    Eine Klasse ist, wie anfangs erwähnt, nur ein Bauplan mit dem man, bis auf einige Ausnahmen, nicht viel anfangen kann. Erst wenn Sie von einer Klasse ein Objekt erzeugen wird es interessant. Solche Objekte nennt man auch Instanz und davon kann man beliebig viele erzeugen.

    Die Variablen in einer Klassen nennt man Instanzvariablen, denn immer wenn Sie eine weitere Instanz der Klasse erzeugen, wird für alle Variablen dieser Klasse auch Speicherplatz reserviert. Jede Instanz hat also ihre eigenen Variablen mit eigenem Speicherplatz.

    Streng genommen müsste man auch Methoden einer Instanz als Instanzmethoden bezeichnen, das geschieht aber eher selten, denn diese Methoden sind der Normalfall. Allerdings gibt es auch andere Methoden, die Klassen-Methoden. Diese können benutzt werden, ohne dass eine Instanz der Klasse erzeugt werden muss. Dazu aber später mehr.

    Die Instanzvariablen sind immer vor Veränderungen von aussen geschützt, in der objektorientierten Programmierung nennt man diese Zustand "privat".
    Methode in der Klassen können die Variablen ändern, von ausserhalb geht das aber nicht.

    Es wäre natürlich Unsinn, wenn man Variablen hätte, die man nicht verändern oder auslesen könnte. Natürlich geht das, aber es geht eben nur über die Methoden der Klasse. Methoden, mit denen die Instanzvariablen direkt verändert werden, werden auch Accessor-Methoden genannt.

    Angenommen eine Klasse hätte eine Instanzvariable für das Alter einer Person:

    int age;
    

    Ausserhalb der Instanz können Sie nicht auf diesen Wert zugreifen, Sie benötigen Accessor-Methoden, die dann so aussehen:

    -(void) setAge:(int)x 
    { 
        age = x; 
    } 
    
    -(int) age 
    { 
        return age; 
    }
    

    Die Methode setAge ermöglicht das Setzen des Wertes, wohingegen die Methode age den Wert zurückgibt. Dass diese Methode genau so heisst wie die Variable, ist auch kein Zufall, sondern beabsichtigt und Sie sollen sich an diese Vorgaben halten.

    Das alles erscheint auf den ersten Blick sehr aufwendig, und das ist es auch. Accessor-Methoden haben aber durchaus Sinn, denn Sie ermöglichen zum Beispiel den zu setzenden Wert zu kontrollieren. So können Sie beispielsweise sicherstellen, dass einer Person kein negatives Alter zugewiesen wird. Mehr über Accessor-Methode erfahren Sie in einem folgenden Kapitel.

    Jetzt zurück zur Praxis. Starten Sie Xode und öffnen Sie wieder das Foundation Tool aus dem letzten Beispiel oder erzeugen sie ein neues Foundation Tool Programm.

    Um Ihrem Projekt eine weitere Klasse hinzuzufügen wählen Sie File -> New File aus dem Xcode Menu. Der zu wählende Typ ist natürlich eine Objective-C Klasse.

    Im nächsten Schritt werden Sie nach dem Klassennamen gefragt. Nennen Sie sie Person . Es gibt die Vorgaben, das Klassennamen immer mit Großbuchstaben beginnen sollen. Das ist natürlich kein Muss, es funktioniert auch anders. Trotzdem sollen Sie sich an dieser Stelle daran halten.

    Die Headerdatei (Person.h) ist überschaubar und bestimmt zwei Variablen, einen int -Wert und eine Zeichenkette vom Typ NSString . Da diese Variablen aber für jeglichen Code ausserhalb der Instanz nicht zugänglich ist, gibt es ein Paar Accessor-Methoden für jede Variable.

    #import <Cocoa/Cocoa.h>
    @interface Person : NSObject { 
        int age; 
        NSString *name; 
    } 
    
    -(void) setAge:(int)aAge; 
    -(int) age; 
    
    -(void) setName:(NSString *)aName; 
    -(NSString *)name; 
    
    @end
    

    Die Umsetzung, auch Implementation genannt, dieser Methoden geschieht in der Codedatei ( Person.m ) und sieht wie folgt aus.

    #import "Person.h"
    
    @implementation Person 
    
    -(void) setAge:(int)x 
    { 
        age = x; 
    } 
    
    -(int) age 
    { 
        return age; 
    } 
    
    -(void) setName:(NSString *)aName 
    { 
        [aName retain]; 
        [name release]; 
        name = aName; 
    } 
    
    -(NSString *)name 
    { 
        return name; 
    } 
    
    @end
    

    Die Accessor-Methoden für den int -Wert sind wahrscheinlich leicht verständlich. Im ersten Fall wird ein Wert per Methode übergeben und dieser dann auf die private Variable gesetzt. Die zweite Methode ist noch einfacher, hier wird einfach nur der Wert der Variablen zurückgegeben. Etwas komplizierter sind hingegen die Accessor-Methoden für die NSString Variable, sie tun aber prinzipiell nichts anderes. Dieser Aufwand ist nötig, weil es sich hier um einen Zeigertyp handelt. Der Methode wird also nicht wirklich ein Text übergeben, sondern eine Speicheradresse, an der dieser Text steht. Lassen Sie sich davon nicht irritieren. Mehr zum diesem Thema erfahren Sie später.

    Die Klasse ist fertig. Der nächste Schritt ist es, eine Instanz zu erzeugen und Werte zu zuweisen. Das machen Sie in der main -Methode des Foundation Tools.

    #import "Person.h"
    #import <Foundation/Foundation.h>
    
    int main (int argc, const char* argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    
        Person *myPerson = [[Person alloc] init]; 
        [myPerson setAge:32]; 
        [myPerson setName:@"Max Müller"]; 
    
        NSLog(@"Name: %@",[myPerson name]); 
        NSLog(@"Alter: %d",[myPerson age]); 
    
        [myPerson release]; 
        [pool drain]; 
        return 0; 
    }
    

    Die erste Zeile ist hier die wichtigste. Da die von Ihnen erstellte Klasse kein Teil des Foundation-Frameworks ist, muss sie erst durch eine Import-Anweisung bekannt gemacht werden.

    Eine Instanz der Personenklasse wird mit alloc und init erzeugt, diese Befehle kennen Sie noch nicht, aber die Erklärung folgt im nächsten Kapitel. Lassen Sie uns erst eine wenig aktiv programmieren, bevor wir uns mit der grauen Theorie beschäftigen müssen.

    Im nächsten Schritt werden dem Objekt Werte zugewiesen und mit NSLog wieder ausgeben. Wie Sie sehen, es funktioniert!

    Vielleicht stellen Sie sich jetzt die Frage, wozu man das Ganze braucht. Einer der Schwerpunkte der objektorientierten Programmierung ist die Wiederverwendbarkeit. Haben Sie einmal eine funktionsfähige Klasse erzeugt, können Sie diese in allen Ihren Programmen verwenden.
    Ein zweiter wichtiger Punkt ist die Kapselung. Instanzvariablen können nur durch Accessor-Methoden verändert werden. Diese Methoden sind Teil der Klasse, Sie können sie also nicht vergessen oder ignorieren. Erzeugen Sie eine neue Instanz, bekommen Sie immer das gesamte Paket, also Variablen und Methoden. Sie müssen auch nicht immer alle Accessor-Methoden implementieren, so gibt es zum Beispiel Variablen, die man nur lesen, aber nicht setzten kann. Solche Variablen sind nicht ungewöhnlich und enthalten meisten Rechenergebnisse der Klasse oder andere Werte die sich nach dem Instanzieren nicht mehr ändern lassen.

    Ein dritter nicht zu unterschätzender Punkt ist die Vererbung. Sie haben hier eine Klasse Person . Benötigen Sie in der Klasse aber weitere Variablen oder Methoden, müssen Sie nicht eine komplett neue Klasse programmieren, sondern Sie erzeugen eine Klasse, die von Person erbt und erweitern diese um alle benötigen Elemente.


Anmelden zum Antworten