Java et la générécité - Java - Programmation
Marsh Posté le 01-02-2006 à 16:00:33
parce que PileArrayList hérite de Pile surement (ou implémente une interface Pile)
Marsh Posté le 01-02-2006 à 16:03:31
Harkonnen a écrit : parce que PileArrayList hérite de Pile surement (ou implémente une interface Pile) |
C'est exact. Mais je ne vois pas pourquoi on doit déclarer la variable de type Pile et non de type PileArrayList. Moi j'ai toujours conçu qu'on déclare une variable d'un type puis on instancie avec le même type.
Marsh Posté le 01-02-2006 à 16:07:02
Parce que l'utilisateur de ta pile n'a pas a savoir quelle est l'implémentation derriere. Tout ce qui le concerne, c'est l'interface. Apres, qu'il y ait une ArrayList ou un Canard derriere, il n'a pas a le savoir.
Marsh Posté le 01-02-2006 à 16:16:58
lorill a écrit : Parce que l'utilisateur de ta pile n'a pas a savoir quelle est l'implémentation derriere. Tout ce qui le concerne, c'est l'interface. Apres, qu'il y ait une ArrayList ou un Canard derriere, il n'a pas a le savoir. |
Oui mais pourquoi alors c'est différent ?
Pile unePile
et unePile = new PileArrayList
S'il n'a pas a savoir quel interface on utilise dans la classe PileArrayList c'est mal partie parce que on déclare la variable du type de l'interface.
Marsh Posté le 01-02-2006 à 16:17:29
Quand une classe hérite d'une classe abstraite il est préférable de déclarer ses variables du type abstrait (c'est moins limitatif et donc plus évolutif)
Exemple : Imagine une classe avec un attribut de type Vector. Tu a donc toute une série de méthode qui retournent ou ont des parametres de type Vector (les accesseurs par exemple)
Imagine maintenant que tu n'aimes plus la classe Vector (ex : les accès sont synchronized donc moins performant), tu veux changer le type de ton attribut par ArrayList (c'est la même chose mais les accès ne sont pas synchonisés).
Ca va coincer car partout où tu manipulait un Vector tu va devoir changer en ArrayList...
Imagine maintenant qu'au départ tu ais définis ton attribut comme une java.utils.List (Vector et ArrayList implémentent List) => a priori, la seule modif à faire sera de changer les new Vector() par new ArrayList()
Marsh Posté le 01-02-2006 à 16:19:03
NullDragon a écrit : |
tsk tsk tsk.
Il n'a pas a savoir l'implémentation.
Pense a l'interface comme a un contrat entre ton objet réel et les objets qui vont le manipuler. Tu t'engages a faire telle et telle chose, mais pas a dévoiler ton etat interne (le fait que tu ais une list ou pas, ...)
Marsh Posté le 01-02-2006 à 16:21:25
NullDragon a écrit : |
Faux, c'est exactement le contraire : l'utilisateur de ta pile doit connaitre l'interface et les méthodes qu'elle expose, rien de plus. Il n'a pas à savoir ce qui se cache derrière l'implémentation de cette interface (la classe PileArrayList en l'occurence)
Marsh Posté le 01-02-2006 à 16:24:01
Euh...je n'ai pas très bien compris, mais si c'est pour éviter de changer le nom du type, il faut quand même changer le new partout non ?
Marsh Posté le 01-02-2006 à 16:25:58
Harkonnen a écrit : Faux, c'est exactement le contraire : l'utilisateur de ta pile doit connaitre l'interface et les méthodes qu'elle expose, rien de plus. Il n'a pas à savoir ce qui se cache derrière l'implémentation de cette interface (la classe PileArrayList en l'occurence) |
Euh...
Moi je mettrais plutôt:
PileArrayList unePile
unePile = new PileArrayList
tout comme on écrit:
Personne unePersonne
unePersonne = new Personne
Marsh Posté le 01-02-2006 à 16:27:35
lorill a écrit : tsk tsk tsk. |
Oui mais on la voit l'implémentation à cause du new PileArrayList de toute façon non ?
Marsh Posté le 01-02-2006 à 16:28:40
NullDragon a écrit : Euh...je n'ai pas très bien compris, mais si c'est pour éviter de changer le nom du type, il faut quand même changer le new partout non ? |
tu changes le code de ton objet, mais pas celui de tous les endroits ou tu l'utilise.
mais de toutes facons, ca n'est qu'un gain pratique (et avec un bon ide, tu peux le faire de toutes facons), la vrai raison est plus conceptuelle. Maintenant si tu t'obstines, je vais pas insister.
Marsh Posté le 01-02-2006 à 16:31:05
lorill a écrit : tu changes le code de ton objet, mais pas celui de tous les endroits ou tu l'utilise. |
Non c'est juste que je ne comprends pas la logique et j'aimerais comprendre
Marsh Posté le 01-02-2006 à 16:33:12
NullDragon a écrit : Oui mais on la voit l'implémentation à cause du new PileArrayList de toute façon non ? |
je crois que je vois le probleme.
1. définition d'un objet
Code :
|
2. définition d'un autre objet sur la même interface
Code :
|
On voit bien que les deux objets ont un fonctionnement interne différent, mais implémentent la même interface, non ?
3. utilisation de l'objet
Code :
|
La, on voit bien que la méthode delegueLeTraitement, qui utilise l'objet, ne connait pas son implémentation.
Et donc, si dans utilisation() tu changes d'implémentation, le reste est identique.
Marsh Posté le 01-02-2006 à 16:37:46
NullDragon a écrit : Euh... |
mais nom d'un cheveu de Kojak, réflechis un peu !
ta classe PileArrayList implémente l'interface Pile. ce qui veut dire qu'elle doit implémenter obligatoirement toutes les méthodes de Pile. donc on peut écrire que PileArrayList est une Pile.
toi qui sembles aimer les analogies, imagine une interface "Véhicule", qui expose 2 méthodes : accélerer() et tourner().
tu créé ensuite une classe "Voiture" qui implémente Véhicule, et une classe "Moto" qui implémente aussi Véhicule. tu implémentes donc dans ces classes les 2 méthodes de Véhicule.
tu vas déclarer ensuite 2 véhicules : une voiture et une moto
Code :
|
maintenant, que se passe t'il si tu ne connais strictement rien des classes Moto et Voiture ? tu veux par exemple les faire tourner, mais tu ne connais pas le nom de la méthode qui permet de faire ça. tu ne sais même pas si le concepteur de ces classes a pensé à ajouter une méthode pour les faire tourner... Mais : comme tu sais qu'elles implémentent l'interface Vehicule, qui elle même oblige toute classe l'implémentant à implémenter cette méthode, tu peux donc écrire :
Code :
|
tu saisis le topo ?
Marsh Posté le 01-02-2006 à 16:38:57
je crois que tu es un peu hors sujet, la question n'est pas sur l'utilité d'une interface dans ce sens, mais au niveau de la déclaration.
Marsh Posté le 01-02-2006 à 16:40:15
NullDragon a écrit : Euh ou est passé le new la dedans ?? |
dans utilisation(), il crée l'objet avant de déleguer le traitement a une autre méthode.
typiquement, ca pourrait etre un constructeur qui instancie un de ses attributs, utilisé par la suite par une de ses methode.
Marsh Posté le 01-02-2006 à 16:41:34
ReplyMarsh Posté le 01-02-2006 à 16:43:09
lorill a écrit : je crois que tu es un peu hors sujet, la question n'est pas sur l'utilité d'une interface dans ce sens, mais au niveau de la déclaration. |
ben oui, mais s'il ne comprend pas qu'on peut utiliser un pointeur sur une classe dérivée pour initialiser un pointeur sur classe de base, il risque pas de comprendre cette déclaration
Marsh Posté le 01-02-2006 à 16:43:51
NullDragon a écrit : Désolé les mecs, mais je ne saisi toujours pas la raison du Pile unePile |
Je te rassure, j'ai compris, je vois a quoi ca sert...mais je ne l'utiliserai jamais.
Marsh Posté le 01-02-2006 à 16:44:02
ReplyMarsh Posté le 01-02-2006 à 16:44:53
Harkonnen a écrit : ben oui, mais s'il ne comprend pas qu'on peut utiliser un pointeur sur une classe dérivée pour initialiser un pointeur sur classe de base, il risque pas de comprendre cette déclaration |
d'apres ce que j'ai compris, il a compris qu'il pouvais, mais il n'a pas compris ou était l'interet.
compris ?
Marsh Posté le 01-02-2006 à 16:47:57
Si, il y a un intérêt. C'est rendre le code un peu plus illisible
Marsh Posté le 01-02-2006 à 16:48:08
lorill a écrit : c'est harko qui perturbe la classe |
j'essaie juste de montrer que je sais faire autre chose que du Win32, du C# ou de l'assembleur
lorill a écrit : d'apres ce que j'ai compris, il a compris qu'il pouvais, mais il n'a pas compris ou était l'interet. |
ben l'exemple que je lui ai pondu peut quand même l'aider à comprendre je pense, non ?
Marsh Posté le 01-02-2006 à 16:48:54
Ce que je comprends, jusqu'à présent, c'est que:
Pile unePile; déclare une variable d'interface.
Mais ça mange quoi en hiver une variable d'interface ?
Marsh Posté le 01-02-2006 à 16:52:11
NullDragon a écrit : Mais ça mange quoi en hiver une variable d'interface ? |
N'importe quel objet qui l'implémente..
Marsh Posté le 01-02-2006 à 16:53:26
NullDragon a écrit : Ce que je comprends, jusqu'à présent, c'est que: |
Ca descendance
Marsh Posté le 01-02-2006 à 16:54:34
une variable d'interface, ca ne veut rien dire.
avec "Pile unePile;" tu déclares une variable de type Pile.
il se trouve que Pile est une interface, mais ca serait une classe que ca ne changerait rien au probleme.
On va faire plus simple.
Tu as ton ArrayList. Quand tu ajoutes quelquechose dedans, il te demande un Object. Toi tu lui mets une String. Ca marche, parce que String est un Object.
maintenant, s'ils n'avaient pas mis Object, mais String, tu ne pourrais pas mettre d'Integer, d'accord ?
ben la c'est pareil. Alors tu va me dire qu'Object n'est pas une interface, mais on s'en fout, c'est le principe qui compte.
Marsh Posté le 01-02-2006 à 16:57:27
ReplyMarsh Posté le 01-02-2006 à 16:58:12
rhoo puis tiens, va :
http://penserenjava.free.fr/pens_2 [...] =00#00.003
si ca suffit pas, lit tout le site, ca devrait eclaircir pas mal de points, le livre explique mieux que moi.
Marsh Posté le 01-02-2006 à 17:11:27
NullDragon a écrit : Désolé les mecs, mais je ne saisi toujours pas la raison du Pile unePile |
Je tente
En gros, il y a deux concepts à piger ici.
Le premier, c'est le concept d'Interface.
Une interface, c'est un contrat, ça dit "un objet avec (implémentant) cette interface doit avoir telle, telle et telle propriétés".
C'est une boite noire avec des manettes précises à la surface.
Mais c'est une boite vide, il n'y a rien derrière les manettes et les boutons, c'est juste un exemple si tu veux.
Ensuite, on implémente l'interface. Ca veut dire qu'on crée de "vrais" objets qui vont respecter les propriétés définies par l'interface.
Ca veut dire qu'ils auront au moins les mêmes manettes et les mêmes boutons que ton exemple (mais peuvent en avoir d'autres en plus).
Maintenant, on veut utiliser notre interface, parce qu'on a besoin des manettes et des boutons. L'interface en elle même ne fait rien du tout (c'est un exemple), donc on doit utiliser une impléméntation de l'interface, c'est à dire un truc qui marche, ici la PileArrayList.
Simplement, tes opérateurs de machinerie (ton code) n'en ont rien à foutre des boutons et des manettes en plus de celles de ton interface. Pire, ça les trouble, ils ne comprennent pas pourquoi la boite que tu leur file (PileArrayList) n'est pas la même que l'exemple sur lequel ils ont appris (Pile).
Alors tu planques ta "vraie" boite derrière la boite-example
C'est pour ça que tu déclares que tu files la boite example
Code :
|
Mais que derrière les manettes et bouton de l'exemple tu mets une vraie boite qui fait quelque chose
Code :
|
De plus ça a un autre gros avantage: imaginons qu'un joyeux jour de Juin tu as un commercial qui arrive et qui te dis "on a une boite qui fait le même boulot que la votre, mais elle est plus petite, plus légère, elle consomme moins et en plus elle fait le café", appelons la PileStack.
Classiquement, tu serais obligé de renvoyer tous tes ouvriers en formation (éditer tout ton code) et de leur apprendre à se servir de la PileStack (remplacer toutes les occurences de Pile ou PileArrayList par PileStack), puisqu'actuellement ils savent juste se servir de la Pile et que la PileStack a des boutons et des manettes différents. Ca coute des sous, beaucoup, et ça trouble tes ouvriers qui risquent de se mélanger entre la Pile et la PileStack, et de faire des conneries.
Maintenant si le commercial rajoute à son speech "en plus elle implémente l'interface Pile", alors allelluia!
T'as rien à dire à tes ouvriers, tu remplace juste
Code :
|
par
Code :
|
Tes ouvriers, eux, auront toujours leur boite-exemple Pile avec les manettes et les boutons qu'ils connaissent, que derrière la boite ait changé, fasse le café et consomme moins ils s'en foutent, non seulement ça ne les intéresse pas mais ça n'a aucune influence sur leur boulot, donc ils n'ont pas à être au courant.
Le principe des interfaces c'est ça: éviter que les gens ne soient au courant de choses qui ne les interesse pas, et qu'ils n'ont pas à savoir.
Ca permet de découpler le code de l'implémentation, et d'être ensuite beaucoup plus flexible dans l'implémentation et (par la suite) dans les modifications de l'implémentation en faisant bosser ton code sur une abstraction d'objet qui n'existe pas mais qui peut servir de "boite noire" (e.g. d'interface, d'ou le nom) entre ton code à toi et le code de l'objet.
Voila, en espérant que c'était à peu près compréhensible.
(PS: après, l'utilisation d'interfaces a des avantages et des inconvénients bien sûr, mais bon c'est un autre problème, tu auras le temps de piger les inconvénients quand tu auras compris les avantages)
Marsh Posté le 01-02-2006 à 19:55:14
http://www.google.com/search?hl=en [...] tnG=Search
http://www.google.com/search?hl=en [...] tnG=Search
(et à moins que le sujet ait changé en cours de route, faudrait voir a rectifier le titre du topic)
Marsh Posté le 01-02-2006 à 20:15:20
@Masklinn
Chapeau , tu fait de la formation maintenant ? Ou le prochain argument sera "Mais en ruby c'est mieux"
Marsh Posté le 01-02-2006 à 21:34:59
esox_ch a écrit : Chapeau , tu fait de la formation maintenant ? |
Parait que quand j'me lance chuis vachement pédagogue, mais c'est ma mère qui dit ça donc faut pas la croire
esox_ch a écrit : Ou le prochain argument sera "Mais en ruby c'est mieux" |
Bah non, chuis pas vil au point de confuser le pauvre petit
Spoiler : et en ruby -- ou en python -- tu te fais pas chier avec des interface ou du typage statique, donc l'affaire est classée |
Marsh Posté le 01-02-2006 à 21:36:45
masklinn a écrit :
|
Spoiler : tu te fais pas chier non plus avec de la qualité, des perfs ou des outils de refactoring corrects non plus remarque. |
Marsh Posté le 01-02-2006 à 21:41:21
nraynaud a écrit :
|
Spoiler : Avec les perfs non, les outils de refactoring en Ruby je sais pas mais en Py il y a le Bicycle Repair Man, et avec la qualité je suis franchement pas d'accord, c'est du même niveau argumentatif que "java c'est lent" |
Marsh Posté le 01-02-2006 à 21:42:54
masklinn a écrit :
|
Spoiler : C'est vrai que la théorie des types ça sert qu'à occuper les chercheurs et pas du tout à rattraper tes conneries. |
Marsh Posté le 01-02-2006 à 21:46:09
nraynaud a écrit :
|
Spoiler : J'vois franchement pas ce que ça vient foutre là |
Marsh Posté le 01-02-2006 à 15:53:36
Salut, dans mon cours à l'université, le prof nous a montré la générécité et les interfaces, malgré ses explications il y a certains points que je n'arrive pas à comprendre.
Pourquoi doit-on écrire:
Pile unePile;
unePile = new PileArrayList<String>;
Au lieu de:
PileArrayList unePile;
unePile = new PileArrayList<String>;