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?

AWF4vk
źródło
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 .

jtbandes
źródło
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ść.

nieznany z nazwiska
źródło
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.

Julie Yu
źródło
„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 #

Add080bbA
źródło
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