• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Viele hassen ihn, manche schwören auf ihn, wir aber möchten unbedingt sehen, welche Bilder Ihr vor Eurem geistigen Auge bzw. vor der Linse Eures iPhone oder iPad sehen könnt, wenn Ihr dieses Wort hört oder lest. Macht mit und beteiligt Euch an unserem Frühjahrsputz ---> Klick

[Anfänger] Methodendekleration in Objective-C?

mad-boy

Cox Orange
Registriert
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 { }
 

gert

Macoun
Registriert
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
 

mad-boy

Cox Orange
Registriert
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
 

below

Purpurroter Cousinot
Registriert
08.10.06
Beiträge
2.858
First things first: It's Xcode, not xCode or XCode or x-code. Remember that now.
-- Chris Espinosa

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?

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
 

mad-boy

Cox Orange
Registriert
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!
 

tjp

Altgelds Küchenapfel
Registriert
07.07.04
Beiträge
4.059
Zunächsteinmal muss man wissen, das Objective-C -- wie Smalltalk -- versucht, natürliche Sprache nachzubilden:
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.

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

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

below

Purpurroter Cousinot
Registriert
08.10.06
Beiträge
2.858
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.
Das Beispiel mit "Lisa throw Ball" habe ich auch aus einem Smalltalk Buch. Allerdings kann ich den Titel nicht mehr wiedergeben.

Nein, das ist der Name der Methode. Objective-C erfordert es alle Parameter ab dem zweiten Parameter zu benennen
Offensichtlich nicht (siehe meinen Beitrag)

weil intern die Signatur wie folgt aussieht "-(id)initwithName: (id) age: (id)".
Stimmt, da habe ich die Signatur mit dem Selector verwechselt.

Alex
 

tjp

Altgelds Küchenapfel
Registriert
07.07.04
Beiträge
4.059
Offensichtlich nicht (siehe meinen Beitrag)
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.
 

below

Purpurroter Cousinot
Registriert
08.10.06
Beiträge
2.858
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

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
 

tjp

Altgelds Küchenapfel
Registriert
07.07.04
Beiträge
4.059
Das eine hat mit dem anderen nichts zu tun.
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.
 

MacApple

Schöner von Bath
Registriert
05.01.04
Beiträge
3.652
Objective-C verlangt (damit es zu keinen Kollisionen kommt), daß jeder Parameter ab dem zweiten Parametern benannt wird.
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.

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]);
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
 

Amin Negm-Awad

Süsser Pfaffenapfel
Registriert
01.03.07
Beiträge
665
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,
Nein, auf Seite 101 im grauen Kasten wird gesagt, dass der Parametername ein Teil des Methodennamens darstellt.

das "Name" was da ohne Leerzeichen folgt soll bereits eine art Hint für die erste Variable sein?
Einfach eine Beschreibung.

Das kann aber doch irgendwie nicht sein, denn woher weiß Cocoa wann der Hint anfängt und der Methodenname endet?
Anhand des Leerzeichens nach dem ersten Parameter.

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];
Nein, ich suche jetzt aber nicht eines der 268743568 Beispiele heraus

Denn ich habe irgendwo mal aufgeschnappt, dass die Worte vor dem : in der Dekleration nur Hilfestellungen sind?
Das hast du falsch aufgeschnappt. Sie sind Bestandteil des Methodennamens, wie dies auch auf Seite 1010 erläutert wird.

Also würde die Dekleration
-(void)meineMethode:(NSString*)name :(int)age;
den gleichen Effekt haben?{/Quote]
Nein, auch das wird im Kasten auf Seite 101 ausdrücklich erläutert.

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.
Bitte

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 { }
 
Zuletzt bearbeitet:

Amin Negm-Awad

Süsser Pfaffenapfel
Registriert
01.03.07
Beiträge
665
[…]
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 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.
 

Amin Negm-Awad

Süsser Pfaffenapfel
Registriert
01.03.07
Beiträge
665
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.[…]
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

  • Doppeldoppelpunkt.zip
    64,1 KB · Aufrufe: 66

Amin Negm-Awad

Süsser Pfaffenapfel
Registriert
01.03.07
Beiträge
665
Stimmt, da habe ich die Signatur mit dem Selector verwechselt.
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.