2012-10-15 18 views
8

że mamy ten blok:Objective-C Parametry bloku

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

Mój obecny zrozumienie tego jest: pierwszy int jest zwracany typ, (^aBlock)(BOOL) podaje nazwę metody i rodzaj jego parametr, i = ^(BOOL param) to nazwa parametru wewnątrz bloku ... plus typ parametru ponownie?

Dlaczego składnia jest taka, że ​​musimy dwukrotnie podać typ parametru? Czy te dwa typy mogłyby być inne?

Odpowiedz

11

To nie jest całkiem „wystawianie parametr wpisać dwa razy” , w pierwszym przypadku deklarujesz typ zmiennej blokowej, aw drugim przypadku definiujesz literę blokową z literą bloku. Następnie przypisujesz literał do wartości zmiennej. Można nawet zrobić coś takiego, co jest równoważne i lepiej ilustruje fakt, że są to naprawdę dwa całkowicie niezależne deklaracje, mimo że wiąże się ze przypisać oświadczenie:

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

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

Fakt, że są one od siebie niezależne środki Prawdopodobnie nie jest nawet poprawna próba dostarczenia jakiegoś przeniesienia lub dziedziczenia wpisywania informacji z lewej strony wyrażenia po prawej stronie. I tak, typy mogą być różne - rozważ ten kod kompilując i wykonując dobrze:

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

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

Mam nadzieję, że to pomoże!

+0

Tak, to niesamowite, dzięki. Żeby wyjaśnić, czy twój drugi fragment kodu jest przykładem przeniesienia informacji na klawiaturze (i dlatego nie jest mile widziany)? – chm

+0

Nie, po prostu ilustruję, że typy między lewą i prawą stroną mogą być różne, a kod będzie kompilowany i uruchamiany. Nie ma zbyt wiele sprawdzania typów blokami innymi niż typy zwracane, o ile mogę to stwierdzić. Nie ma przeniesienia informacji o pisaniu, ponieważ tak naprawdę to nie jest, ja sformułowałem to trochę dziwnie, próbowałem powiedzieć, że nawet jeśli kompilator spróbowałby zrobić coś takiego, to niekoniecznie byłoby to poprawne, niektóre właściwości polimorficzne bloków, które mogłyby zakłócać taką funkcję. –

1

Dlaczego składnia jest taka, że ​​musimy dwukrotnie podać typ parametru?

Blok został zaprojektowany w ten sposób, a więc można zrobić to tak:

int (^aBlock)(BOOL); 

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

To po prostu lubi

- (int)aMethodWithParam:(BOOL)param; 

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

można dwa rodzaje kiedykolwiek będzie inaczej?

Nie, a co więcej, kolejność typów powinny być takie same, czyli:

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

A tu wyraźna postać dla bloku:

Image

2

Kod Podany fragment kodu nie jest deklaracją blokową: jest to deklaracja blokowa i definicja bloku. Po pierwsze, należy zadeklarować identyfikator nazwany aBlock:

int (^aBlock)(BOOL) 

następnie zdefiniować blok:

^(BOOL param) { ... 

Obie te są analizowane i oceniane oddzielnie. Ponieważ przypisujesz jeden do drugiego, kompilator wykonuje test typu, aby upewnić się, że wyrażenie po lewej stronie (twoja deklaracja aBlock) jest tego samego typu, co wyrażenie po prawej stronie (definicja bloku) .

Tak więc, odpowiedź jest taka, że ​​te części należy oceniać oddzielnie. Ponieważ definicja bloku jest kompilowana na własną rękę, musisz uwzględnić typ param, ponieważ w przeciwnym razie kompilator nie będzie wiedział, jaki powinien być typ. (Tak, możesz zrobić wyjątek w tym przypadku i spojrzeć na to zadanie, ale wszędzie indziej w języku C zadeklarujesz identyfikator, najpierw podając typ, więc dlaczego robisz to inaczej?)

Ale - możesz powiedzieć - czy to prawda, dlaczego nie musiałem zdefiniować typu zwrotu (int) po prawej stronie?

Bardzo bystry z twojej strony. Odpowiedź jest taka, że ​​podczas pisania wyrażenia blokowego nie trzeba definiować typu zwracanego, ponieważ kompilator może wywnioskować go z instrukcji return (lub jej braku) wewnątrz bloku.

(Więc dlaczego muszą zawierać typy wrócić z definicji funkcji? Cóż, historia, tak myślę. Definicje języka programowania zostały stworzone przez niedoskonałych ludzi.)

+0

„Fragment kodu dałeś nie jest deklaracja blok” - Too prawda! Dziękuję, mogę to edytować! – chm

-1

Według Ry's Objective C Tutorial:

Bloki korzystać ze wszystkich tych samych mechaników jak normalnych funkcji. Możesz zadeklarować zmienną blokową dokładnie tak, jak zadeklarowałbyś funkcję.

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

Podczas kopiowania tekstu z cudzej pracy, musisz powiedzieć, skąd pochodzi tekst i odsyłać do oryginalnego źródła, a także poprawnie cytować słowa *, które nie są twoimi własnymi *. W przeciwnym razie ** popełniasz plagiat **. Aby uzyskać dodatkowe informacje o tym, jak prawidłowo odwoływać się do * innych osób w pracy * w swoich odpowiedziach, zobacz [Jak korzystać z materiałów napisanych przez innych] (http://stackoverflow.com/help/referencing). –

Powiązane problemy