equivalent à une méthode virtuelle pure ?

foo4web

Membre enregistré
5 Avril 2011
5
0
Bonjour amis codeurs,

Je suis bloqué: je sais très bien que les méthodes virtuelles pures (virtual abstract) n'existent pas en objC. Mais comment faire ? Je veux appeler dans une classe parente une méthode qui est définie dans une classe enfant. C'est tout à fait courant en C#, Java, Delphi... Il existe donc un moyen de contourner ce manque ?

Exemple :

Bloc de code:
@interface ClassA: NSObject
 
- (void) DisplayHello;
 
@end
 
@implementation ClassA
 
- (void) DisplayHello {
NSLog("Hello %@", [self UserName]);             <=== userName est défini dans classe B
}
 
@end
 
@interface ClassB:ClassA
- (NSString*) UserName;
@end
 
@implementation ClassB
 
(NSString*) UserName {
return @"Colt Sivers";
}
 
@end
Dans un autre langage, j'aurais déclaré UserName dans classe A en tant que méthode virtual abstract.

Une idée???
 
Oui, j'ai jeté un oeil sur les protocoles et effectivement, c'est une interface. Cela me permet "d'obliger" une classe à implémenter un certains nombres de méthode, mais ça ne résouds pas mon soucis.

En fait, pour en avoir discuté ailleurs, je pense que la solution est très simple.
Il faut que je déclare ma méthode dans la classe A et dans la classe B, qui override celle de la A.

Pas testé encore...
En parallèle, l'utilisation des protocoles peut rendre la chose plus propre.
 
Ah, OK, je comprends mieux ton problème.

La classe A ne peut pas appeler [self userName] à moins de définir la méthode -userName; eh bien tu peux donner une implémentation par défaut:

Bloc de code:
- (NSString *) userName
{
	return nil;
}

Mais typiquement, on ne fait pas ça en ObjC (ni en Java). Je sais qu'en C++ en adore l'héritage, mais l'héritage est plein de défauts, à commencer par la nécessité de bien connaître la classe qu'on surcharge.

Le mieux est de remplacer l'héritage par une association. Ainsi, la ClasseA possède un pointeur vers une instance de Classe B qui répond au protocole UserNameProtocol:

ClassA.h :
Bloc de code:
@protocol UserNameProtocol

- (NSString *) userName;

@end

@interface ClassA : NSObject
{
	id <UserNameProtocol> associatedObject;
}

@property (nonatomic, retain) id <UserNameProtocol> associatedObject;

- (void) displayHello;

@end

ClassA.m:
Bloc de code:
@implementation ClassA

@synthesize associatedObject;

- (void) displayHello
{
	NSLog(@"Hello %@", [associatedObject userName]);
}

ClassB.h:
Bloc de code:
#import "ClassA.h"	// Pour connaître UserNameProtocol

@interface ClassB: NSObject <UserNameProtocol>
{
	
}

ClassB.m:
Bloc de code:
@implementation ClassB

- (NSString *) userName
{
	return @"Colt Sivers";	
}

C'est plus complexe dans la syntaxe, mais plus flexible à moyen terme.