2012-10-15 4 views
8

sagen, wir haben diesen Block:Objective-C-Block-Parameter

int (^aBlock)(BOOL) = ^(BOOL param) { ... 

Mein gegenwärtiges Verständnis dafür ist: die erste int der Rückgabetyp ist, (^aBlock)(BOOL) gibt den Namen der Methode und die Art seines Parameter, und = ^(BOOL param) ist der Name des Parameters innerhalb des Blocks ... plus der Typ des Parameters wieder?

Warum ist die Syntax so, dass wir den Parametertyp zweimal auflisten müssen? Könnten die beiden Typen jemals anders sein?

Antwort

11

Es ist nicht ganz „Auflistung der Parameter zweimal eingeben“ Sie deklarieren im ersten Fall den Typ einer Blockvariablen, und im zweiten Fall definieren Sie ein Blockliteral. Dann weisen Sie das Literal dem Wert der Variablen zu. Man könnte sogar so etwas tun, was äquivalent ist und besser veranschaulicht die Tatsache, dass diese sind wirklich zwei völlig unabhängige Erklärungen, obwohl er mit einer assign-Anweisung zugeordnet ist:

id thisBlock = ^id (id x, NSUInteger idx) { 
    NSLog(@"x = %@",x); 
    return x; 
}; 

id (^thatBlock)(id obj, NSUInteger index) = thisBlock; 

Die Tatsache, dass sie jedes andere Mittel unabhängig sind es ist wahrscheinlich nicht einmal richtig, zu versuchen, irgendeine Art von Übertragung oder Vererbung von Tippinformationen von der linken Seite des Ausdrucks nach rechts bereitzustellen. Und ja, die Typen können unterschiedlich sein - bedenken Sie, dass dieser Code kompiliert und gut ausgeführt wird:

id (^thatBlock)(NSArray *, NSDictionary *, NSString *) = ^id (id x, id y, id z) { 
    NSLog(@"x = %@",x); 
    return x; 
}; 

thatBlock(@[],@{},@""); 

Hoffe, das hilft!

+0

Ja, das ist großartig, danke. Nur um zu verdeutlichen, ist Ihr zweites Stück Code ein Beispiel für die Übertragung von Tippinformationen (und daher verpönt)? – chm

+0

Nein, ich zeige nur, dass die Typen zwischen der linken und der rechten Seite unterschiedlich sein können und der Code kompiliert und ausgeführt wird. Es gibt nicht viel Typ-Überprüfung mit anderen Blöcken als Rückgabetypen, soweit ich das beurteilen kann. Es gibt keine Übertragung von Tippinformationen, da das nicht wirklich eine Sache ist. Ich habe das ein bisschen komisch formuliert, ich habe versucht zu sagen, dass selbst wenn der Compiler so etwas tun würde, es nicht unbedingt korrekt wäre, wie es ist einige polymorphe Eigenschaften von Blöcken, die ein solches Merkmal stören würde. –

1

Warum ist die Syntax so, dass wir den Parametertyp zweimal auflisten müssen?

Der Baustein auf diese Weise gestaltet, und so können Sie es wie folgt tun:

int (^aBlock)(BOOL); 

aBlock = ^(BOOL param) { 
    ... 
}; 

Es mag nur

- (int)aMethodWithParam:(BOOL)param; 

- (int)aMethodWithParam:(BOOL)param { 
    ... 
} 

Könnte die beiden Typen jemals anders sein?

Nö, und was mehr ist, sollte die Reihenfolge der Typen gleich sein, das heißt:

int (^aBlock)(BOOL, NSString*) = ^(BOOL param, NSString *aString) { 
    ... 
}; 

Und hier ist eine klare Abbildung für Block:

Image

2

Der Code Snippet, das Sie angegeben haben, ist keine Blockdeklaration: es ist eine Blockdeklaration und eine Blockdefinition. Zuerst erklären Sie eine Kennung aBlock genannt:

int (^aBlock)(BOOL) 

dann definieren Sie einen Block:

^(BOOL param) { ... 

Beide werden analysiert und getrennt ausgewertet. Da Sie dem anderen einen zuweisen, führt der Compiler eine Typüberprüfung durch, um sicherzustellen, dass der Ausdruck auf der linken Seite (Ihre aBlock Deklaration) vom selben Typ ist wie der Ausdruck auf der rechten Seite (die Blockdefinition). .

Also, die Antwort ist, diese Teile müssen separat ausgewertet werden. Da die Blockdefinition selbst kompiliert wird, müssen Sie den Typ param angeben, da der Compiler sonst nicht weiß, um welchen Typ es sich handelt. (Ja, Sie könnten in diesem Fall eine Ausnahme machen und über die Zuweisung schauen, aber überall sonst in der C-Sprache deklarieren Sie zuerst einen Typ, also warum anders?)

Aber - Sie können sagen - , wenn das stimmt, warum musste ich nicht den Rückgabetyp (int) auf der rechten Seite definieren?

Sehr scharf von Ihnen. Die Antwort besteht darin, dass Sie beim Schreiben eines Blockausdrucks den Rückgabetyp nicht definieren müssen, da der Compiler dies aus der return-Anweisung (oder einem Mangel davon) innerhalb des Blocks ableiten kann.

(Warum müssen Sie Rückgabetypen mit Funktionsdefinitionen enthalten? Nun, Geschichte, denke ich. Programmiersprache Definitionen von unvollkommenen Menschen geschaffen wurden.)

+0

"Code-Snippet Sie gegeben haben, ist kein Block Erklärung" - zu wahr! Danke, ich könnte das bearbeiten! – chm

-1

Nach Ry's Objective C Tutorial:

Blöcke verwenden alle die gleiche Mechanik wie normale Funktionen. Sie können eine Blockvariable genau so deklarieren, wie Sie eine Funktion deklarieren würden.

NSInteger (^BlocksAddition)(NSInteger x,NSInteger y)=^NSInteger(NSInteger x, NSInteger y){ 

    return x+y; 
}; 

NSUInteger result=BlocksAddition(4,5); 
NSLog(@"Addition Result:%d",result); 
+0

Wenn Sie Text von der Arbeit eines anderen kopieren, müssen Sie angeben, woher der Text stammt und mit der ursprünglichen Quelle verknüpfen, und Sie müssen auch die Wörter *, die nicht Ihre eigenen sind, richtig zitieren. Andernfalls begehen Sie Plagiate **. Weitere Informationen darüber, wie Sie in Ihren Antworten auf die Arbeit anderer Personen * Bezug nehmen, finden Sie unter [Wie Sie auf Materialien verweisen, die von anderen geschrieben wurden] (http://stackoverflow.com/help/referencing). –