1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

[Anfänger] Methodendekleration in Objective-C?

Dieses Thema im Forum "OS X-Developer" wurde erstellt von mad-boy, 10.05.08.

  1. mad-boy

    mad-boy Cox Orange

    Dabei seit:
    18.09.07
    Beiträge:
    97
    Hallo,
    ich fange gerade an mich mit Objektive-C zu beschäftigen. In meinem Studium lerne ich Java und bin außerdem recht fit in PHP. Die Kenntnisse der beiden Sprachen machen zwar einiges einfacher zu verstehen, an anderen Sachen scheitere ich aber auch weil einige Dinge für mich recht unlogisch klingen. An einer Stelle frage ich mich, ob ich das richtig verstanden habe:

    Eine Methodendekleration in der .h Datei sieht doch wie folgt aus:

    -(void)meineMethodeName:(NSString*)name Alter:(int)age;

    Laut meinem Buch (Objective-C und Cocoa) heißt das, wenn ich das richtig verstehe, dass die Methode den Namen "meineMethode" trägt, das "Name" was da ohne Leerzeichen folgt soll bereits eine art Hint für die erste Variable sein? Das kann aber doch irgendwie nicht sein, denn woher weiß Cocoa wann der Hint anfängt und der Methodenname endet?

    Der Aufruf dieser Methode würde dann wie aussehen? So:?
    [meineMethode Name:mad:"Test" Alter:17];
    und wenn ja, würde theoretisch auch das gehen:?
    [meineMethode :mad:"Test" :17];

    Denn ich habe irgendwo mal aufgeschnappt, dass die Worte vor dem : in der Dekleration nur Hilfestellungen sind? Also würde die Dekleration
    -(void)meineMethode:(NSString*)name :(int)age;
    den gleichen Effekt haben?

    Ihr merkt, ich blicke an diesem zentralen Punkt leider noch überhaupt nicht durch und es wäre super wenn jemand ein wenig Licht ins Dunkel bringen könnte.

    Liebe Grüße,
    Michael

    Ps: Vielleicht kann jemand mal beispielhaft folgenden Java Code in Objective-C übersetzen:?
    public static int summe(int zahl1, int zahl2) { }

    währe das das hier:?
    -(int)summeZahl1:(int)zahl1 Zahl2:(int)zahl2 { }
     
  2. gert

    gert Macoun

    Dabei seit:
    19.08.05
    Beiträge:
    118
    Hallo,

    hmm. Ich hab das Buch zwar nicht gelesen, aber ich schaetze mal, dass das mit dem Hint eher fuer den Leser des codes gedacht war.

    -(void)meineMethodeName:(NSString*)name Alter:(int)age;

    "meineMethode" soll im allgemeinen beschreiben, was diese Methode macht
    "Name" gibt dann an, wofuer der erste Parameter steht und
    "Alter" wofuer der zweite steht.

    Somit sollte es vielleicht so heissen, wenn das Ganze z.b. ein Setter sein soll
    - (void)setName:(NSString *)aName age:(int)anAge;

    oder du hast ne Klasse Person und brauchst nen Initializer
    - (id)initWithName:(NSString *)aName age:(int)anAge;

    oder du hast ne Klassenmethode der Klasse Person
    + (id)personWithName:(NSString *)aName age:(int)anAge;

    Die Aufrufe waeren dann ungefaehr so:

    1) [aPerson setName:mad:"Paul" age:33];
    2) Person *aPerson = [[Person alloc] initWithName:mad:"Paul" age:33];
    3) Person *aPerson = [Person personWithName:mad:"Paul" age:33];

    Vielleicht wird daraus ein wenig klarer, wie der Methodennameaufbau funktioniert.

    Ich moechte zwar nicht behaupten, dass man die Bezeichner vor dem Doppelpunkten nie weglassen koennte, aber dennoch.... warum sollte man das tun?
    Schliesslich sagt dir das Wort, wofuer der folgende Parameter steht.
    Also komm mal von der Java Denkweise ein wenig weg mit den elendig langen Parameterlisten und ueberleg, wie du nen satz sprichst. Bestimmt nicht "setze Name Alter Paul 33" sondern wahrscheinlich eher sowas wie "setze Name Paul Alter 33".
    So richtig super klingt das zwar auch nicht, kommt aber der natuerlichen Sprache doch naeher als ersteres.

    Und genauso sind halt die Methoden aufgebaut. Ach und die Uebersetzung deines Java Beispiels stimmt...

    Beste Gruesse,
    Gert
     
  3. mad-boy

    mad-boy Cox Orange

    Dabei seit:
    18.09.07
    Beiträge:
    97
    Hey schonmal danke für die Hilfe!

    Also rein technisch gehört aber bei
    - (id)initWithName:(NSString *)aName age:(int)anAge;

    das "Name" nach dem With schon zum Methoden Name, wogegen das age praktisch eine Hilfestellung ist?

    Die Methode heißt also so wie sie intern abgelegt wird dann initWithName?
    Finde ich ehrlich gesagt nicht so gut, liegt aber vielleicht wirklich daran dass ich jetzt im Moment von Java komme. Denn genau genommen initialisiert initWithName ja eben nicht nur mit einem Namen sondern auch mit Alter, was ich aber nicht sehe, wenn ich mir nur die Liste der verfügbaren Methoden anschaue, oder?

    Ich habe auch mal ein wenig rum gespielt und festgestellt, dass der Methodenaufruf genauso lauten muss wie die Methodendekleration! Also ich kann oben besagte Methode nicht aufrufen über [Person initWithName:mad:"Paul" :33]; sondern das age muss dann schon mit. Fehlt es in der Methodendekleration dagegen, dann darf es im Methoden Aufruf auch nicht stehen!? Was soviel heißt wie: Wenn der, der die Klasse geschrieben hat sauber gearbeitet hat, dann bin ich gezwungen sauber zu arbeiten. Hat der dagegen den Code einfach nur schnell runtergeschrieben und diese "Hinweise" weg gelassen, dann bin ich gezwungen auch unsauber zu arbeiten... seltsame Sache! =)

    Ich habe das mehr so verstanden, dass mir dieses age dann als Hinweis in meiner IDE, also z.B. in xCode angezeigt wird, nicht dass das ganze auch in den Aufruf muss. Aber nun gut, muss man sich dran gewöhnen! =)

    Danke für die Infos!

    Liebe Grüße,
    Michael
     
  4. below

    below Kalterer Böhmer

    Dabei seit:
    08.10.06
    Beiträge:
    2.865
    First things first: It's Xcode, not xCode or XCode or x-code. Remember that now.
    -- Chris Espinosa

    Nein.

    Zunächsteinmal muss man wissen, das Objective-C -- wie Smalltalk -- versucht, natürliche Sprache nachzubilden:

    [Lisa throw:[ball withColor:red] to:Tom];

    Objective-C Methoden haben eine sog. "Signatur". Für das Beispiel:
    - (id)initWithName:(NSString *)aName age:(int)anAge;

    ist die Signatur "initWithName:age:" . Das ist der "Interne Name" der Funktion. (Das erklärt, warum Objective-C kein Type Overloading erlaubt, wie C++)

    Und ja, Du musst natürlich die Methode so aufrufen, wie es ihrer Signatur entspricht. Man kann eklig programmieren, und eine Methode so definieren:

    - (id)uglyMethodWithTwoParams:(id)firstParam :(id)secondParam;

    Der Aufruf wäre dann:

    [myUglyObject uglyMethodWithTwoParams:mad:"test" :mad:"toast"];

    Man kann in Objective-C auch nicht (wie in C++) Parameter mit einem Default Wert belegen. Deshalb musst Du immer alle Parameter angeben.

    Beantwortet das Deine Frage?

    Alex
     
  5. mad-boy

    mad-boy Cox Orange

    Dabei seit:
    18.09.07
    Beiträge:
    97
    Alles klar, danke :)

    Dann werde ich mich jetzt mal an die nächsten Seiten im Buch machen und diese mit Xcode ;) nachbasteln. :)

    Vielen Dank euch beiden!
     
  6. tjp

    tjp Baldwins roter Pepping

    Dabei seit:
    07.07.04
    Beiträge:
    3.250
    Also, zu diesem Schluß bin ich nie gekommen, und ich halte ihn auch für sehr gewagt. In Smalltalk-80, The Language (ein lesenswertes Buch gerade wenn man Objective-C verstehen will) ist davon auch auch kein Rede.

    Nein, das ist der Name der Methode. Objective-C erfordert es alle Parameter ab dem zweiten Parameter zu benennen, weil intern die Signatur wie folgt aussieht "-(id)initwithName: (id) age: (id)". Andere Programmiersprachen verwenden zur Unterscheidung von Methoden mit gleich vielen Parametern deren Typ, da aber in Objective-C letztlich auch PODs nur als (id) übergeben werden funktioniert dies so nicht, und man muß Parametern zusätzlich benennen. In den internen Datenstrukturen wird auch nie die Signatur gespeichert, weil es von Anfang an klar ist, daß der Typ für ein Objekt immer (id) ist, daher reichen die Namen für die Unterscheidung aus.

    Das hat damit nichts zu tun, das ist so, weil Objective-C dynamisches Dispatching macht und kein statisches Dispatching. Typ Overloading funktioniert eben nur dann, wenn man keine polymorphen Methodenaufrufe hat, die sich aber in Objective-C nie vermeiden lassen.
     
  7. below

    below Kalterer Böhmer

    Dabei seit:
    08.10.06
    Beiträge:
    2.865
    Das Beispiel mit "Lisa throw Ball" habe ich auch aus einem Smalltalk Buch. Allerdings kann ich den Titel nicht mehr wiedergeben.

    Offensichtlich nicht (siehe meinen Beitrag)

    Stimmt, da habe ich die Signatur mit dem Selector verwechselt.

    Alex
     
  8. tjp

    tjp Baldwins roter Pepping

    Dabei seit:
    07.07.04
    Beiträge:
    3.250
    Es muß dazu noch ergänzt werden, daß die notwendig ist, sobald es mehr als eine Methode mit n Parametern gibt. Objective-C ist zum Beispiel nicht in der Lage folgendes zu Unterscheiden:
    Code:
    // C++ Code
    class fooClass {
    public:
      void foo (char);
      void foo (short);
      void foo (int);
      void foo (long);
    };
    
    void fooClass::foo(char) {}
    void fooClass::foo(short) {}
    void fooClass::foo(int) {}
    void fooClass::foo(long) {}
    
    // pseudo Objective-C Code
    
    @interface NameCollision : NSObject {
    	int numerator;
    }
    
    -(void) foo: (char) c;
    -(void) foo: (short) s;
    -(void) foo: (int) s;
    -(void) foo: (long) l;
    
    @end
    
    @implementation NameCollision
    
    -(void) foo: (char) c {}
    -(void) foo: (short) s {}
    -(void) foo: (int) i {}
    -(void) foo: (long) l {}
    @end
    Interessant ist vor allem, daß es erst bei der Definition knallt und nicht schon bei der Deklaration. Aber das ganze Message Sending ist bei Objective-C nichts anderes als syntaktischer Zucker für OO-Hack wie etwa Xt. Typsicher ist das Dispatching von Objective-C jedenfalls nicht.
     
  9. tjp

    tjp Baldwins roter Pepping

    Dabei seit:
    07.07.04
    Beiträge:
    3.250
    Schade, gerade die Autoren hätten mich interessiert. Denn das Buch was ich habe ist von den beiden Designer von SmallTalk.
     
  10. below

    below Kalterer Böhmer

    Dabei seit:
    08.10.06
    Beiträge:
    2.865
    Das eine hat mit dem anderen nichts zu tun. Objective-C kann einfach keine Methoden nur anhand der Parametertypen unterscheiden, wie wir beide schon geschrieben haben.

    Auch

    -(void) this:(id)foo withThat:(int)bar

    und

    -(void) this:(int)foo withThat:(id)bar

    kann Objective-C nicht unterscheiden. Ob ich die Parameter dabei benenne oder nicht ist vollkommen irrelevant.

    Alex
     
  11. tjp

    tjp Baldwins roter Pepping

    Dabei seit:
    07.07.04
    Beiträge:
    3.250
    Doch, das hängt direkt miteinander zusammen.
    Code:
    -([color=green]void[/color]) [color=red]foo[/color]:([color=green]id[/color])[color=blue]this[/color] [color=red]withThat[/color]:([color=green]int[/color])[color=blue]bar[/color]
    
    Die Farbe Rot markiert die Namen der Methode bzw. des Parameters, die Farbe Blau markiert den Namen der Variablen, die Farbe Grün markiert die Typen. Ich beziehe mich auf den Namen der Parameter und nicht den Variablen Namen in den Deklarationen oder Definitionen. Objective-C verlangt (damit es zu keinen Kollisionen kommt), daß jeder Parameter ab dem zweiten Parametern benannt wird. Das ist wegen der laxen Typprüfung notwendig und deutet darauf hin, daß das ganze über einen simpler Wrapper für C-Funktionen mit variabler Anzahl von Parametern abläuft.

    Zum Vergleich das Ganze analog farblich verdeutlicht an einer C++ Methode
    Code:
    [color=green]void[/color] [color=purple]Foo[/color]::[color=red]foo[/color] ([color=green]Foo*[/color] [color=blue]self[/color], [color=green]int[/color] [color=blue]bar[/color]);
    
    Die Farbe Purpur steht hier für die Klassen/den Namensraums.
     
  12. MacApple

    MacApple Lord Grosvenor

    Dabei seit:
    05.01.04
    Beiträge:
    3.470
    Nein, das verlangt Objective-C nicht. Es muss nur der Methodenname/Selector eindeutig sein. So etwas hier:
    Code:
    @interface MyClass : NSObject
    {
    }
    
    - (void)foo:(id)this :(int)x;
    - (void)bar:(id)this :(int)x;
    
    @end
    ist kein Problem.

    Eine entsprechende Objective-C Methode kann genauso gut so aussehen:
    Code:
    - ([COLOR="Green"]void[/COLOR])[COLOR="Red"]foo:[/COLOR]([COLOR="Green"]id[/COLOR])[COLOR="Blue"]this[/COLOR] [COLOR="Red"]:[/COLOR]([COLOR="Green"]int[/COLOR])[COLOR="Blue"]bar[/COLOR];
    MacApple
     
  13. Amin Negm-Awad

    Amin Negm-Awad Süsser Pfaffenapfel

    Dabei seit:
    01.03.07
    Beiträge:
    665
    Nein, auf Seite 101 im grauen Kasten wird gesagt, dass der Parametername ein Teil des Methodennamens darstellt.

    Einfach eine Beschreibung.

    Anhand des Leerzeichens nach dem ersten Parameter.

    Nein, ich suche jetzt aber nicht eines der 268743568 Beispiele heraus

    Das hast du falsch aufgeschnappt. Sie sind Bestandteil des Methodennamens, wie dies auch auf Seite 1010 erläutert wird.

     
    #13 Amin Negm-Awad, 13.05.08
    Zuletzt bearbeitet: 13.05.08
  14. Amin Negm-Awad

    Amin Negm-Awad Süsser Pfaffenapfel

    Dabei seit:
    01.03.07
    Beiträge:
    665
    Das ist nicht richtig.

    a) Es ist nicht vorgeschrieben, dass weitere Paramneter benannt werden. Wie auch im Buch erläutert, kannst du sehr wohl eine Methode -(int)add:(int)summand1 :(int)summand2 schreiben.

    b) Die weiteren Ausführungen, warum da angeblich notwendig sein soll, sind damit obsolet.
     
  15. Amin Negm-Awad

    Amin Negm-Awad Süsser Pfaffenapfel

    Dabei seit:
    01.03.07
    Beiträge:
    665
    Nein, die nur angeblich notwendige Benennung des zweiten Parameters deutet auf gar nichts hin, weil sie nicht existiert. Der Anhang kompiliert jedenfalls einwandfrei und gibt add:: als Selektor aus.

    Es gibt sogar in Cocoa eine Methode (möglicherweise mehr) die das benutzt. Hier werden IIRC X- und Y- Koordinaten übergeben.
     

    Anhänge:

  16. Amin Negm-Awad

    Amin Negm-Awad Süsser Pfaffenapfel

    Dabei seit:
    01.03.07
    Beiträge:
    665
    Nein, du hast überhaupt nichts verwechselt, also schon, also jein.

    a) Für den Aufruf ist der Selektor maßgeblich. Um dieses Thema ging es. Dafür ist die Parametrisierung gleichgültig! Die Auswahl der Methode erfolgt ausschließlich über den Selektor, der genau deshalb so heißt.

    b) Die Signatur sieht auch nicht so wie von tjp angegeben aus, wobei ich schon nicht weiß, was mit "intern" gemeint ist. (Compiler oder Laufzeitumgebung?)

    Die Signatur enthält nämlich ausschließlich Informationen über die Typen der Parameter und des Rückgabewertes. Für die obig Methode sähe die Signatur also etwa (wie auch immer man das notieren möchte) so aus:
    0: @
    1: :
    2: @
    3: i
    R: v

    Wobei ich jetzt die einzelnen Zeichen für das Type-Encoding nicht sicher im Kopf habe. Können auch andere sein. Ich bin zu faul zum nachschauen. (Siehe Edit)

    Damit haben übrigens etwa alle Actionmethoden exakt dieselbe Signatur.
    +++
    Edit: Habe es doch noch einmal nachgeschlagen.
    Für den Selektor steht : (nicht S) und für den signed Integer i (nicht I) Man schreibt übrigens kürzer häufig:
    v@:mad:i
    für die Signatur.
     
  17. Amin Negm-Awad

    Amin Negm-Awad Süsser Pfaffenapfel

    Dabei seit:
    01.03.07
    Beiträge:
    665

Diese Seite empfehlen