Warning bizarre

FloFlo Membre
05:27 modifié dans API AppKit #1
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 :

<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 />	&nbsp;  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 !

«1

Réponses

  • AliGatorAliGator Membre, Modérateur
    05:27 modifié #2
    Bizarre... et si tu essayes :
    return (anItem != nil) ? [anItem childAtIndex: anIndex] : [dataSource childAtIndex: anIndex];
    
    Ca donne quoi ?
  • FloFlo Membre
    05:27 modifié #3
    ça change rien, j'avais déjà  essayé... merci pour ta réponse en tous cas.
  • Philippe49Philippe49 Membre
    05:27 modifié #4
    Je n'arrive pas à  reproduire ton Warning, ni dans un projet XCode, ni lors d'une programmation en ligne de commande ...
    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>


  • FloFlo Membre
    05:27 modifié #5
    En réalité je n'ai changé aucune option du compilateur depuis la création du projet...

    Si je remets cette ligne :

    <br />return (anItem) ? [anItem childAtIndex: anIndex] : [dataSource childAtIndex: anIndex];<br />
    


    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 ?
  • Philippe49Philippe49 Membre
    05:27 modifié #6
    C'est très curieux, car, comme je l'indique au-dessus, l'essai que j'ai fait est sans aucun warning à  la compilation.

    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 ?


  • FloFlo Membre
    janvier 2009 modifié #7
    Si je scinde les lignes comme tu l'indiques, le même warning apparaà®t au niveau de la derniere ligne : [dataSource childAtIndex: anIndex];

    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...
  • FloFlo Membre
    05:27 modifié #8
    Ce que je ne comprends pas c'est que si j'écris ça :

    <br />if (anItem)<br />		return [anItem childAtIndex: anIndex];<br />	<br />	return [dataSource childAtIndex: anIndex];<br />
    


    et ben je n'ai aucun problèmes... :'(

  • Philippe49Philippe49 Membre
    05:27 modifié #9
    dans 1231080801:

    Si je scinde les lignes comme tu l'indiques, le même warning apparaà®t au niveau de la derniere ligne : [dataSource childAtIndex: anIndex];


    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: ?)
  • FloFlo Membre
    05:27 modifié #10

    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... :(
  • FloFlo Membre
    05:27 modifié #11
    Et toi lorsque tu écrits cette ligne :

    <br /> return (item)? self:@&quot;does not exist&quot;;<br />
    


    tu n'as pas de warning ? C'est bizarre d'autant plus que les deux situations sont assez similaires...

  • Philippe49Philippe49 Membre
    05:27 modifié #12
    dans 1231082012:

    tu n'as pas de warning ? C'est bizarre d'autant plus que les deux situations sont assez similaires...

    aucun de chez personne
  • ChachaChacha Membre
    05:27 modifié #13
    Mais il n'a rien de bizarre ce warning ?! Faut pas vous prendre la tête avec des import. Le warning, il dit que l'un des deux opérandes de la construction A ? B : C n'est pas du même type que l'autre.
    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 :

    return (anItem) ? (id)[anItem childAtIndex: anIndex] : (id)[dataSource childAtIndex: anIndex];


    +
    Chacha
  • FloFlo Membre
    05:27 modifié #14

    Je pense que tu as deux méthodes "childAtIndex:" qui renvoient chacune un objet de type différent


    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 :
    <br /> - (NSInteger) outlineView: (NSOutlineView *)outlineView numberOfChildrenOfItem: (id)anItem<br />{<br />	return (anItem) ? [anItem numberOfChildren] : [dataSource numberOfChildren];<br />}<br />
    


    qui ne me retourne aucun warning...
  • FloFlo Membre
    05:27 modifié #15
    A l'exécution bien évidemment le warning ne change rien mais bon, c'est pour le principe...

    EDIT
    La méthode childAtIndex: à  la définition suivante : - (ITTreeNode *) childAtIndex: (NSUInteger)anIndex;

  • Philippe49Philippe49 Membre
    05:27 modifié #16
    Pas de warning avec cela non plus.


    +++++++++++++++++++++++++++++++++++++++++
    #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
  • ChachaChacha Membre
    05:27 modifié #17
    dans 1231082685:

    A l'exécution bien évidemment le warning ne change rien mais bon, c'est pour le principe...

    EDIT
    La méthode childAtIndex: à  la définition suivante : - (ITTreeNode *) childAtIndex: (NSUInteger)anIndex;



    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é
  • FloFlo Membre
    05:27 modifié #18
    "il a le choix entre "- (ITTreeNode *) childAtIndex: (NSUInteger)anIndex;", "- (NSXMLNode *)childAtIndex:(NSUInteger)index", et même "- (PDFOutline *)childAtIndex:(NSUInteger)index"."

    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 !
  • Philippe49Philippe49 Membre
    05:27 modifié #19

    Toujours pas de warning en implémentant childAtIndex:

    -(id)string:(id) item{
    return ( item )?
    [item childAtIndex:0] :  // renvoie un Truc *
    @does not exist;
    }

  • ChachaChacha Membre
    05:27 modifié #20
    dans 1231083460:

    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.

    Exactement !

    Bonne année aussi
    +
    Chacha
  • Philippe49Philippe49 Membre
    05:27 modifié #21
    dans 1231082937:

    Donc il te suffit juste de préciser :
    return (anItem) ? [(ITTreeNode*)anItem numberOfChildren] : [dataSource numberOfChildren];
    Et là  ça lève toute ambiguà¯té


    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.
  • ChachaChacha Membre
    janvier 2009 modifié #22
    dans 1231083664:

    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)"
  • FloFlo Membre
    05:27 modifié #23

    Toujours pas de warning en implémentant childAtIndex:

    -(id)string:(id) item{
      return ( item )?
      [item childAtIndex:0] :  // renvoie un Truc *
      @does not exist;
    }


    ç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 ?
  • Philippe49Philippe49 Membre
    05:27 modifié #24
    Dans le principe de la distribution dynamique des messages, le compilo ne choisit aucune méthode childAtIndex, il cherche sans doute dans les interfaces à  sa disposition (les #import) si il existe une méthode correspondante, mais c'est tout. Après c'est objc_msgSend() qui fait le boulot ...

    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
  • Philippe49Philippe49 Membre
    05:27 modifié #25
    As-tu essayé de changer NSInteger en NSUInteger pour être pile-poil semblable ?
  • ChachaChacha Membre
    05:27 modifié #26
    dans 1231084468:

    Dans le principe de la distribution dynamique des messages, le compilo ne choisit aucune méthode childAtIndex, il cherche sans doute dans les interfaces à  sa disposition (les #import) si il existe une méthode correspondante, mais c'est tout. Après c'est objc_msgSend() qui fait le boulot ...

    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.


    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

    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.
  • FloFlo Membre
    05:27 modifié #27

    As-tu essayé de changer NSInteger en NSUInteger pour être pile-poil semblable ?


    Je viens de tester, toujours ce maudit warning !
  • FloFlo Membre
    05:27 modifié #28

    La warning n'a rien de curieux, il est logique, et révèle que le développeur a laissé une ambiguité


    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...
  • Philippe49Philippe49 Membre
    janvier 2009 modifié #29
    dans 1231085084:

    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.


    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.
  • FloFlo Membre
    janvier 2009 modifié #30
    Dans mon cas, c'est comme si AppController avait une variable d'instance héritant de Truc, du coup se donnerait :

    <br />-(id)string:(id) item{<br />   return ( item )? <br />   [item childAtIndex:0] :  // renvoie un Truc *<br />   [unSousTruc childAtIndex:0]; // demande au sousTruc(var d&#39;instance) de renvoyer un Truc *<br />}<br />
    


    Est-ce que ça pourrait changer la donne ?

  • ChachaChacha Membre
    05:27 modifié #31
    dans 1231085741:

    -(id)string:(id) item{
    return ( item )?
    [item childAtIndex:0] :  // renvoie un Truc *
    @does not exist;


    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;

Connectez-vous ou Inscrivez-vous pour répondre.