2013-03-06 12 views
7

Jeśli mam następujące obiekty:Objective-C: Jak przekazać obiekt jako argument bloku do metody, która oczekuje swojej klasy bazowej?

@interface Simple : NSObject 

@end 

@interface Complex : Simple 

@end 

a inny obiekt takich jak:

@interface Test : NSObject 

+(void) doSomething:(void (^)(Simple*)) obj; 

@end 

wszystko działa jeśli zgłoszę metoda jak:

[Test doSomething:^(Simple * obj) { 

}]; 

Kiedy próbuję zamiast zadzwonić to jak:

[Test doSomething:^(Complex * obj) { 

}]; 

Kompilator mówi, że:

Incompatible block pointer types sending 'void (^)(Complex *__strong)' to parameter of type 'void (^)(Simple *__strong)'

Ponieważ Complex rozciąga Simple, myślałem, że to będzie działać, podobnie jak w Javie.

Czy jest jakiś sposób, aby to osiągnąć?

Odpowiedz

8

Niestety, jest to ograniczenie interfejsu API Blocks. Jeśli chcesz, masz możliwość całkowicie rezygnując bezpieczeństwa typu oraz deklarując bloku jako:

+(void) doSomething:(void (^)(id)) obj; 

który pozwala ustawić klasę argumentów bloku. Ale znowu, to jest całkowicie niebezpieczne, pod względem typu.

+0

Czy to naprawdę niefortunne? 'Test' prosi o referencję do bloku z sygnaturą, która mówi, że blok przyjmuje argument typu' Simple'. Przekazanie jej bloku, który przyjmuje podtyp "Complex", może oznaczać, że 'Test' może wykonać niedozwolone połączenie, wywołując blok z inną podklasą' Simple'. –

+0

Po prostu mówię, że rozsądnie jest nazwać to naruszeniem umowy. Jeśli tak nie jest, kompilator nie wie, czy wywołanie w 'Testie' do wykonania bloku ma parametr prawny. –

+0

@SeamusCampbell Przepraszam, nie przeczytałem dokładnie tego, co napisałeś. Tak, dokładnie. – CodaFi

2

Użyj id zamiast Complex * lub Simple *. Typy bloków są obsługiwane inaczej niż typy parametrów metod (dzięki @CodaFi).

Powiązane problemy