Différence entre @protocol et @interface?
Greensource
Membre
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
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
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Si en java on a:
public class MaClasse extends Object implements ActionListener, MenuListener
en ObjC ça donne:
@interface MaClasse : NSObject <ActionListener,MenuListener>
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).
Ca d'accord je comprend mais ton exemple ne me parait pas correspondre:
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:
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
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.
Enfin merci en tout cas.
Donc pour mon exemple je ferais quelques chose du genre:
et Humain qui implémente Joueur comme ceci:
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.
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 :
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Â
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.
Oki doki je vois.
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.
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.
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é...
Non, mettre le nom du protocole entre crochet suffit
@interface MaClasse : DadClass <UnProtocole , UnAutreProtocole> {
}
@end
Sinon est-ce normale d'avoir cette erreur dans xCode:
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"?
Moi j'appelle ça plutôt des chevrons que des crochets, mais bon... chacun sa terminologie :P
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.
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.
Par contre, on peut l'utiliser comme type d'argument.
id<GWPlayer> maClasse;
sinon:
MaClasse<GWPlayer> *maClasse;
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?
C'est même combat : id<Protocol>
Tu veux dire qu'on peut effectivement déclarer un objet de type protocol?
En Java (et en C++), un " Protocole " est une classe (virtuelle).
Pas en Objective-C.
Nop, je voulais dire qu'on ne peut pas l'utiliser non plus comme argument d'une méthode...
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.
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:
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?
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)...
@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: ...]
.....
}
Exemple:
NSNumber * aNumber=[NSNumber numberWithFloat:12.05];
NSString * aString=aNumber;
NSLog(@%@",[aString class]); ==> affiche NSCFNumber
NSString * otherString=(NSString *)aNumber;
NSLog(@%@",[otherString class]); ==> affiche NSCFNumber