web-dev-qa-db-fra.com

Implémenter une méthode virtuelle pure en Objective-C

Je veux aller là-bas. Sérieusement, comment implémenter une méthode virtuelle pure à la manière "Apple"? Utilisez-vous un protocole avec votre classe de base et lancez-vous des exceptions sur ces méthodes?

41
Chris

Lorsque vous programmez en Objective-C, vous devez purger votre esprit de choses telles que les méthodes virtuelles. Vous n'appelez pas de méthodes sur des objets Objective-C, vous leur envoyez des messages. Les objets répondent aux messages ou non, mais en raison de la liaison dynamique, vous ne pouvez pas le dire avant l'exécution.

Ainsi, vous pouvez déclarer une méthode sur un objet de base et ne pas fournir d'implémentation, pas de problème (sauf pour l'avertissement du compilateur), mais vous ne pouvez pas avoir le drapeau du compilateur lorsque vous instanciez directement un objet avec de telles méthodes et cela a gagné ne lancez pas d'erreur au moment de l'exécution, sauf si vous envoyez réellement ce message à l'objet.

La meilleure façon de créer des classes de base "virtuelles" (à mon avis) est de déclarer la méthode et de lui donner une implémentation de stub qui lève une exception appropriée.

55
JeremyP

En Objective-C, il n'y a pas de support virtuel pur comme en C++.

Une simulation serait que vous déclariez une méthode dans votre interface mais ne l'implémentiez pas dans votre fichier .m. Bien sûr, vous recevrez des avertissements du compilateur mais IIRC vous pouvez les désactiver. Mais vous n'obtiendrez pas d'avertissements/erreurs si vous ne les écrasez pas dans la sous-classe, que vous obtenez en C++ (IIRC).

Une alternative serait de les implémenter avec juste un corps NSAssert(NO, @"Subclasses need to overwrite this method");. Pourtant, vous ne l'attraperez qu'au moment de l'exécution, pas à la compilation.

33
DarkDust

Selon ce que vous faites, le modèle de délégué peut être plus approprié qu'une sous-classe, où le délégué est défini comme id<YourDelegateProtocol>. Le compilateur générera un avertissement si les méthodes requises dans le protocole délégué ne sont pas implémentées.

Le sous-classement est généralement évité en Objective-C car les objets ne peuvent pas hériter de plusieurs superclasses mais ils peuvent implémenter plusieurs protocoles.

7
Matt Stevens

Vous devez utiliser le:

- (void)doesNotRecognizeSelector:(SEL)aSelector method. 

Comme indiqué par Apple, ici: https://developer.Apple.com/library/mac/#documentation/cocoa/reference/Foundation/Classes/NSObject_Class/Reference/Reference.html

6
Antony Clements

Vous avez quelques options, mais vous êtes sur la bonne voie.

ObjC ne prend pas en charge cela directement, forcer les sous-classes à implémenter un protocole est le meilleur moyen de le vérifier lors de la compilation.

Implémenter "secrètement" la méthode dans la classe de base et affirmer est ce que je fais pour confirmer que le sous-classe a correctement sous-classé lors de l'exécution. Certaines personnes ont des sentiments mitigés à propos des affirmations ou doivent les laisser actives, ce n'est donc pas toujours une bonne solution.

Vous pouvez également forcer les sous-classes à utiliser un constructeur de classe et une séquence d'initialisation spécifiques, puis vérifier qu'elles ont implémenté tout ce qui est nécessaire avant de renvoyer une instance, au cas où les avertissements du compilateur ne la coupent pas.

Mais il manque à ObjC certaines fonctionnalités lang qui permettent aux clients de se tirer une balle dans le pied, ou de contourner ce qu'ils souhaitent ... vous ne devriez pas trop vous attarder à l'appliquer.

remarque: les exceptions sont très rares (et un peu dangereuses également) dans ObjC.

2
justin

Une méthode virtuelle est une méthode dont le comportement peut être remplacé dans une classe héritière par une fonction avec la même signature (c'est-à-dire le même nom avec le même nombre de paramètres et le même type de paramètres).

Exemple: -

@implementation BaseClass

-(void)viewDidLoad
{
 [self virtualMethod:123];
}

-(void)virtualMethod:(int)param
{
 //implement this method in subclass
}

@end

//////////////////////////////////////////////////// //

@interface ChildClass:BaseClass
@end

@implementation ChildClass

-(void)virtualMethod:(int)param
{
 NSLog(@"There is no keyword "Virtual" in Objective C.");
}
@end

Sortie: -

"Il n'y a pas de mot-clé" Virtuel "dans l'Objectif C."

0
Deepak