2013-09-22 13 views
8

Pracując nad nad projektem open source, natknąłem następującej deklaracji funkcji C i realizacja:obiektywne metody C Klasa vs C Funkcje

// FSNData.h 
NSString *stringForMimeType(MimeType type); 

@interface FSNData : NSObject 
// All the expected objective-c property and instance method declarations 
@end 

// FSNData.m 
#import "FSNData.h" 

// where 'type' is an enum 
// this does work as expected 
NSString *stringForMimeType(MimeType type) { 
    switch (type) { 
     case MimeType_image_jpeg: return @"image/jpeg"; 
     case MimeType_image_png: return @"image/png"; 
     default: 
      NSLog(@"ERROR: FSNData: unknown MimeType: %d", type); 

     // do not return "application/octet-stream"; instead, let the recipient guess 
     // http://en.wikipedia.org/wiki/Internet_media_type 
     return nil; 
    } 
} 

@implementation 

// all properties and methods defined in FSData.h implemented as expected 

@end 

Ten przykład może łatwo być ponownie napisany jako metody poziomu klasy z każdy problem. Tak czy inaczej, użycie paragrafu stringFormMimeType() wymaga importowania pliku nagłówkowego FSNData.

Patrząc na the Apple docs, stwierdza tylko:

Ponieważ Objective-C opiera się na fundamencie ANSI C, można swobodnie intermix prosty kod C z kodem Objective-C. Co więcej, twój kod może wywoływać funkcje zdefiniowane w programowych interfejsach innych niż Cocoa, takich jak jako interfejsów biblioteki BSD w/usr/include.

Nie ma wzmianki o tym, kiedy funkcje C powinny preferować metody Celu C.

Jedyną korzyścią jaką widzę w tym momencie jest to, że wywołanie powyższej funkcji, w przeciwieństwie do metody klasy, niektóre wywołania środowiska wykonawczego Objective-C będą pomijane. W typowym przypadku użycia FSNData nie dałoby to zauważalnego zwiększenia wydajności dla użytkownika (prawdopodobnie nawet dla programistów) *.

Jakie są korzyści (inne niż styl kodowania) dla faworyzowania funkcji C w stosunku do metody klasy?

* FSNData jest używana jako część biblioteki FSNetworking, więc wątpię, że w trakcie cyklu życia każdej aplikacji wykonano by tysiące operacji sieciowych.

+0

Styl, struktura programu (wyraźnie wiążąca metodę z klasą) i odrobina (bardzo słaba) kontroli dostępu to wszystko, co mogę wymyślić. (Ale widzę, że @ipmcc wspomina o dziedziczeniu i jest tam również kilka rzeczy.) –

+0

Preferuję metodę klasy, ponieważ metody Objective-C oferują nazwany parametr, którego funkcje C nie są – onmyway133

+0

@ onmyway133 Starałem się trzymać z daleka z osobistych preferencji (tj. ** innych niż styl kodowania **) i szukania przyczyn technicznych. –

Odpowiedz

7

W skrócie, C (lub C++) implementacje są bardzo przydatne:

  • abstrakcji
  • wielokrotnego wykorzystania
  • Dokonując programy średnim i dużą skalę
  • W wykonaniu krytyczne ścieżki
  • W przypadku implementacji "Wnętrznych"

Jakie są korzyści (inne niż styl kodowania) dla faworyzowania funkcji C w stosunku do metody klasy?

  • Wiadomości objC wprowadzają pośrednie wywołania funkcji.Są to firewalle dla optymalizatorów.
  • Funkcje C mogą z łatwością ograniczyć dostęp, natomiast "prywatne" implementacje ObjC mogą być wyszukiwane przy użyciu środowiska wykonawczego ObjC lub przypadkowo zastąpione.
  • C funkcje mogą zostać usunięte z pliku wykonywalnego, jeśli nie są do niego odwoływane, lub mogą być prywatne. Jeśli napiszesz kod wielokrotnego użytku (i powinieneś), może to mieć ogromny wpływ na twoje rozmiary binarne i czasy ładowania - funkcje C, które nie są przywoływane/używane, mogą zostać usunięte, ale typy i metody ObjC zostaną zachowane (w tym wszystkie one odniesienie). Z tego powodu rozmiar binarny twojej aplikacji może znacznie wzrosnąć, gdy używasz tylko niewielkiej części statycznej biblioteki ObjC - każda klasa obiektu w bibliotece jest zachowywana. Jeśli ta biblioteka to C lub C++, możesz uzyskać bardzo mały wzrost, ponieważ potrzebujesz tylko tego, do czego się odwołujesz. To, co jest lub nie jest odniesione, łatwiej jest udowodnić w C i C++.
  • Funkcje C można wstawiać podczas kompilacji lub podczas fazy Link Time Optimization.
  • Kompilator i optymalizatory są w stanie wykonać wiele optymalizacji za pomocą funkcji C (np. Optymalizacji między proceduralnych), ale bardzo niewiele z metodami ObjC, ponieważ są one zawsze pośrednie.
  • Aby uniknąć wysyłania wiadomości ObjC (jak wspomniano wcześniej)
  • Potencjał do dodatkowych operacji liczenia odwołań i autoreakcji puli podczas interakcji z obiektami ObjC.

Oczywiście nie zawsze będzie ci szkodzić płacenie za rzeczy, których nie potrzebujesz lub nie używasz - i pamiętaj, że metody klasy ObjC mają również pewne zalety w porównaniu z funkcjami języka C. Zatem spójrz na implementacje C lub C++ jako inne narzędzie w twoim przyborniku. Uważam je za bardzo użyteczne, ponieważ zwiększają się złożoność i rozmiary projektów, i można je wykorzystać do szybszego tworzenia programów. Po prostu rób to, czego najmniej żałujesz w 2015 roku;)

+0

Myślę, że odpowiedź @ipmcc ma również cenne informacje. Czy możesz uzyskać link do tego, jak i kiedy funkcje są usuwane? –

+1

@MikeD 'man strip' będzie wstępem. to, używane w połączeniu z optymalizacją i prawidłową eliminacją martwego kodu (lub nieosiągalnego kodu) na różnych etapach (na przykład kompilacja, łączenie) pozwalają narzędziom zidentyfikować to, co jest, a czego nie ma odniesienia, lub nie jest osiągalne przez program. jest to użyteczne dla C i C++, ale nie ma zastosowania do symboli ObjC (i do nich odwołują się), ponieważ masz możliwość łatwego odniesienia się do nich dynamicznie za pośrednictwem środowiska wykonawczego (np. 'NSClassFromString',' NSSelectorFromString'), więc wszystkie są zachowywane przez domyślnie, ponieważ Xcode dodaje niezbędne flagi w Twoim imieniu. (cd) – justin

+1

Funkcja @MikeD a C jest "referencyjna", jeśli jest wywoływana zewnętrznie (może być usunięta, jeśli jest wstawiona w każdym przypadku) lub jeśli odwołujesz się do niej po adresie (np. przekazuj ją jako wskaźnik funkcji). jeśli toolchain zda sobie sprawę, że wywołujesz go tylko z nieosiągalnego kodu, to może on również zostać wyeliminowany. zamierzam zmienić to nieco. – justin

8

Już poruszyłeś marginalną różnicę wydajności unikania połączenia objc_msgSend. Metody klasy Objective-C również podlegają nadrzędności w podklasach, więc implementacja metody w C uniemożliwi jej nadpisanie w podklasie. W związku z tym, z powodu tego dziedziczenia/polimorfizmu środowiska wykonawczego, metoda Objective-C nigdy nie może być inline, podczas gdy funkcja C może być potencjalnie zainicjowana przez kompilator w celu zwiększenia wydajności.

Jeśli chodzi o unikanie objc_msgSend, pewien mądry człowiek powiedział mi kiedyś: "Jeśli obciążenie związane z objc_msgSend jest zbyt duże dla ciebie, Cel-C jest prawdopodobnie niewłaściwym narzędziem do tej pracy."

+0

Dobra rada w dziedziczeniu. –