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.