IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Listes et interfaces


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut Listes et interfaces
    Salut à toutes et à tous

    En pleine création d'un petit logiciel de gestion de comptes, je suis confronté à un problème qui me parait un peu stupide... Soit je m'y prends mal, soit java peut être amélioré.

    Situons le contexte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    package org.aspyct.mpc.accounting;
     
    public interface Movement {
       ...
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    package org.aspyct.mpc.accounting;
     
    class MovementImpl implements Movement {
        ...
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package org.aspyct.mpc.accounting;
     
    class AccountingImpl implements Accounting {
        private List<MovementImpl> movements;
     
        public Iterator<Movement> movements() {
            // La ligne suivante plante lamentablement, me disant "Incompatible types"
            return Collections.unmodifiableList(movements).iterator();
     
            // Pourtant, la suivante fonctionne, alors que c'est, en soi, la même histoire
            return new ArrayList<Movement>(movements).iterator();
        }
    }
    Alors... est-ce que je m'y prends comme un pied avec mes interfaces et mes listes, ou est-ce que vous trouvez aussi que c'est un comportement bizarre ?

    Je conçois bien que la première ligne retournerait quelque chose du type Iterator<MovementImpl>, mais puisque de MovementImpl à Movement on effectue une généralisation, ça devrait passer quand même...

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    Si j'étais toi, je déclarerais une List<Movement> plutôt qu'une List<MovementImpl>. As-tu vraiment besoin de savoir que ce que tu stockes sont des MovementImpl ? N'as-tu pas besoin uniquement des méthodes déclarées dans Movement ?

  3. #3
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Oui, c'est de fait mieux une List<Movement>, mais c'est presque une chance: dans le cas des Account, j'ai bel et bien besoin des AccountImpl pour faire du travail sans cast à tout bout de champ...
    J'ai été induit en erreur par cette dernière nécessité, et c'est dors et déjà corrigé.

    Il n'empeche que le fait exposé plus haut est un peu étrange, non ?

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    Non : par défaut les génériques prennent des types exacts. Pour dire qu'on veut un type qui peut implémenter, il faut utiliser les wildcards.

    Je préfère éviter de raconter des bêtises. Aussi, je te redirige vers ce tutoriel à ce sujet.

  5. #5
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Merci pour ce lien ! Mon problème est résolu.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public Iterator<? extends Movement> movements() {}
    Résolu, oui, mais nettement moins naturel, aussi.
    Je ne doute pas du fait qu'il y ait une bonne raison d'avoir forcé les développeurs à faire ça, mais je serais intéressé de connaître cette raison. A l'heure actuelle, elle m'échappe complètement.

    Edit: Non, en fait je me suis planté et j'ai fait n'importe quoi. La solution ci-dessus ne fonctionne pas plus que la première.
    Ceci, par contre, fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class AccountingImpl {
        private Map<String, AccountImpl> accounts;
     
        public Iterator<Account> accounts() {
            return Collections.unmodifiableCollection(
                    (Collection<? extends Account>) accounts.values()).iterator();
        }
    }
    C'est horrible, c'est atroce, mais ça fonctionne et c'est correct.

    Quelqu'un pourrait-il m'expliquer la différence entre les deux types suivants ? Pour moi, c'est exactement pareil, sauf que la version avec le "?" est juste plus sympa niveau compilation...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    List<? extends Account> accounts;
    List<Account> accounts;

    Peut-être vous demandez-vous pourquoi je tiens tant à stocker des AccountImpl et offrir des Account. Car de plus, c'est peut-être là que se situe ma réelle erreur, et vous sauriez m'aider à la corriger...
    Première chose, je voudrais n'exposer que des interfaces aux utilisateurs de mes packages.
    Ensuite, il existe deux méthodes sur ma classe AccountImpl dont je désire faire usage dans le package sans pour autant les divulger dans l'interface.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package org.aspyct.mpc.accounting
    public interface Account {
        String getName();
        BigDecimal getMoney();
        boolean isMine();
        void setMine(boolean);
    }
     
     
    package org.aspyct.mpc.accounting
    class AccountImpl implements Account {
        // Méthodes implémentées: getName, getMoney...
     
        // Méthodes à accessibilité package
        void deposit(BigDecimal amount) {}
        void withdraw(BigDecimal amount) {}
    }
    Il y a peut-être une meilleure méthode pour faire ce que je voudrais... Et peut-être connaissez-vous la solution.

  6. #6
    Membre Expert

    Homme Profil pro
    SDE
    Inscrit en
    Août 2007
    Messages
    2 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : SDE

    Informations forums :
    Inscription : Août 2007
    Messages : 2 013
    Par défaut
    Bonjour,

    La différence entre List<MyType> et List<? extends MyType> est qu'avec la première version, uniquement des instance de type List<MyType> pouront être affecté à une référence de type List<MyType> (par exemple ArrayList<MyType> sera valide mais pas ArrayList<MySubType>, et ceci même si MySubType extends MyType).

    en ce qui concerne la seconde version, elle permet de faire ce qui est interdit dans le premier cas).

    Ici ce qui pourait résoudre ton problème, c'est d'avoir deux interfaces :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public interface Account {
        String getName();
        BigDecimal getMoney();
        boolean isMine();
        void setMine(boolean);
    }
     
    public interface AccountFull extends  Account{
        void deposit(BigDecimal amount);
        void withdraw(BigDecimal amount);
    }
     
    public class AccountFullImpl implements AccountFull {
        // toutes les implémentations.
    }
    Tu as donc un type générique qui fédère tous les types de compte. Ensuite tu as une autre interface qui te permet d'abstraire ton implémentation pour la maintenance du programme. Puis l'implémentation même.

  7. #7
    Membre Expert
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Par défaut
    Citation Envoyé par Antoine_935 Voir le message
    Je conçois bien que la première ligne retournerait quelque chose du type Iterator<MovementImpl>, mais puisque de MovementImpl à Movement on effectue une généralisation, ça devrait passer quand même...
    La raison est simple : si tu renvoies une liste de Movement, tu peux dans du code rajouter dans cette liste des choses qui hériteraient de Movement, mais qui ne seraient pas du tout des MovementImpl.
    Or, ta liste peut être utilisée ailleurs en tant que liste de MovementImpl, et donc en extraire des objets et y appliquer des méthodes spécifiques à MovementImpl, ce qui déclencherait des erreurs au Runtime.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 10
    Dernier message: 07/05/2012, 00h03
  2. List et Interface
    Par farid_974 dans le forum C#
    Réponses: 3
    Dernier message: 19/08/2009, 13h51
  3. propriété retournant une liste d'interface
    Par Invité dans le forum C#
    Réponses: 17
    Dernier message: 02/07/2009, 18h44
  4. ASIO liste d'interfaces
    Par Ferllings dans le forum Boost
    Réponses: 6
    Dernier message: 06/01/2009, 11h56
  5. Liste des interfaces
    Par NiamorH dans le forum C#
    Réponses: 2
    Dernier message: 22/10/2008, 17h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo