Différence entre @protocol et @interface?

GreensourceGreensource Membre
08:37 modifié dans API AppKit #1
Bonjour bonjour! ;)
Je pense que mon titre est assez clair, je viens de lire la doc Apple sur Objectice-C mais j'avoue que l'Anglais dois encore me bloquer pour quelques subtilités. Du coup quand je suis tomber sur les protocole et les interface j'ai bien saisi la différence entre les deux.
Je suis étudiant et on fait quasi que du Java dans ma Fac donc ça me trouble peut-être à  cause de ça.

Ce que moi j'ai envi de faire dans mon projet, c'est par exemple une interface(java) Joueur avec une implémentation Humain de cette interface.

Merci en tout cas si quelqu'un peu m'aider.
Green
«1

Réponses

  • mpergandmpergand Membre
    08:37 modifié #2
    Les interfaces en java sont l'équivalent des protocols en ObjC

    Si en java on a:
    public class MaClasse extends Object implements ActionListener, MenuListener


    en ObjC ça donne:
    @interface MaClasse : NSObject <ActionListener,MenuListener>
  • FloFlo Membre
    février 2009 modifié #3
    Juste une petite précision, un truc que j'ai remarqué, la notion de classe abstraite telle qu'elle est implémentée en Java n'existe pas en objective-c.

    A ma connaissance, il existe également deux types de protocols :
    - formal : la classe s'engage à  implémenter toutes les méthodes du protocole
    - informal : certaine méthodes peuvent être optionnelles (le développeur doit clairement spécifier les méthodes requises et celles qui sont optionnelles).
  • GreensourceGreensource Membre
    08:37 modifié #4
    Oulà  je ne te suit pas tout à  fait, tu dit:
    dans 1235033008:

    Les interfaces en java sont l'équivalent des protocols en ObjC

    Ca d'accord je comprend mais ton exemple ne me parait pas correspondre:
    dans 1235033008:

    Si en java on a:
    public class MaClasse extends Object implements ActionListener, MenuListener

    Donc ici tu définis une classe qui hérite d'Object et qui doit implémenter les interfaces ActionListener et MenuListener c'est bien ça?
    Mais ici:
    dans 1235033008:

    en ObjC ça donne:
    @interface MaClasse : NSObject <ActionListener,MenuListener>

    J'ai l'impression que tu définis une autre interface (pas une class comme l'exemple java plus haut) qui hérite et implémente les mêmes choses.
    Je pense que ce que je ne comprend pas c'est que moi j'aurais mis plutôt class que @interface?
    Donc si je te suit, @interface veut dire "je déclare une class qui va devoir implémenter des protocoles/interfaces" et @protocol veut dire "je déclare une interface/protocol" c'est bien ça?

    Merci
  • FloFlo Membre
    février 2009 modifié #5

    Donc si je te suit, @interface veut dire "je déclare une class qui va devoir implémenter des protocoles/interfaces" et @protocol veut dire "je déclare une interface/protocol" c'est bien ça?


    C'est ça, la confusion vient du fait que le mot clé @interface est utilisé pour définir l'interface d'une classe et non une interface au sens Java du terme.

    Cette ligne : "@interface MaClasse : NSObject <ActionListener,MenuListener>"
    définit l'interface de la classe MaClasse héritant de NSObject et implémentant les protocols ActionListener et MenuListener.
    A souligner que les protocols ActionListener et MenuListener sont ici considérés comme formal... En informal, il n'est pas nécessaire de mettre les <> et les noms des protocoles.
  • GreensourceGreensource Membre
    08:37 modifié #6
    Mais c'est un peu étrange non? Ca donne l'impression de ce répéter. @interface + <interface1,interface2...>.
    Enfin merci en tout cas.
    Donc pour mon exemple je ferais quelques chose du genre:
    @protocol Joueur<br />{<br />}<br />method1();<br />method2();
    


    et Humain qui implémente Joueur comme ceci:
    @interface Humain &lt;Joueur&gt;<br />{<br />att1;<br />att2;...<br />}<br />method1();<br />method2();
    

    Ais-je vraiment besoin de réécrire method1 et method2 puisque je dit que j'implémente Joueur?

    Merci! Et je vais relire la doc Apple avec vos lumières ça devrais mieux passer.
  • FloFlo Membre
    février 2009 modifié #7

    Mais c'est un peu étrange non? Ca donne l'impression de ce répéter. @interface + <interface1,interface2...>


    Pas du tout puisque ce sont deux choses bien différentes :
    - @interface signifie interface de classe, soient les méthodes et variables d'instances d'une classe

    - <protocol1, protocol2...> signifie, dans l'interface de MaClasse on va trouver une signature pour chaque méthode définie dans protocol1, protocol2 ...

    Pour définir un protocol c'est comme ça :
    <br />@protocol Joueur<br />  - method1();<br />  - method2();<br />@end<br />
    



    Ais-je vraiment besoin de réécrire method1 et method2 puisque je dit que j'implémente Joueur?


    Oui, les méthodes des protocols ne contiennent pas de code. Le compilo vérifie juste qu'il trouve une signature correspondante dans les classes qui implémente le protocol. Implémenter signifie bien donner une implémentation, donc écrire du code  :o

    A toute classe en objective-c correspond deux fichiers (un d'extension .h et l'autre d'extension .m) :
    - le .h contient l'interface de la classe (balise @interface) soient les varibles d'instance et la signature des méthodes d'instance ou de classes.
    - le .m contient l'implémentation d'au moins chacune des méthodes définies dans le .h.

    La notion d'interface de Java est donc standardisée en objective-c à  chaque classe.
  • GreensourceGreensource Membre
    08:37 modifié #8
    dans 1235038844:

    Pour définir un protocol c'est comme ça :
    <br />@protocol Joueur<br />&nbsp; - method1();<br />&nbsp; - method2();<br />@end<br />
    


    Oki doki je vois.

    dans 1235038844:

    Oui, les méthodes des protocols ne contiennent pas de code. Le compilo vérifie juste qu'il trouve une signature correspondante dans les classes qui implémente le protocol. Implémenter signifie bien donner une implémentation, donc écrire du code  :o


    Oui oui ça je savais, ce que je voulais dire c'était plutôt doit-on les marqué dans le header? Je me disais que ça n'étais peut-être pas nécessaire dans le sens où ma class implémente tel protocole elle à  forcément implémenté ses méthodes.

    Merci merci.
  • FloFlo Membre
    08:37 modifié #9

    Oui oui ça je savais, ce que je voulais dire c'était plutôt doit-on les marqué dans le header? Je me disais que ça n'étais peut-être pas nécessaire dans le sens où ma class implémente tel protocole elle à  forcément implémenté ses méthodes.


    Ha autant pour moi...
    Il faut faire un #import "MonProtocol.h" dans chaque interface de classe implémentant le protocole et pour chaque protocole.

    Il me semble qu'il faut réécrire les signatures des méthodes pour les protocoles de type formal. Ce qui est sûr c'est que ce n'est pas nécessaire pour les protocoles de type informal.
  • GreensourceGreensource Membre
    08:37 modifié #10
    Donc comme j'ai dit je relit la doc là , j'ai encore une petite interrogation. Je suppose que quand on fait un protocol on ne créer pas de .m seulement le .h? Mais je n'en suis pas sur. En tout cas je ne voit pas ce que je pourrais écrire dans le .m?
  • FloFlo Membre
    08:37 modifié #11

    Donc comme j'ai dit je relit la doc là , j'ai encore une petite interrogation. Je suppose que quand on fait un protocol on ne créer pas de .m seulement le .h?


    Absolument !
    Il me semble qu'un genre de protocole visant à  contenir du code était en projet avec l'objective-c 2.0 mais je ne sais pas si ça à  été réalisé...
  • GreensourceGreensource Membre
    08:37 modifié #12
    Okay, merci c'est gentil de m'aider et tu es super réactif en plus! 
  • Philippe49Philippe49 Membre
    février 2009 modifié #13
    dans 1235039878:

    Il me semble qu'il faut réécrire les signatures des méthodes pour les protocoles de type formal.


    Non, mettre le nom du protocole entre crochet suffit

    @interface MaClasse : DadClass <UnProtocole , UnAutreProtocole> {
    }
    @end
  • GreensourceGreensource Membre
    08:37 modifié #14
    Bon c'est cool j'ai réussi ce que je voulais (enfin ça compile c'est déjà  ça ^^)
    Sinon est-ce normale d'avoir cette erreur dans xCode:
    warning: cannot find interface declaration for 'GWPlayer'

    En gros il me dit, c'est bizarre tu n'as pas de .m qui va avec ton .h
    Ca voudrais dire qu'il faut en faire une implémentation "de base"?
  • schlumschlum Membre
    08:37 modifié #15
    dans 1235042311:

    dans 1235039878:

    Il me semble qu'il faut réécrire les signatures des méthodes pour les protocoles de type formal.


    Non, mettre le nom du protocole entre crochet suffit

    @interface MaClasse : DadClass <UnProtocole , UnAutreProtocole> {
    }
    @end


    Moi j'appelle ça plutôt des chevrons que des crochets, mais bon... chacun sa terminologie  :P
  • Philippe49Philippe49 Membre
    08:37 modifié #16
    dans 1235047287:

    Bon c'est cool j'ai réussi ce que je voulais (enfin ça compile c'est déjà  ça ^^)
    Sinon est-ce normale d'avoir cette erreur dans xCode:
    warning: cannot find interface declaration for 'GWPlayer'

    En gros il me dit, c'est bizarre tu n'as pas de .m qui va avec ton .h
    Ca voudrais dire qu'il faut en faire une implémentation "de base"?

    Non, il te dit je ne trouve pas GWPlayer.h
  • GreensourceGreensource Membre
    08:37 modifié #17
    dans 1235048153:

    dans 1235047287:

    Bon c'est cool j'ai réussi ce que je voulais (enfin ça compile c'est déjà  ça ^^)
    Sinon est-ce normale d'avoir cette erreur dans xCode:
    warning: cannot find interface declaration for 'GWPlayer'

    En gros il me dit, c'est bizarre tu n'as pas de .m qui va avec ton .h
    Ca voudrais dire qu'il faut en faire une implémentation "de base"?

    Non, il te dit je ne trouve pas GWPlayer.h

    En fait je crois avoir trouver d'où ça viens. J'avais fait une nouvelle "Objective-c class" pour faire le protocole du coup il avait l'air de chercher le .m
    Mais même après avoir résolu le souci l'erreur restait, j'ai du relancer xcode et maintenant c'est bon. Il doit exister quelques choses pour réinitialiser les erreurs non? Un genre de clean comme avec les Makefile.
  • Philippe49Philippe49 Membre
    08:37 modifié #18
    Menu Build > Clean et Build > Clean Alll Targets
  • GreensourceGreensource Membre
    08:37 modifié #19
    Ok, merci philippe!
    Je crois avoir un autre souci (ça fait beaucoup hein ^^)
    Mais c'est toujours dans le même sujet.
    Peut-on déclarer un objet de type du protocole?
    Par exemple moi j'ai un @protocol GWPlayer ais-je le droit d'écrire GWPlayer *myPlayer; ??
    Parce qu'xCode n'a pas l'air du tout d'apprécier? Mais je trouve ça étrange.
  • schlumschlum Membre
    08:37 modifié #20
    On ne peut pas instancier un protocole... Une variable déclarée avec un type protocole n'a aucun sens.
    Par contre, on peut l'utiliser comme type d'argument.
  • mpergandmpergand Membre
    08:37 modifié #21
    Si tu ne connais pas le type de la classe, juste le protocole :

    id<GWPlayer> maClasse; 

    sinon:

    MaClasse<GWPlayer> *maClasse;
  • GreensourceGreensource Membre
    février 2009 modifié #22
    dans 1235050090:

    On ne peut pas instancier un protocole... Une variable déclarée avec un type protocole n'a aucun sens.
    Par contre, on peut l'utiliser comme type d'argument.

    Qu'on ne puisse instancier avec un type protocol je suis d'accord ça n'a aucun sens. Mais on doit forcément pouvoir dire que tel variable x est de type T avec T un type protocol, c'est bien le sens d'une interface! Par exemple en Java si je fait une Interface Player avec une implémentation Human de cette interface, et bien ensuite je pourrais écrire:
    Player j1;
    j1 = new Human();

    Or moi dans mon code xCode tique lorsque j'écrit Player p1;
    J'ai l'impression que je ne comprend pas un truc là ...

    [edit] Ah oui mais je pense à  ça, ce que je veux faire c'est plutôt ce qu'on appel "informal protocol" auquel cas je pourrais avoir un type de ce protocole?
    Mais alors du coup, si c'est ça, je ne vois plus bien à  quoi sert un protocole formal?
  • schlumschlum Membre
    08:37 modifié #23
    Pour le type d'argument j'ai dit des bêtises... Perturbé par le C++ en ce moment  :P

    C'est même combat : id<Protocol>
  • GreensourceGreensource Membre
    08:37 modifié #24
    Excuse moi mais je n'ai pas bien compris ce que tu as voulu dire schlum dans ton dernier post?
    Tu veux dire qu'on peut effectivement déclarer un objet de type protocol?
  • schlumschlum Membre
    08:37 modifié #25
    dans 1235050411:

    dans 1235050090:

    On ne peut pas instancier un protocole... Une variable déclarée avec un type protocole n'a aucun sens.
    Par contre, on peut l'utiliser comme type d'argument.

    Qu'on ne puisse instancier avec un type protocol je suis d'accord ça n'a aucun sens. Mais on doit forcément pouvoir dire que tel variable x est de type T avec T un type protocol, c'est bien le sens d'une interface! Par exemple en Java si je fait une Interface Player avec une implémentation Human de cette interface, et bien ensuite je pourrais écrire:
    Player j1;
    j1 = new Human();

    Or moi dans mon code xCode tique lorsque j'écrit Player p1;
    J'ai l'impression que je ne comprend pas un truc là ...

    [edit] Ah oui mais je pense à  ça, ce que je veux faire c'est plutôt ce qu'on appel "informal protocol" auquel cas je pourrais avoir un type de ce protocole?
    Mais alors du coup, si c'est ça, je ne vois plus bien à  quoi sert un protocole formal?


    En Java (et en C++), un " Protocole " est une classe (virtuelle).
    Pas en Objective-C.
  • schlumschlum Membre
    08:37 modifié #26
    dans 1235051133:

    Excuse moi mais je n'ai pas bien compris ce que tu as voulu dire schlum dans ton dernier post?
    Tu veux dire qu'on peut effectivement déclarer un objet de type protocol?


    Nop, je voulais dire qu'on ne peut pas l'utiliser non plus comme argument d'une méthode...
  • Philippe49Philippe49 Membre
    février 2009 modifié #27
    Déclarer qu'un objet se conforme à  un protocole signifie qu'il implémente les méthodes dont la liste est donnée par le protocole.
    En quelque sorte un protocol en Objective-C est une liste de méthodes (dont certaines optionnelles) auxquelles l'objet ou la classe s'engage à  répondre (en ce qui concerne les méthodes non optionnelles) .

    Quand on met comme dit Pergand
    id <unProtocole> suivi d'une instance unObjet cela signifie que le programmeur s'engage à  ce que l'objet en question soit de classe indéterminée, mais que la classe saura répondre à  la liste de méthodes (non optionnelles) du protocole. Cela ne définit aucune classe pour l'objet.


    Quand on met dans l'interface
    @interface MaClasse : DadClass <UnProtocole , UnAutreProtocole> {
    }
    cela signifie que toute instance de maClasse (ou maClasse pour une méthode de classe) saura répondre aux méthodes (non optionnelles) du protocole. maClasse.m doit donc implémenter ces méthodes sans les redéclarer dans son interface autrement que la syntaxe entre crochets chevrons.


    En aucun cas, un protocole ne définit une classe d'objets.
  • GreensourceGreensource Membre
    février 2009 modifié #28
    Bon bon, alors je crois que je fait un peu n'importe quoi ou que je ne comprend rien à  l'Objective-C  ???
    En gros je fait un jeu, il y a deux types de joueur, Humain et IA. Pour pouvoir utiliser ces deux types de joueur j'ai bien besoin d'une interface/protocole?

    Parce que par exemple plus loin dans mon code, j'ai des Cases qui doivent avoir un attribut "controller" (celui qui la contrôle). Cet attribut doit bien être du type Joueur et pas IA ou Humain.
    Mais alors comment je fait si je ne peu déclarer un objet de type protocole?
    J'ai bien penser à  faire hériter IA et Humain de Joueur mais ce n'est pas vraiment ça que je veux, je veux juste que Humain et IA ai certaine méthodes en commun.

    En cours, en java on avais fait quelques chose dans ce style.

    Merci en tout cas du temps que vous passez à  répondre...

    ps: Schlum, quand tu dis:

    En Java (et en C++), un " Protocole " est une classe (virtuelle).
    Pas en Objective-C.

    Ca implique quoi exactment?

    [edit pour le message de philippe vue après ^^]
    Hum hum, du coup moi ce que je veux faire c'est quand même plutôt un héritage de IA et Humain qui hérite de Joueur?
  • schlumschlum Membre
    08:37 modifié #29
    On peut simuler une classe virtuelle en Objective-C ; il suffit d'implémenter les méthodes " virtuelles " en balançant une exception.
    Le problème c'est qu'on en verra pas les ennuis à  la compilation, mais à  l'exécution (un des principaux effets de bord du " dynamisme " de l'Objective-C).

    Qu'un protocole ne soit pas une classe implique qu'on ne peut pas l'utiliser comme une classe où que ça soit ; il faut toujours l'utiliser entre chevrons <Protocol>.
    Le type "id" permettant l'" indirection " (langage dynamique)...
  • Philippe49Philippe49 Membre
    08:37 modifié #30
    Le schéma d'héritage en Objective C :

    @interface IA:Joueur {
    }
    @end

    @interface Humain:Joueur {
    }
    @end

    et IA et Humain hérite de la liste des méthodes de Joueur et de l'implémentation dans cette classe.
    Ils peuvent éventuellement redéfinir leur propre implémentation.

    Si on ne redéfinit rien, et ben c'est l'implémentation de Joueur qui est utilisée,
    Si on redéfinit, on peut (ce n'est pas obligatoire) faire agir l'implémentation de la classe parent par
    -(...) methode : .. arguments {
        .....
        .....  [super  methode: ...]
        .....
    }
  • Philippe49Philippe49 Membre
    08:37 modifié #31
    Il faut également bien comprendre que les déclarations id <unProtocol> unObjet ne sert qu'à  la gestion des warnings et erreurs pour le compilateur, et ne fixe pas la classe de l'objet

    Exemple:
    NSNumber * aNumber=[NSNumber numberWithFloat:12.05];
    NSString * aString=aNumber;
    NSLog(@%@",[aString class]);      ==> affiche NSCFNumber
    NSString * otherString=(NSString *)aNumber;
    NSLog(@%@",[otherString class]);  ==> affiche NSCFNumber

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