Warning bizarre
Flo
Membre
Bonjour à tous et bonne année 2009 sur OC !
En retard mais bon, ma connexion internet à craché pendant une semaine... durdur de passer en dégroupé avec la télé chez neuf-sfr...
J'aurai juste une petite question à vous soumettre, j'ai le code suivant :
Quand je compile, j'ai le warning suivant :
warning: comparison of distinct Objective-C types lacks a cast
J'ai donc réécrit le code comme suit et le warning disparaà®t :
Visiblement cette exemple ne nécessite pas de cast alors que le premier oui, pourquoi ?
Merci d'avance pour vos réponses et encore tout plein de bonnes choses pour 2009 !
En retard mais bon, ma connexion internet à craché pendant une semaine... durdur de passer en dégroupé avec la télé chez neuf-sfr...
J'aurai juste une petite question à vous soumettre, j'ai le code suivant :
<br />- (id) outlineView: (NSOutlineView *)outlineView child: (NSInteger)anIndex ofItem: (id)anItem<br />{ <br />return (anItem) ? [anItem childAtIndex: anIndex] : [dataSource childAtIndex: anIndex];<br />}<br />
Quand je compile, j'ai le warning suivant :
warning: comparison of distinct Objective-C types lacks a cast
J'ai donc réécrit le code comme suit et le warning disparaà®t :
<br />- (id) outlineView: (NSOutlineView *)outlineView child: (NSInteger)anIndex ofItem: (id)anItem<br />{ <br /> if (anItem)<br /> return [anItem childAtIndex: anIndex];<br /> <br /> return [dataSource childAtIndex: anIndex];<br />}<br />
Visiblement cette exemple ne nécessite pas de cast alors que le premier oui, pourquoi ?
Merci d'avance pour vos réponses et encore tout plein de bonnes choses pour 2009 !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Peut-être as-tu des options spéciales sur la target de ton projet ?
Et si tu réécris sous la première forme le warning est toujours là ?
Essai : aucun warning
@implementation AppController
-(id)string:(id) item{
return (item)? self:@does not exist;
}
-(IBAction) buttonAction:(id)sender {
NSLog(@%@",[self string:nil]);
NSLog(@%@",[self string:0]);
NSLog(@%@",[self string:self]);
}
@end
Log :
2009-01-03 23:59:23.732 Untitled[390:10b] does not exist
2009-01-03 23:59:23.733 Untitled[390:10b] does not exist
2009-01-03 23:59:23.735 Untitled[390:10b] <AppController: 0x134950>
Si je remets cette ligne :
j'ai toujours le même warning, bien évidemment si je cast le warning disparaà®t mais il doit bien exister une solution ou le cast n'est pas nécessaire non ?
as-tu des renseignements en séparant les lignes comme ceci :
return
(anItem) ?
[anItem childAtIndex: anIndex] :
[dataSource childAtIndex: anIndex];
dataSource répond bien à childAtIndex: ?
L'interface associée est bien en #import ?
En fait, dans mon projet, ITDataSource hérite de ITTreeNode et je fais bien un
#import "ITDataSource.h" dans le fichier .m. Pas dans le .h ou j'ai mis un
@class ITDataSource; pour éviter une inclusion infinie (car ITDataSource importe aussi la classe dans laquelle j'ai le warning).
Les objets cachés derrière anItem sont de type ITTreeNode. childAtIndex est une méthode de ITTreeNode donc normalement dataSource et anItem répondent tout deux à cette méthode...
et ben je n'ai aucun problèmes...
Si je scinde aussi, le warning apparaà®t à la ligne incorrect
-(id)string:(id) item{
return ( item )?
toto:
Error , blabla ..
@does not exist;
Et si tu fais #import "ITTreeNode.h" en plus (qui doit être l'interface contenant childAtIndex: ?)
Oui c'est ça, il s'agit bien de l'interface qui contient la méthode childAtIndex:
J'avais essayé, et ça ne donne rien...
tu n'as pas de warning ? C'est bizarre d'autant plus que les deux situations sont assez similaires...
aucun de chez personne
Je pense que tu as deux méthodes "childAtIndex:" qui renvoient chacune un objet de type différent. Or, la construction "A ? B : C" nécessite que B et C soient exactement de même type.
Il n'y a rien de mal (au contraire) à écrire :
+
Chacha
Ben non justement, dataSource(sous-classe de ITTreeNode) et anItem(objects de type ITTreeNode) possède tous deux la même méthode childAtIndex: définie dans ITTreeNode.h.
Normalement il ne devrait PAS y avoir de warning d'autant plus qu'ailleur j'ai écrit ça :
qui ne me retourne aucun warning...
EDIT
La méthode childAtIndex: à la définition suivante : - (ITTreeNode *) childAtIndex: (NSUInteger)anIndex;
+++++++++++++++++++++++++++++++++++++++++
#import "Truc.h"
@implementation Truc
-(Truc *) lui_meme {
return self;
}
@end
+++++++++++++++++++++++++++++++++++++++++
#import "AppController.h"
#import "Truc.h"
@implementation AppController
-(void) awakeFromNib {
}
-(id)string:(id) item{
return ( item )?
[item lui_meme] : // renvoie un Truc *
@does not exist;
}
-(IBAction) buttonAction:(id)sender {
Truc * truc=[[Truc alloc]init];
NSLog(@%@",[self string:nil]);
NSLog(@%@",[self string:0]);
NSLog(@%@",[self string:truc]);
}
@end
Oui mais en cocoa, la méthode "- (NSXMLNode *)childAtIndex:(NSUInteger)index" existe déjà . C'est pas que ce soit gênnt, mais sur un objet "inconnu" de type "id", le compilateur ne sait pas laquelle sera employée. ça marchera au run-time, mais à la compilation, il a le choix entre "- (ITTreeNode *) childAtIndex: (NSUInteger)anIndex;", "- (NSXMLNode *)childAtIndex:(NSUInteger)index", et même "- (PDFOutline *)childAtIndex:(NSUInteger)index".
Donc il te suffit juste de préciser :
return (anItem) ? [(ITTreeNode*)anItem numberOfChildren] : [dataSource numberOfChildren];
Et là ça lève toute ambiguà¯té
Ha pas con...
ça expliquerait pourquoi les exemple de philippe49 marchent et pourquoi l'exemple avec numberOfChildren marchent aussi... (ça expliquerait aussi pourquoi l'éditeur de texte me met la méthode childAtIndex: en bleu et pas en vert...)
Donc si j'ai bien compris, il faut, soit caster, soit renommer la méthode pour que le compilo n'est qu'un choix possible à la compilation.
Merci à tous deux et bonne année 2009 !
Toujours pas de warning en implémentant childAtIndex:
-(id)string:(id) item{
return ( item )?
[item childAtIndex:0] : // renvoie un Truc *
@does not exist;
}
Exactement !
Bonne année aussi
+
Chacha
Certes le cast lève l'ambiguité, mais id ne sert plus à rien , et ce que tu dis va contre le principe de l'envoi dynamique des messages.
Pas du tout.
Ce que j'ai dit, c'est que ça ne gêne que le compilo dans la construction "A ? B : C".
Ici, (C) = [dataSource childAtIndex: anIndex], et on sait qu'il s'agit de "-(ITTreeNode*) childAtIndex:" via le typage fort
Mais (B) = [anItem childAtIndex: anIndex], où anItem laisse une ambiguà¯té.
Si tu veux, on enlève aussi le warning avec
return (anItem) ? [anItem childAtIndex:anIndex] : [(id)dataSource childAtIndex:anIndex]];
Logiquement, même si le compilo se "trompe" de childAtIndex:, c'est tout à fait correct.
[EDIT]Il faut juste que le compilo fasse un choix qui donne le même type à (B) et (C)"
ça prouve bien qu'il y a moyen d'implémenter la chose sans caster...
Le fait que j'ai un @class ITDataSource; dans le .h de la classe qui implémente la méthode : - (id) outlineView: (NSOutlineView *)outlineView child: (NSInteger)anIndex ofItem: (id)anItem ne change rien non ?
Par exemple :
#import "AppController.h"
#import "Truc.h"
@implementation AppController
-(void) awakeFromNib {
}
-(id)string:(id) item{
return ( item )?
[item bivouac] : // renvoie un Truc *
Warning : no method bivouac found ...
@does not exist;
}
-(IBAction) buttonAction:(id)sender {
Truc * truc=[[Truc alloc]init];
NSLog(@%@",[self string:nil]);
NSLog(@%@",[self string:0]);
NSLog(@%@",[self string:truc]);
}
@end
Ceci dit, t'as raison sur un point, c'est que quand on a la solution du cast , cela devient une curiosité que ce warning ... ou alors une erreur masquée
Oui, c'est ce que je dis, au run-time, ça marche très bien, mais le compilo, lui, voit plusieurs méthodes qui peuvent aller. Il "choisit" (entre guillemets) sans doute la première qui convient, et là il la trouve dans Cocoa.
Que veux-tu dire ? La warning n'a rien de curieux, il est logique, et révèle que le développeur a laissé une ambiguité. C'est donc gentil de sa part de le signaler.
Je viens de tester, toujours ce maudit warning !
Oui mais si je comprends bien, dans l'exemple de philippe49 contenant la méthode childAtIndex: (dans Truc non ?) l'ambiguà¯té est la même et pourtant il n'y a pas de warning pour la signaler...
Si cela était comme tu le dis, dès qu'une signature de méthode est partagée entre plusieurs classes on aurait des warnings ?
ce n'est pas ainsi que cela se passe d'habitude . je reprends mon exemple en totalité, il est sans warning aucun, et pourtant NSXML est dans Foundation.framework
=======================================
#import <Cocoa/Cocoa.h>
@interface Truc : NSObject {
}
-(Truc *) childAtIndex:(NSUInteger) n ;
@end
=======================================
#import <Cocoa/Cocoa.h>
@interface AppController : NSObject {
}
-(id) string:(id) item;
-(IBAction) buttonAction:(id)sender;
@end
=======================================
#import "AppController.h"
#import "Truc.h"
@implementation AppController
-(void) awakeFromNib {
}
-(id)string:(id) item{
return ( item )?
[item childAtIndex:0] :Â // renvoie un Truc *
@does not exist;
}
-(IBAction) buttonAction:(id)sender {
Truc * truc=[[Truc alloc]init];
NSLog(@%@",[self string:nil]);
NSLog(@%@",[self string:0]);
NSLog(@%@",[self string:truc]);
}
@end
Pour moi, cela semble plutôt une réaction imprévue du compiiateur.
Est-ce que ça pourrait changer la donne ?
Je ne sais pas comment les chaà®nes statiques sont gérées, mais le code suivant génère bien le warning :
return ( item ) ? [item childAtIndex:0] : (NSString*)@does not exist;