2010-01-16 13 views
8

Okay, mam wrażenie, że jesteście w stanie szybko wskazać, dlaczego jestem tak zdezorientowany, ale mam pytanie, dlaczego poniższe NIE powoduje kompilatora błąd lub ostrzeżenie:Oszacowanie typu celu C

NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ]; 

selectedObject jest NSObject i name dzieje się nazwa @property typu int.

Co mnie wprawia w zakłopotanie jest dlaczego kompilator jest całkowicie skłonny przyjąć, że wynik powrót [ self.selectedObject valueForKey:name ] jest typu NSNumber * (bez rzutowania go) w celu łańcucha wiadomość z wezwaniem do integerValue.

Oczywiście KVC owija się non-object „number” typy na NSNumber, ale nie ma mowy o kompilator wiedział, że -valueForKey: zwróci NSNumber * w tym konkretnym przypadku.

Dlaczego to nie powoduje ostrzeżenia kompilatora wzdłuż linii "id może nie odpowiadać na"""?

Odpowiedz

10

Mam nadzieję, że mam to dobrze: to dlatego, że id jest "specjalny". Obiekty typu id można wysyłać dowolną wiadomość, nie ma sprawdzania wykonanego przez kompilator i wszystko zostanie sprawdzone w środowisku wykonawczym. Innymi słowy, typ id jest częścią "dynamicznego pisania" w Objective-C, podczas gdy wszystkie pozostałe typy (takie jak NSObject) są częścią "statycznego pisania".

W ten sposób możesz wybrać miejsce, w którym chcesz pisać statycznie i gdzie chcesz pisać dynamicznie. Jest to całkowicie legalne zrobić coś takiego:

id str1 = @"Hello"; 
id str2 = [str1 stringByAppendingString:@", world"]; 

Ale zwykle piszesz sznurki „ciasno”, jak NSString s, ponieważ można uzyskać wygodę kompilacji statycznej sprawdzenia typu, a uciekać jedynie do dynamicznego typowania gdzie statyczna przeszkoda stanąłaby na przeszkodzie, jak w sytuacji valueForKey.

+0

Dzięki! Miałem wrażenie, że ma to związek z "id" będącym uprzywilejowanym typem w Objective-C. :) Moją tendencją jest ZAWSZE ciasno pisać rzeczy za każdym razem, gdy to możliwe, więc myślę, że nigdy nie spotkałem tego pozornie dziwnego zachowania. Zgadnij, że czyni "id" zarówno potężnym, jak i niebezpiecznym. Zastanawiam się, czy lepiej jest typecast dać kompilatorowi jakiś kontekst, gdy mamy do czynienia z 'id', lub jeśli jest to całkowicie w porządku, aby zostawić to, jeśli jesteś przekonany o tym, co stanie się' id' (tak jak w moim przykładzie) . – LucasTizma

+0

Reguła kciuka to: "Pisanie statyczne tam, gdzie to możliwe, dynamiczne pisanie w razie potrzeby." (Możesz uzyskać od Google dodatkowe informacje.) W tym przypadku nie będę pisał kodu, utrudniłoby to czytanie tego wyrażenia. Czasami trzeba wpisać typ, aby pomóc kompilatorowi wybrać właściwą metodę - patrz http://stackoverflow.com/questions/1113270. – zoul

+0

Dzięki za link. Napotkałem kilka nieprzyjemnych błędów w wyniku nazewnictwa metod, które mają "konflikt" z istniejącymi nazwami metod SDK. Myślałem, że kompilator szaleje na mnie. :) Tak, jestem zwolenniczką filozofii "Pisanie statyczne, gdzie to możliwe, dynamiczne pisanie w razie potrzeby". Teraz, jeśli tylko Objective-C doda obsługę typowych kolekcji ... Wydaje się, że częściej niż nie wiem, co moje kolekcje będą przechowywać. – LucasTizma