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

avec Java Discussion :

Le chaînage en Java


Sujet :

avec Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 197
    Par défaut Le chaînage en Java
    Bonjour
    j'ai une petite question sur le Java.
    J'ai une class ou je mets tout ce qui est générique et d'autre si c'est plus particulier. J'aimerais faire une sorte de chainage des méthodes et je ne sais pas comment faire à part tout séparer dans des class différente.

    Par exemple je démarre ma méthode principal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClassTest test = new ClassTest().methode_1(p);
    La je récup ma position:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Vector3d getPosition = test.getPosition();
    Le problème c'est que toute les autres méthodes dans la class ClassTest sont accessible et ça me gêne car getPosition() ne pourra rien renvoyer si la méthode methode_1() à pas été démarré.
    J'aimerais que quand je crée "ClassTest test = new ClassTest().methode_1(p);" que je puisse avoir accès aux méthodes qui fonctionnent qu'avec celle si et donc pouvoir faire: "Vector3d test = new ClassTest().methode_1(p).getPosition();".
    On peut remédier à ça ?

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 766
    Par défaut
    Un code proche de celui-ci en utilisant les interfaces (je n'arrive pas à compiler et il faut mettre l'interface dans son propre fichier ). Ensuite en Java, les interfaces ont évolué et on peut mettre du code dedans (si je ne dis pas de bêtises)

    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    import javax.vecmath.Vector3d;
     
     
    interface Position
    {
        public Vector3d getPosition();
    }
     
     
    public class ClassTest implements Position
    {
        public Position method_1(double input_x, double input_y, double input_z) {
            x = input_x;
            y = input_y;
            z = input_z;
     
            return this;
        }
     
     
    //  main  
     
        public static void main(String[] args) {
            Position position = new ClassTest().method_1(0.0, 0.0, 0.0);
            Vector3d vector = position.getPosition();
     
            System.out.printf("Main - position: (%lf, %lf, %lf)\n", vector.x, vector.y, vector.z);
        }
     
     
    //  Interface Position
     
        private double x, y, z;
     
        public Vector3d getPosition() {
            return new Vector3d(x, y, z);
        }
    }

  3. #3
    Membre expérimenté
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2013
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Israël

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 131
    Par défaut
    Salut,

    Est ce que tu ne decrirai pas la l'implementation du Design Pattern Builder : https://dzone.com/articles/design-pa...uilder-pattern ?

    Exemple pris du lien ci dessus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    BankAccount account = new BankAccount.Builder(1234L)
                .withOwner("Marge")
                .atBranch("Springfield")
                .openingBalance(100)
                .atRate(2.5)
                .build();

  4. #4
    Membre confirmé
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 197
    Par défaut
    Un ami ma proposé un code qui fait ce que je veux. En gros j'ai toujours ma méthode principal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClassTest test = new ClassTest().methode_1(p);
    Sauf que dans cette méthode principal je démarre une seconde class ou j'ai les méthodes lié. Donc c'est isolé et c'est ce que je voulais. Après on va me dire pourquoi ne pas la démarrer directement ? car je veux une class principal ou tout est lié sans devoir démarrer une class différente en fonction de ce que j'ai besoin.
    Ce qui fait que ce code fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Vector3d test = new ClassTest().methode_1(p).getPosition();
    Après je sais pas si c'est vraiment une bonne façon de faire.

  5. #5
    Membre confirmé
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 197
    Par défaut
    Pour vous c'est bien ?

  6. #6
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    Citation Envoyé par foetus Voir le message
    Ensuite en Java, les interfaces ont évolué et on peut mettre du code dedans (si je ne dis pas de bêtises)
    Tu ne dis pas vraiment de bêtises, mais attention à ne pas abuser du mécanisme d'implémentation par défaut: à l'origine, ça sert *surtout* à fournir la rétrocompatibilité aux clients de l'interface lorsque cette dernière évolue. Pas à filer de l'implém à tout va. Attention aux risques de comportements inattendus (diamond inheritance, etc...). On ne devrait jamais écrire de méthode "default" si on n'est pas dans un cadre de l'évolution d'une API publiée.

    Sinon Lprof, pas de souci tant que correspond à ton besoin. Ensuite tu parles d'une classe liée qui n'est pas visible de prime abord. C'est très bien et ça s'appelle de l'encapsulation (cacher les détails non pertinents du fonctionnement d'une classe à un consommateur). ça te permettra, un jour, de changer ta classe liée sans impacter personne. So far so good

  7. #7
    Membre confirmé
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 197
    Par défaut
    C'est surtout que c'est bien car ça isole mes méthodes alors qu'avant on y avait accès n'importe comment, mais ça me donne l'impression que c'est pas optimisé une méthode qui démarre une autre class et je me dis que dans ce qu'a autant démarré la fameuse class directement même si c'est ce que je veux éviter^^.

    On peut faire en sorte que la seconde class soit exécutable seulement par une class particulière et non directement ?

  8. #8
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    Bah tu sais, créer quelques petits objets simples en trop c'est peu couteux. Si en plus ça se justifie pour des raisons d'architecture pas d'inquiétude. C'est quand tu commences à créer inutilement des centaines d'objets que les soucis commencent (ex. concaténation de strings dans une boucle).

    Citation Envoyé par Lprofessionnelle Voir le message
    On peut faire en sorte que la seconde class soit exécutable seulement par une class particulière et non directement ?
    On peut jouer avec la visibilité de la class (public ou pas) et les structures de packages. Mais ça a ses limites

  9. #9
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Juste deux petites remarques, pas forcément liés au sujet initial.

    Citation Envoyé par Pill_S Voir le message
    Attention aux risques de comportements inattendus (diamond inheritance, etc...).
    Les interfaces par défaut ne peuvent pas gérer d'état, et en cela ça limite les problèmes lié à l'héritage multiples.

    Citation Envoyé par Pill_S Voir le message
    On ne devrait jamais écrire de méthode "default" si on n'est pas dans un cadre de l'évolution d'une API publiée.
    Je ne suis pas trop d'accord sur ce point.
    Bien sûr le fait de pouvoir enrichir une interface est un des gros avantages des méthodes par défaut, mais il n'est pas interdit d'aller plus loin.
    Je trouve au contraire que cela permet un niveau d'abstraction supplémentaire à mi-chemin entre l'interface pure et la classe abstraite.
    Cela permet d'avoir des contrats d'implémentation simple tout en proposant une API riche.

    D'ailleurs l'API des Collections aurait gagné en richesse si elle avait pu utiliser les méthodes par défaut lors de sa création : la majorité des AbstractCollection, AbstractList... auraient pu être intégré directement au sein de l'interface via des méthodes par défaut...

  10. #10
    Membre confirmé
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 197
    Par défaut
    adiGuba tu dis un peut du chinois pour moi.


    Dernière petite chose: si je veux créer un second niveau je refais pareil ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClassTest test = new ClassTest().methode_1(p).methode_2().methode_3()
    Exemple: je voulais faire un truck qui donnait soit les coins d'un carré au sol soit si on choisit le mode volume ça donne les coins de notre cube et donc encore une fois séparer les méthodes.

    Quand je code je fais souvent ces choses la avec certaines api par exemple et moi quand je veux le faire je trouve pas de tuto qui explique sauf avec la façon qu'on ma montré

  11. #11
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Lprofessionnelle Voir le message
    adiGuba tu dis un peut du chinois pour moi.
    Désolé...

    Pour faire simple avant Java 8 on avait 3 "niveaux" pour nos types :
    • Les interfaces, qui permettent de définir les différentes méthodes sans implémentations (tu as juste le nom de la méthode et ses paramètres).
    • Les classes abstraites, qui permettent en plus de définir des attributs et d'implémenter le code des méthodes, même partiellement (les méthodes abstraites devront être implémentée par une classe fille).
    • Enfin les classes concrètes, qui peuvent hérité d'une classe abstraite ou implémenter des interfaces (elles doivent alors implémenter toutes les méthodes "manquantes")



    Désormais on a aussi la possibilité d'utiliser des interfaces avec des méthodes par défaut, à mi-chemin entre les interfaces "pures" et les classes abstraites.
    Elles sont restreintes dans leurs possibilités (car tu ne peux pas y définir ni manipuler des attributs), mais bien pratique car elles permettent de définir des comportements induits.

    Cela permet d'enrichir l'API sans obliger à implémenter ces méthodes (même si cela reste possible).


    Exemple : tu veux définir un type Liste avec des méthodes add() et addAll().
    Avant Java 8 ton interface aurait eu cette tête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public interface List<V> {
        public void add(V value);
     
        public void addAll(Iterable<V> values); // Collection d'objets
     
        public void addAll(V...values); // Tableau d'objets
    }
    Problème : chaque classe qui implémente l'interface devra implémenter toutes les méthodes.
    Cela a souvent limité les interfaces.
    Afin de ne pas les rendre trop contraignantes, les interfaces proposaient un nombre réduit de méthode, avec une classe utilitaires à coté pour étendre les possibilités.


    Mais désormais avec Java 8 tu peux inclure tout çà directement 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
    public interface List<V> {
        public void add(V value);
     
        public default void addAll(Iterable<V> values) {
            for (V value : values) {
                this.add(value);
            }
        }
     
        public default void addAll(V...values) {
            this.addAll(Arrays.asList(values));
        }
     
    }
    Pour implémenter cette interface tu n'es obligé que d’implémenter add(V), et les méthodes addAll() fonctionneront quand même.


    Citation Envoyé par foetus Voir le message
    Effectivement la notion de "problème du diamant" et d'héritage multiple n'existe guère en Java (qu'on peut avoir justement avec les méthodes par défaut des interfaces), et ce sont des notions un peu difficile à appréhender.
    Mais la notion d'interface et de classe abstraite, c'est quand même l'identité du Java
    Justement du fait de l'absence d'état dans les interfaces ces problèmes sont bien moins fréquent.

    Le seul problème en Java c'est quand tu implémentes deux (ou plusieurs) interfaces non-liées qui définissent une implémentation par défaut pour la même méthode, que ce soit en losange ou pas.
    Et le problème disparait dès que tu as une implémentation définie dans une classe...

    Citation Envoyé par foetus Voir le message
    En C++, les méthodes par défaut ont quand même un gros défaut : on peut oublier ce comportement par défaut et/ ou ce comportement ne correspond pas aux classes filles. Et sa modification peut poser des problèmes.
    Je ne connais pas le fonctionnement des méthodes par défaut en C++...
    Citation Envoyé par foetus Voir le message
    J'ai regardé en Java, et le plus gros inconvenient c'est le fait qu'une interface fille masque le comportement par défaut en le redéfinissant.
    En quoi est-ce un inconvénient ? C'est plutôt logique même.
    Une classe fille est plus spécifique et on peut considérer qu'elle est plus à même de proposer une meilleure implémentation...

  12. #12
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 766
    Par défaut
    Citation Envoyé par Lprofessionnelle Voir le message
    adiGuba tu dis un peut du chinois pour moi.
    Effectivement la notion de "problème du diamant" et d'héritage multiple n'existe guère en Java (qu'on peut avoir justement avec les méthodes par défaut des interfaces), et ce sont des notions un peu difficile à appréhender.
    Mais la notion d'interface et de classe abstraite, c'est quand même l'identité du Java


    Citation Envoyé par adiGuba Voir le message
    Je ne suis pas trop d'accord sur ce point.
    Bien sûr le fait de pouvoir enrichir une interface est un des gros avantages des méthodes par défaut, mais il n'est pas interdit d'aller plus loin.
    En C++, les méthodes par défaut ont quand même un gros défaut : on peut oublier ce comportement par défaut et/ ou ce comportement ne correspond pas aux classes filles. Et sa modification peut poser des problèmes.
    J'ai regardé en Java, et le plus gros inconvenient c'est le fait qu'une interface fille masque le comportement par défaut en le redéfinissant.


    Citation Envoyé par Lprofessionnelle Voir le message
    Exemple: je voulais faire un truck qui donnait soit les coins d'un carré au sol soit si on choisit le mode volume ça donne les coins de notre cube et donc encore une fois séparer les méthodes.
    J'ai l'impression que tu te mélanges les pinceaux Tu essaies de faire une usine (<- patron de conception) avec des variables automatiques et avec la syntaxe du patron de conception StringBuilder ... mais pas pour la création (parce que le rôle d'une usine et du StringBuilder, comme leur nom l'indique, c'est pour la création)

    Tiens, non testé, peut-être pas en Java pur, et niveau performances et maintenance, cela peut être mauvais :
    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    class InterfaceException extends Exception
    {
        public enum t_method {
            interface1_method_1,
            interface1_method_2,
            interface1_method_3,
            interface2_method_1,
            interface2_method_2	
        };
     
     
        InterfaceException(t_method input_method) {
            method = input_method;
        }
     
     
        public void display(String start_str) {
            String method_str;
     
            switch(method) {
            case interface1_method_1: method_str = "interface1_method_1"; break;
            case interface1_method_2: method_str = "interface1_method_2"; break;
            case interface1_method_3: method_str = "interface1_method_3"; break;
            case interface2_method_1: method_str = "interface2_method_1"; break;
            case interface2_method_2: method_str = "interface2_method_2"; break;
            default: method_str = "unkown"; break;
            }
     
            System.out.println(start_str + "\n\tmessage: Wrong Interface - cannot use this method " + method_str);
        }
     
     
    //  Attribute  
     
        private t_method method;
    }
     
     
     
    public class ClassTest
    {
        public enum t_interface {
            interface_1,
            interface_2	
        };
     
     
        ClassTest() {
            interf = t_interface.interface_1;
        }
     
     
        ClassTest set_interface(t_interface new_interface) {
            interf = new_interface;
     
            return this;
        }
     
     
        public ClassTest interface1_method_1() throws InterfaceException {
            if (interf != t_interface.interface_1) { throw new InterfaceException(InterfaceException.t_method.interface1_method_1); }
     
            System.out.println("interface1 - method_1");
     
            return this;
        }
     
     
        public ClassTest interface1_method_2() throws InterfaceException {
            if (interf != t_interface.interface_1) { throw new InterfaceException(InterfaceException.t_method.interface1_method_2); }
     
            System.out.println("interface1 - method_2");
     
            return this;
        }
     
     
        public ClassTest interface1_method_3() throws InterfaceException {
            if (interf != t_interface.interface_1) { throw new InterfaceException(InterfaceException.t_method.interface1_method_3); }
     
            System.out.println("interface1 - method_3");
     
            return this;
        }
     
     
        public ClassTest interface2_method_1() throws InterfaceException {
            if (interf != t_interface.interface_2) { throw new InterfaceException(InterfaceException.t_method.interface2_method_1); }
     
            System.out.println("interface2 - method_1");
     
            return this;
        }
     
     
        public ClassTest interface2_method_2() throws InterfaceException {
            if (interf != t_interface.interface_2) { throw new InterfaceException(InterfaceException.t_method.interface2_method_2); }
     
            System.out.println("interface2 - method_2");
     
            return this;
        }
     
     
    //  main  
     
        public static void main(String[] args) {
            ClassTest test = new ClassTest();
     
            try {
                test.set_interface(t_interface.interface_1).interface1_method_2().interface1_method_1().set_interface(t_interface.interface_2).interface2_method_2();
            } catch(InterfaceException e) {
                e.display("Main - Exception: test 1");
            }
     
            try {
                test.set_interface(t_interface.interface_1).interface1_method_3().set_interface(t_interface.interface_2).interface2_method_1().interface1_method_2();
            } catch(InterfaceException e) {
                e.display("Main - Exception: test 2");
            }
        }
     
     
    //  Attribute  
     
        private t_interface interf;
    }

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