Rozszerzenie klasy a kategoria klas


82

Rozszerzenia klas @interface Class () są o wiele bardziej wydajne i mogą wprowadzać zmienne do klasy. Kategorie @interface Class (Category)nie mogą.

Jakie są inne różnice i kiedy należy używać kategorii zamiast rozszerzenia klasy?


kategorie są rzeczywistym kodem. w ten sposób dodajesz funkcje do zajęć. rozszerzenia są (w bardzo ogólnym ujęciu) bardziej tylko cukrem syntaktycznym, sygnalizującym pewne pomysły dotyczące prywatności itp. innym programistom. rozszerzenia nie zawierają kodu i nie są kodem.
— Fattie

Aby zapoznać się z rozszerzeniami używanymi w Swift, zobacz to pytanie: stackoverflow.com/questions/24142829/ ...
— Suragch

Odpowiedzi:


91

Główna różnica polega na tym, że z rozszerzeniem kompilator będzie oczekiwał, że zaimplementujesz metody w obrębie @implementationpliku main , podczas gdy w przypadku kategorii masz oddzielny @implementationblok. Więc powinieneś używać tylko rozszerzenia na górze głównego .mpliku (jedyne miejsce, w którym powinieneś się przejmować ivars, nawiasem mówiąc) - ma to być po prostu rozszerzenie .


41
Rozszerzenie jest najlepsze dla prywatnych metod, które chcesz zadeklarować w swoim .mpliku. Używam go do tego cały czas. Kategorie są bardziej przydatne, gdy chcesz pogrupować swoje metody w różne sekcje - kategorie :) - lub gdy chcesz dodać kod do istniejących klas, których nie utworzyłeś.
— jtbandes

1
Możesz również dodać dodatkowe miejsce do przechowywania rozszerzeń klas za pomocą właściwości.
— Paul.s

23
Rozszerzenia klas zostały również specjalnie zaprojektowane, aby umożliwić udostępnianie właściwości publicznie readonlyi prywatnie readwrite. Nie można tego zrobić z kategoriami (świadomy wybór projektu).
— bbum

Dlaczego Google używa kategorii do implementacji metod prywatnych zamiast rozszerzenia? np. code.google.com/p/gdata-objectivec-client/source/browse/trunk/…
— Ryan

rozszerzenia wymagają implementacji wszystkich metod w bloku @implementation, zapewnia również rozszerzenie dla zmiennych. Ale w zasadzie staramy się umieścić niektóre z prywatnych metod zamiast używać prywatnych zmiennych, więc w tym przypadku preferujemy kategorię zamiast rozszerzenia
— Ankit Thakur

29

Rozszerzenie klasy ma pewne podobieństwo do kategorii, ale można je dodać tylko do klasy, dla której masz kod źródłowy w czasie kompilacji (klasa jest kompilowana w tym samym czasie co rozszerzenie klasy). Metody zadeklarowane przez rozszerzenie klasy są zaimplementowane w bloku @implementation dla oryginalnej klasy, więc nie można na przykład zadeklarować rozszerzenia klasy w klasie struktury, takiej jak klasa Cocoa lub Cocoa Touch, taka jak NSString.

Składnia deklarowania rozszerzenia klasy jest podobna do składni kategorii i wygląda następująco:

@interface ClassName ()
@end

Ponieważ w nawiasach nie podano nazwy, rozszerzenia klas są często określane jako kategorie anonimowe.

W przeciwieństwie do zwykłych kategorii rozszerzenie klasy może dodawać własne właściwości i zmienne instancji do klasy. Jeśli deklarujesz właściwość w rozszerzeniu klasy, na przykład:

@interface XYZAnimal () {
    id _someCustomInstanceVariable;
}
...
@end

IMHO, najlepiej jest myśleć o rozszerzeniach klas jako o prywatnym interfejsie do klasy. Główny interfejs (w Twoim pliku .h) działa jako interfejs publiczny, który definiuje kontrakt behawioralny klasy z innymi klasami.

Użyj rozszerzeń klas, aby ukryć informacje prywatne

Rozszerzenia klas są często używane do rozszerzania interfejsu publicznego o dodatkowe metody lub właściwości prywatne do użycia w implementacji samej klasy. Na przykład często definiuje się właściwość jako tylko do odczytu w interfejsie, ale jako readwrite w rozszerzeniu klasy zadeklarowanym powyżej implementacji, aby wewnętrzne metody klasy mogły bezpośrednio zmieniać wartość właściwości.

Na przykład klasa XYZPerson może dodać właściwość o nazwie uniqueIdentifier, przeznaczoną do śledzenia informacji, takich jak numer ubezpieczenia społecznego w USA.

Zwykle wymaga to dużej ilości dokumentów, aby przypisać niepowtarzalny identyfikator do osoby w świecie rzeczywistym, więc interfejs klasy XYZPerson może zadeklarować tę właściwość jako tylko do odczytu i zapewnić metodę, która żąda przypisania identyfikatora, na przykład:

@interface XYZPerson : NSObject
    ...
    @property (readonly) NSString *uniqueIdentifier;
    - (void)assignUniqueIdentifier;
@end

Aby klasa XYZPerson mogła wewnętrznie zmieniać właściwość, sensowne jest ponowne zadeklarowanie właściwości w rozszerzeniu klasy, które jest zdefiniowane na początku pliku implementacji dla klasy:

@property (readwrite) NSString *uniqueIdentifier;

Uwaga: atrybut readwrite jest opcjonalny, ponieważ jest domyślny. Możesz go użyć podczas ponownego zgłaszania nieruchomości, aby zwiększyć przejrzystość.


7

Kategorie to funkcja języka Objective-C, która umożliwia dodawanie nowych metod do istniejącej klasy. Rozszerzenia to szczególny przypadek kategorii, które pozwalają zdefiniować metody, które muszą być implementowane w głównym bloku implementacji.

Prywatne deklaracje mogą znajdować się w rozszerzeniach klas, które są głównie niektórymi właściwościami, ponieważ nie musimy deklarować metody przed jej wywołaniem.


„należy to zadeklarować w głównym bloku implementacji”. -> to musi być "zaimplementowane" w głównym bloku implementacji
— Fawkes

Dzięki, zmodyfikowałem to.
— Julie Yu

0

rozszerzenie ios podobne do C #, abstrakcyjnej klasy java lub
kategorii ios podobne do rozszerzenia klasy C #


Java nie obsługuje metod rozszerzających
— someUser

przepraszam! Literówka kopiuj-wklej. Kategoria ios podobna do rozszerzenia klasy C #.
— Add080bbA

Czy możesz dodać przykład o?
— Pedro Trujillo
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.