Geek Quizz VI: jouons avec les portées


Le thème semble simple, pourtant cherchez l’erreur dans le code suivant. L’exercice est plus amusant si vous n’utilisez pas l’aide du compilateur bien évidemment.


J’attends vos suggestions.


class Outer
{
static void F(long l) { }
static void F(string s) { }

class Inner
{
void G()
{
F(
1);
F(
Hello);
}
static void F(long l) { }
}
}


Désolé pour les dates de posts erronées mais je suis aux US (business + vacances pour les curieux :p).


Mitsu


[Update] Quizz suivant: Geek Quizz VII: toujours les portées !

Comments (16)

  1. Simon says:

    C’est sur F("Hello");   je pense, il me semble pas que tu es accès direct au membres statiques de la classe Outer.

  2. Mitsu Furuta says:

    Désolé, mais si, une inner class accède à la portée statique de la classe qui la définit.

    Mitsu

  3. Simon says:

    Bon bah ca doit etre la ligne du dessus alors, il doit couiner parce qu’il sait pas qui appeler (Inner.F(long) ou Outter.F(long))^^

  4. Miiitch says:

    Je pensais comme toi, mais en vérifiant on se rend compte qu’on est loin de la réponse!

  5. L’accès statique existe, mais est-il pour autant implicite ? Moi je pense que le compilateur ne va pas jusqu’à Outer.F(string) tout seul et donc qu’il se rabat sur Inner.F(long)…. et pour F("Hello"), forcément, ça ne doit pas passer.

  6. Sauf erreur de ma part, le fait d’avoir définit une méthode F dans la classe Inner empêche l’accès implicite aux méthodes F de Outer. Du coup, il ne connais plus que static void F(long l). Donc le compilo doit gueuler sur F("Hello");.

    Il faudra donc appeler explicitement le F de Outer :

    F(1);

    Outer.F("Hello");

    En revanche si Inner n’avait pas défini de méthode F, pas de problème.

  7. Petite précision.

    Sauf erreur de ma part, l’accès implicite aux méthodes de Outer via Inner n’est possible que sur les méthodes statiques (ça semble d’ailleurs bien normal).

  8. Mitsu Furuta says:

    Bon, c’est bien un problème de portée mais la vraie réponse n’est pas encore là…

    Dans cet exemple, F("Hello") plante.

    Pourtant si je mets en commentaire la méthode F() de l’inner class, tout fonctionne !

    Donc toutes les syntaxes de portée qu’elles soient implicites ou explicites sont correctes. Le pb est ailleurs.

  9. "Pourtant si je mets en commentaire la méthode F() de l’inner class, tout fonctionne !"

    C’est ce que j’ai dit : "En revanche si Inner n’avait pas défini de méthode F, pas de problème."

    C’est "le fait d’avoir défini une méthode F dans la classe Inner [qui] empêche l’accès implicite aux méthodes F de Outer".

    C’est pas ça ?

  10. Tetranos says:

    Je pense que le fait de mettre la méthode F dans Inner "masque" dans la portée de Inner les méthodes F de Outer.

    Il est toujours possible d’appeler depuis Inner la méthode F de Outer par un appel explicite. En fait, l’appel explicite indique au compilateur dans quelle portée il doit chercher.

  11. Mitsu Furuta says:

    Vous y êtes presque mais ce n’est pas tout à fait ça.

    Dans l’exemple suivant c’est facile. Le i de la méthode Toto() masque la donnée membre.

    class Test

    {

       int i = 0;

       void Toto()

       {

           int i = 1;

       }

    }

    Voici la règle pour les méthodes: lorsqu’une méthode d’une inner class masque une méthode de la classe outer (car la portée en plus proche), alors elle masque toutes les méthodes du même nom et donc tous les occurences de méthodes overloadées.

    Ainsi Inner.F() masque toutes les méthodes F() de Outer.

    Cette règle s’applique aux méthodes qu’elles soient statiques ou non.

  12. Tetranos says:

    Est-ce réellement une règle où un pb lié au compilateur ?

  13. Celui-ci est plus simple que les autres, donc attention: question de rapidité ! Dans l’exemple suivant,

  14. Raluy Gilles says:

    Dans la classe interne, il y a appel de Inner.LaMethodeStatique. En conséquence, la seule méthode appelée est Inner.F par défaut

    Pour appeler une des deux méthodes externes, il faut les qualifier complètement, soit

    Inner.F("Hello …")

    A bientôt

  15. Raluy Gilles says:

    Erratum : Il faut appeler Outer.F("Hello")