web-dev-qa-db-fra.com

Extension de classe Objective-C

En tant que programmeur objective-c relativement nouveau (avec une expérience de 4 ans Java), il semble que j'ai du mal à comprendre quand utiliser les extensions de classe. D'après ce que j'ai compris (et s'il vous plaît, corrigez moi si je me trompe), la principale différence entre les catégories et les extensions est que l'extension s'attend à ce que vous implémentiez les méthodes à l'intérieur de votre implémentation principale, alors qu'avec une catégorie, cela peut être dans une autre implémentation. Il semble également que les gens utilisent des extensions principalement pour les méthodes privées.

Voici ma première question. Quelle est la différence entre utiliser une extension de classe pour déclarer une méthode privée et ne pas la déclarer du tout (elle semble se compiler en cours d'exécution dans les deux cas)? (exemple 1 vs 2)

Exemple 1

@interface Class()
-(void) bar;
@end

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end

Exemple 2

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end

Deuxième question: quelle est la différence entre déclarer ivars à l'intérieur de l'extension et le déclarer directement à l'intérieur de l'implémentation? (Exemple 3 vs 4)

Exemple 3

@interface Class() {
    NSArray *mySortedArray;
}
@end

@implementation Class
@end

Exemple 4

@implementation Class
NSArray *mySortedArray;
@end

J'ai une dernière question sur les conventions de codage: quand dois-je mettre un trait de soulignement (_) devant le nom d'une variable?

Je vous remercie

34

Méthodes dans les extensions de classe

Auparavant, vous n'aviez pas besoin de déclarer vos méthodes privées. Jusqu'à récemment, vous deviez déclarer vos méthodes privées quelque part, et la plupart des gens choisissaient une extension de classe pour le faire. À partir de Xcode 4.4 (je crois), le compilateur est assez intelligent pour déterminer quelles méthodes sont censées être privées dans cette implémentation, supprimant la nécessité de les déclarer ailleurs.

Variables dans les extensions de classe

Comme pour les exemples 3 et 4, soyez prudent. Dans une extension de classe, la variable est une variable d'instance de cette classe (exemple 3). L'exemple 4 déclare une variable globale (car elle suit la sémantique des variables globales de C). Restez avec l'exemple 3 pour vos variables d'instance privées.

Conventions de codage

Quant à la convention de codage, c'est au développeur/à l'équipe de décider d'utiliser ou non un trait de soulignement. Notre équipe utilise m_ pour les variables d'instance privées. Apple dans leur documentation suggérée utilisant des traits de soulignement (c'est le style de dénomination des variables d'instance sous-jacentes pour les propriétés synthétisées). L'important est, pour être cohérent tout au long de votre code.

27
WDUK

la principale différence entre les catégories et les extensions est que l'extension s'attend à ce que vous implémentiez les méthodes à l'intérieur de votre implémentation principale, alors qu'avec une catégorie, elle peut être dans une autre implémentation. Il semble également que les utilisateurs utilisent principalement des extensions pour des méthodes privées.

Correct.

Quelle est la différence entre utiliser une extension de classe pour déclarer une méthode privée et ne pas la déclarer du tout (elle semble se compiler en cours d'exécution dans les deux cas)?

Peut-être juste un avertissement du compilateur concernant le sélecteur non déclaré. (Bien sûr, cela fonctionne bien - la méthode est implémentée et existe.) Notez également qu'une déclaration (une signature de fonction correcte et connue) est nécessaire pour le compilateur afin d'émettre du code binaire correct conforme à ABI. L'hypothèse qu'il fait à propos des méthodes non déclarées (à savoir qu'elles renvoient id et acceptent des arguments variadiques) peut ne pas être correcte - appeler une fonction via un pointeur d'un type incompatible est un comportement non défini.

Quelle est la différence entre déclarer ivars à l'intérieur de l'extension et le déclarer directement à l'intérieur de l'implémentation?

Dans le 4ème exemple, c'est une variable C globale, c'est pas une variable d'instance de votre classe.

quand dois-je mettre un trait de soulignement (_) devant le nom d'une variable?

Chaque fois que vous le souhaitez, faites-le régulièrement. Toujours ou jamais.

8
user529758

Dans la question 1, exemple 2: Les méthodes foo et bar implémentées dans Class sont visibles par les instances de Class. Si foo et bar ne sont pas déclarés dans un fichier d'en-tête séparé ET que le fichier d'implémentation n'est pas rendu disponible, une autre classe ignorera l'existence de foo et bar. foo et bar sont des méthodes privées; les instances de Class répondront toujours aux messages foo et bar. En outre, Xcode signalera un avertissement si une autre classe qui essaie d'envoyer un message à foo et bar car Xcode ne peut pas vérifier (sans la déclaration dans le fichier d'en-tête) que foo et bar existent. En revanche, l'exemple 1 de déclaration de barre permet à toute autre classe d'envoyer une barre de message aux instances de Class. Xcode ne signalera pas non plus d'erreur pour tout message à barrer si @interface Class se trouve dans un fichier d'en-tête qui est #import par l'autre classe.

Dans la question 2, exemple 4: mySortedArray est un tableau local immuable déclaré avec une portée locale dans Class. Le mySortedArray dans l'exemple 3 est une variable d'instance de type NSArray accessible à une autre classe qui crée une instance de Class.

2
Global nomad

Hope subclass-category-and-extensions peut vous être utile.

1
Smith
0
Darshan