[Résolu] héritage
Bonjour,
J'ai une classe un peu trop chargé donc je veux l'éclater. Pour expliquer, je vais parler d'animaux,de chat et chien ::)
Pour le moment, c'est ma tête qui éclate :crackboom:-
Le Monde.m il hérite de NSObject
Le Animal.h
Le Chat.h
Je ne sais pas si je suis bien claire
Je vous rassure, je ne manipule pas en réalité des chat chien... mais ça me semble plus simple pour expliquer.
J'ai une classe un peu trop chargé donc je veux l'éclater. Pour expliquer, je vais parler d'animaux,de chat et chien ::)
Pour le moment, c'est ma tête qui éclate :crackboom:-
Le Monde.m il hérite de NSObject
<br />@implementation Monde<br />Animal* annimal = [[[Animal alloc] initWithId:idA :nbPatte] autorelease];<br />[listeSection addObject: annimal];<br /><br />//....<br /><br />switch([[listeSection objectAtIndex:loop] idA]){<br /> case 0x00:<br /> if(![(Chien*)[listeSection objectAtIndex:loop] mordre]){<br /> return NO;<br /> }<br /> break;<br /> <br /> case 0x01:<br /> if(![(Chat*)[listeSection objectAtIndex:loop] mordre]){<br /> return NO;<br /> }<br /> break;<br />}<br />@end<br />
Le Animal.h
@interface Animal : NSObject{<br /> <br />} <br />-initWithId:(UI08_)idA :(int) nbPatte;<br />@end
Le Chat.h
#import "Animal.h"<br /><br />@interface Chat : Animal {<br /><br />}<br />-(id)mordre;<br /><br />@end
Je ne sais pas si je suis bien claire

Je vous rassure, je ne manipule pas en réalité des chat chien... mais ça me semble plus simple pour expliquer.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Mon problème c'est que ça ne marche pas.
Peut être en voyant ma structure on me dirait "tu as :fouf): "
Peut on allouer puis initialiser un type Animal.
Puis faire un cast sur Animal en Chat ou Chien et lancer une méthode qui est disponible que dans les classes spécifiques.
La méthode mordre est disponible que dans Chat et Chien, non dans Animal.
Ta classe Animal définit dans son interface des méthodes communes à toutes les sous-classes, sans forcément en faire une implémentation précise.
enum { DOUCEMENT, FORT } MODE_DE_MORSURE;
@interface Animal : NSObject
{
// variables communes
}
-(id) initWithSpeed:(CGFloat) aSpeed;
-(void) mordre:(MODE_DE_MORSURE) aMode;
@end
Chaque sous-classe redéfinit les méthodes dans son implémentation sans avoir besoin de les déclarer dans l'interface
appel : Chat * aCat=[[CHAT alloc] initWithSpeed:25.];
Je ne passe pas dans la méthode mordre de ma classe Chien mais dans la méthode mordre de ma classe animal.
Oui.
En objective-C chaque objet possède un champ isa pointant sur l'objet de classe représentant la classe de l'objet.
Le cast ne change pas ce champ.
Les messages sont envoyés dynamiquement, si l'objet qui le reçoit sait répondre au message il l'effectue comme il sait l'effectuer. C'est logique : on hérite des manies de ses parents si on ne les a pas réinventées soi-même, pas le contraire, mais chaque génération peut réinventer ...
#import <Foundation/Foundation.h>
@interface Animal : NSObject
{
}
-(void) mordre;
@end
@interface Chat : Animal
{
}
@end
@implementation Animal
-(void) mordre { NSLog(@Ouarf);}
@end
@implementation Chat
-(void) mordre { NSLog(@Miaou);}
@end
int main(int argc, char**argv){
NSAutoreleasePool * pool=[[NSAutoreleasePool alloc] init];
Chat * minou=[[[Chat alloc] init] autorelease];
Animal * ours=[[[Animal alloc] init] autorelease];
[minou mordre];
[ours mordre];
[(Chat*) ours mordre];
[(Animal*) minou mordre];
[pool release];
return 0;
}
Et les chats font toujours Miaou, les Ours font toujours Ouarf
% clear;gcc pgm.m -o pgm -framework Foundation
% pgm
2008-04-17 17:17:54.723 pgm[770:10b] Miaou
2008-04-17 17:17:54.724 pgm[770:10b] Ouarf
2008-04-17 17:17:54.725 pgm[770:10b] Ouarf
2008-04-17 17:17:54.726 pgm[770:10b] Miaou
%
Je vais chercher une autre solution, comme par exemple, faire des alloc de chien et chat et pas de animal.
Fais gaffe, le gouvernement vient d'annoncer que les alloc vont baisser, mais bon peut-être pas pour les chiens et les chats .
"It is raining Cats and Dogs"
ou les équivalents :
It's raining cats and dogs / buckets / stair rods / pitchforks / elephants & giraffes ;D
It's a frog strangler,
It's a frog-strangling-gully-washer,
It's a frog-strangling downpour
it's pelting / chucking / pissing / tipping it down
Mais avant, il faut réfléchir à savoir si c'est vraiment judicieux. Ne faut-il pas mieux créer un Chat directement, quitte à le stocker dans une variable Animal ?
Ca me parait plus adapté et mieux respecter le principe d'abstraction, et palier à ton problème : Comme ça tu peux par exemple dans une classe avoir une variable d'instance de ta classe de type générique "Animal*" et ensuite c'est en au moment de l'allocation (donc création de l'objet que tu stockes dans cette variable) que le type est défini
----
Maintenant si tu veux vraiment appeler la méthode "mordre" de la classe "Chat" sur un objet qui n'en n'est pas forcément un à l'origine, il suffit de demander à la classe qui t'intéresse ("Chat" en l'occurence) la méthode appelée quand tu demandes ce @selector sur les objets de classe Chat, puis de l'appeler sur ton autre objet.
Tout ça est décrit ici dans la doc Apple
Ca devrait donner un code du genre (non testé) :
@implementation Chat
-(void) mordre { NSLog(@Miaou);}
-(void) mordreCommePapa { [super mordre];}
@end
Appel
Chat * chat=[[alloc] init];
[chat mordreCommePapa];
===========================================================
#import <Foundation/Foundation.h>
@interface Animal : NSObject
{
}
-(void) mordre;
@end
@interface Chat : Animal
{
}
-(void) mordreCommePapa;
@end
@implementation Animal
-(void) mordre { NSLog(@Ouarf);}
@end
@implementation Chat
-(void) mordre { NSLog(@Miaou);}
-(void) mordreCommePapa { [super mordre];}
@end
int main(int argc, char**argv){
NSAutoreleasePool * pool=[[NSAutoreleasePool alloc] init];
Chat * minou=[[[Chat alloc] init] autorelease];
[minou mordre];
[minou mordreCommePapa];
[pool release];
return 0;
}
Resultat :
% pgm
2008-04-18 06:33:22.618 pgm[218:10b] Miaou
2008-04-18 06:33:22.620 pgm[218:10b] Ouarf
%
Pour moi le NSAnimal * animal ne sert que pour la compilation, et à nous faire de jolis Warnings ... La déclaration ne fait rien du tout sur l'objet en lui-même que l'on manipulera à l'exécution.
Le monde est un gigantesque void *, né de void*, et qui y retournera ...
=============================================
#import <Foundation/Foundation.h>
@interface Animal : NSObject
{
}
-(void) mordre;
@end
@interface Chat : Animal
{
}
@end
@implementation Animal
-(void) mordre { NSLog(@Ouarf);}
@end
@implementation Chat
-(void) mordre { NSLog(@Miaou);}
@end
int main(int argc, char**argv){
NSAutoreleasePool * pool=[[NSAutoreleasePool alloc] init];
NSString * ours=[[[Animal alloc] init] autorelease];
[ours mordre];
[pool release];
return 0;
}
Exécution :
% clear;gcc pgm.m -o pgm -framework Cocoa
pgm.m: In function ‘main':
pgm.m:30: warning: ‘NSString' may not respond to ‘-mordre'
pgm.m:30: warning: (Messages without a matching method signature
pgm.m:30: warning: will be assumed to return ‘id' and accept
pgm.m:30: warning: ‘...' as arguments.)
% pgm
2008-04-18 08:48:25.100 pgm[530:10b] Ouarf
%
Par contre si tu mets Animal* (et pas NSAnimal* tu l'as rajouté d'où le NS ?
Sinon un truc que j'adore dans vos exemples à vous deux, c'est que vous déclarez une NSAutoreleasePool que vous relâchez à la fin de votre main, ce qui est normal... mais vous ne faites jamais ni de release, ni d'autorelease sur l'Animal que vous allouez pour l'exemple ;D Je trouve ça assez comique pour le coup
Ok mais NextStep aurait quand même dû penser à nous fournir une classe aussi importante !! ;D
Pour confirmer tout cela :
Il n'y a aucun warning avec
Chat * ours=[[Chat alloc] init];
[ours mordre];
ou
Animal * ours=[[Chat alloc] init];
[ours mordre];
ou même
Animal * ours=[NSString stringWithString:@Balou];
[ours mordre];
Ce n'est qu'à l'exécution que ça coince sur le dernier avec un "unrecognized selector" bien logique.
D'ailleurs, sur le papier, on peut bein demander à l'ours Balou de mordre en disant "Miaou", ce n'est qu'à l'exécution que ça craint !
C'est un oubli, l'habitude des convenient methods ... Faudrait quand même que je me relise ...
Bon je corrige pour la post-hérité de ce post.
Moi ce matin ma voisine (la mère Michelle) est venue me voir parce qu'elle a perdue son chat (lol), une idée ?
Ok, je sors ->
Oui, mais la vrai question est... est-ce que tu t'appelles Lustucru ? ???
J'ai mis le temps ???
Merci à tous