Różnica między definicją @interface w plikach .h i .m

81

Zwykle używamy

@interface interface_name : parent_class <delegates>
{
......
}
@end 

w pliku .h iw pliku .m syntezujemy właściwości zmiennych zadeklarowanych w pliku .h.

Ale w pewnym kodzie ta metoda @interface ..... @ end jest również przechowywana w pliku .m. Co to znaczy? Jaka jest różnica między nimi?

Podaj także kilka słów o metodach pobierających i ustawiających dla pliku interfejsu zdefiniowanego w pliku .m ...

Z góry dziękuję

bgolson
źródło

Odpowiedzi:

63

Często umieszcza się dodatkowy, @interfacektóry definiuje kategorię zawierającą metody prywatne:

Person.h:

@interface Person
{
    NSString *_name;
}

@property(readwrite, copy) NSString *name;
-(NSString*)makeSmallTalkWith:(Person*)person;
@end

Osoba. M:

@interface Person () //Not specifying a name for the category makes compiler checks that these methods are implemented.

-(void)startThinkOfWhatToHaveForDinner;
@end


@implementation Person

@synthesize name = _name;

-(NSString*)makeSmallTalkWith:(Person*)person
{
    [self startThinkOfWhatToHaveForDinner];
    return @"How's your day?";
}


-(void)startThinkOfWhatToHaveForDinner
{

}

@end

„Kategoria prywatna” (właściwa nazwa kategorii bezimiennej to nie „kategoria prywatna”, tylko „rozszerzenie klasy”) .m zapobiega wyświetlaniu przez kompilatorowi ostrzeżenia, że ​​metody są zdefiniowane. Jednakże, ponieważ @interfacew pliku .m jest kategorią, nie można w niej zdefiniować ivars.

Aktualizacja 6 sierpnia '12: Cel-C ewoluował od czasu napisania tej odpowiedzi:

  • ivars można zadeklarować w rozszerzeniu klasy (i zawsze może być - odpowiedź była niepoprawna)
  • @synthesize Nie jest wymagane
  • ivarsmożna teraz zadeklarować w nawiasach na górze @implementation:

to jest,

@implementation { 
     id _ivarInImplmentation;
}
//methods
@end
Benedict Cohen
źródło
4
Mała uwaga, tak naprawdę nie umieszczaj niczego w nawiasach, kiedy deklarujesz prywatny interfejs. W przeciwnym razie po prostu utworzy kategorię, a tego nie chcesz. @interface Person ()wystarczy.
Itai Ferber
Dzięki itaiferber, nie zauważyłem tego. Zaktualizowałem odpowiedź.
Benedict Cohen
4
Jeśli ludzie chcą dowiedzieć się więcej o kategoriach ... ta strona była dla mnie bardzo przydatna.
Tim,
1
Jeśli nie ma nic w nawiasach, to faktycznie nazywa się to class extensionnie acategory
Paul.
5
@ giant91 Ta odpowiedź jest dość stara, a kompilator znacznie się poprawił od czasu, gdy został napisany. Kompilator nie potrzebuje już deklaracji metody, jeśli treść metody jest „widoczna”. Oznacza to, że kontynuacje klas ( @interface className ()) będą teraz generalnie zawierać tylko prywatne pliki @propertys.
Benedict Cohen
10

Koncepcja jest taka, że ​​możesz uczynić swój projekt znacznie czystszym, jeśli ograniczysz .h do publicznych interfejsów swojej klasy, a następnie umieścisz prywatne szczegóły implementacji w tym rozszerzeniu klasy.

kiedy deklarujesz zmienne metody lub właściwości w pliku ABC.h, oznacza to, że te zmienne właściwości i metody mogą być dostępne poza klasą

@interface Jain:NSObject
{
    NSString *_name;
}

@property(readwrite, copy) NSString *name;
-(NSString*)makeSmallTalkWith:(Person*)jain;
@end

@Interface umożliwia deklarowanie prywatnych wartości ivar, właściwości i metod. Więc do niczego, co tutaj zadeklarujesz, nie można uzyskać spoza tej klasy. Ogólnie rzecz biorąc, chcesz zadeklarować wszystkie wartości ivars, właściwości i metody domyślnie jako prywatne

Po prostu powiedz, kiedy deklarujesz zmienne metody lub właściwości w pliku ABC.m, oznacza to, że te zmienne właściwości i metody nie mogą być dostępne poza klasą

@interface Jain()
    {
        NSString *_name;
    }

    @property(readwrite, copy) NSString *name;
    -(NSString*)makeSmallTalkWith:(Person*)jain;
    @end
Shubham JAin
źródło
0

możesz nawet utworzyć inne klasy w pliku .m, na przykład inne małe klasy, które dziedziczą po klasie zadeklarowanej w pliku .h, ale zachowują się nieco inaczej. Możesz użyć tego we wzorcu fabrycznym

Enrico Cupellini
źródło