2010-01-11 6 views
1

J'ai la classe X, une classe abstraite, et les classes A et B qui en héritent. Les classes A et B ont chacune leur propre fonction 'return_something'. J'ai une autre méthode ailleurs qui appelle 'return_something' sur une série d'objets, tous de type X. 'return_something' renvoie quelque chose de différent selon qu'il s'agit d'un A ou d'un B, donc je peux juste appeler id * result = [x return_something).Héritage dans Objective-c et Fonctions

Je peux concevoir tout cela bien, mais quand je viens de l'implémenter je ne sais pas quoi mettre dans la classe X, le parent. Il doit avoir une fonction 'return_something' pour pouvoir être appelé, mais la fonction elle-même est définie dans les classes enfant. Je peux le déclarer dans le parent et les deux enfants, mais Je n'ai rien à retourner de l'implémentation X - l'objet retourné dépend de la redéfinition de l'enfant.

Ce serait bien pour une méthode non-retour, mais comment est-ce que je suis censé utiliser l'héritage et le polymorphisme avec une fonction?

+1

classes abstraites ne sont pas quelque chose qui va bien avec Objective-C. Il y a des clusters de classes comme une sorte de remplacement. –

+0

Les classes n'ont pas de fonctions dans Objective-C. Ce dont vous parlez, ce sont des méthodes. Juste pour être clair. – Chuck

+0

Ouais, j'utilisais juste la fonction parce qu'elle retourne quelque chose. Alors, que feriez-vous pour différencier quelque chose avec et sans type de retour (autre que le vide)? –

Répondre

6

La chose la plus simple à faire est de lancer une exception de la fonction "base". De cette façon, vous saurez s'il est appelé par erreur.

D'autres langages qui fournissent une "abstraction" explicite ne nécessitent pas de corps de méthode pour les méthodes abstraites.

+0

Exactement - la meilleure implémentation que j'ai vue est dans Eiffel, où vous indiquez explicitement que la classe est abstraite et que la routine est différée. Donc vous dites simplement de retourner quelque chose (parce que je dois le faire) et ça pourrait aussi bien être une exception pour que je le sache, n'est-ce pas? Mais que faire si je fais des choses génériques dans la définition de base, et que j'appelle [super return_something] dans l'enfant? La classe de base retournera l'exception et la caution du code de l'enfant immédiatement? –

+0

Si vous attendez que les routines enfants appellent réellement la routine de base, alors ce n'est pas vraiment "abstrait". S'il s'agit d'une routine abstraite, l'implémentation de classe de base ne doit pas être appelée. –

+0

C'est abstrait dans le sens où il ne devrait pas être créé, mais il a des qualités génériques que tous les enfants partagent. Peut-être que je dois revoir mes définitions. Par exemple, je pourrais ne jamais vouloir créer un 'véhicule', seulement une voiture ou un bus, mais chacun a une routine 'drive' avec beaucoup de code similaire qui pourrait être dans la classe de base. Je suppose que pour contourner le problème, je pourrais avoir le code générique dans une nouvelle méthode de la classe de base, que chaque enfant appelle dans le cadre de sa propre implémentation. Semble un peu inélégant cependant. –

5

Utilisez un protocole Objective-C au lieu d'une classe de base abstraite:

@protocol ProtocolX 
-(int)return_something; 
@end 

@interface ClassA : NSObject <ProtocolX> { 
} 
-init; 
-(int)return_something; 
@end 

@interface ClassB : NSObject <ProtocolX> { 
} 
-init; 
-(int)return_something; 
@end 

@implementation ClassA : NSObject <ProtocolX> 
-(int)return_something { return 1; } 
-init { retur [super init]; } 
@end 

@implementation ClassB : NSObject <ProtocolX> 
-(int)return_something { return 3; } 
-init { retur [super init]; } 
@end 

Références de type id<ProtocolX> peuvent ensuite être passés autour et utilisés:

id<ProtocolX> ref = [[ClassA alloc] init]; 
int myIntForA = [ref return_something]; 
[ref release]; 
ref = [[ClassB alloc] init]; 
int myIntForB = [ref return_something]; 
[ref release]; 
+0

Intéressant, merci - Je vais sortir mon livre et lire, pas encore rencontré de protocoles. Cela semble trompeusement simple! –

+0

Fonctionne si la classe de base est complètement "abstraite", par ex. il n'y a pas d'état ou de méthodes par défaut. –

+0

Oui, je vois - Je voudrais avoir du code générique dans la définition de la classe de base, donc je ne suis pas sûr que cela fonctionnera. Peut-être re-concevoir pour l'utiliser cependant. –