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 :

déclaration sans "new"


Sujet :

Langage Java

  1. #1
    Candidat au Club
    Inscrit en
    Juin 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 6
    Points : 3
    Points
    3
    Par défaut déclaration sans "new"
    Désolé de poser une question qui pourrait être stupide mais je n'arrive pas à comprendre ce concept :

    quand on déclare un objet de sa propre classe, on fait :
    MaClasse test = new MaClasse();

    mais quand on déclare un objet venant du framework alors on fait ceci :
    Sequencer testSeq = MidiSystem.getSequencer();

    pourquoi n'emploie-t-on pas le mot-clé "new" ? testSeq n'est-il pas crée dans le memory heap ?

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Le new est appelé en interne de la classe MidiSystem.
    On utilise ce genre de procédé dans les patterns factory ou singleton.
    Dans le cas du singleton, c'est pour éviter d'avoir plusieurs instances de la même classe.

  3. #3
    Candidat au Club
    Inscrit en
    Juin 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    merci !

    Si je regarde le tutoriel sur les design pattern dans la section factory, on a ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class CanvasFactory 
    {
           public Point getPoint( int x, int y ) 
           {
                 return new PointImpl( x, y );
            }
    }
    Si on map cela avec mon exemple du MidiSystem, peut-on dire que :
    CanvasFactory correspond à MidiSystem
    getPoint correspond à getSequencer
    ?

  4. #4
    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
    Points : 3 675
    Points
    3 675
    Par défaut
    en gros oui, mais c'est un peu plus compliqué.

    dans le cas de factory, le but est de séparer la création des objets du reste du code. Pourquoi? parce que créer un objet avec "new" c'est super rigide, impossible de changer le type de l'objet: "new" impose que l'on connaisse la classe qui sera utilisée.

    En utilisant factory, on délègue cette tâche à un autre agent (la "factory"), et comme cela c'est beaucoup plus facile de modifier la manière dont sont créés les objets: tu veux changer le mode de fonctionnement, bam tu créé une nouvelle factory, tu adaptes un peu le code qui permet de récupérer la factory, et c'est bon partout dans ton programme.

    Pour singleton, c'est plus simple: il y a plus ou moins la même notion que factory (déléguer l'instanciation à un agent), mais dans ce cas-là, on ne recherche pas la simplicité de changement, mais la garantie de n'avoir qu'une seule instance d'une classe partout dans le programme.

    On reconnait très facilement le pattern factory dans un programme java: le nom de la classe se termine presque toujours par "factory" (mais bon ça reste assez peu fréquent d'utiliser factory, c'est un pattern relativement lourd)
    "Le plug gros problème des citations trouvées sur internet, c'est qu'on ne peut jamais garantir leur authenticité"

    Confucius, 448 av. J-C

  5. #5
    Candidat au Club
    Inscrit en
    Juin 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Merci pour vos explications sur les design patterns.

    pour revenir au framework, pourquoi avoir choisi cette méthode :
    Sequencer testSeq = MidiSystem.getSequencer();

    plutôt que celle-ci :
    Sequencer testSeq = new Sequencer();
    le système me dit "cannot instanciate the type Sequencer" => Pourquoi ?

    Pourtant, dans ce cas, on est sûr de la classe que l'on veut créer.

  6. #6
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 526
    Points
    9 526
    Billets dans le blog
    1
    Par défaut
    Et bien, comme expliqué précédemment, c'est pour n'avoir qu'une seule instance de l'objet en mémoire...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    OButterlin > Non ce n'est pas un singleton : chaque appel renvoi bien un nouvel objet...


    Citation Envoyé par Antonio81 Voir le message
    Pourtant, dans ce cas, on est sûr de la classe que l'on veut créer.
    Justement tu ne sais pas quelle classe tu vas utiliser Sequencer est une interface et ne peut donc pas être instancié !

    La méthode getSequencer() se charge de trouver la bonne classe selon ta configuration : chez moi elle renvoi un objet non-standard de type com.sun.media.sound.RealTimeSequencer. Il est donc probable que cette méthode renvoie un autre objet sur une autre JVM (et en particulier sur une JVM autre que Sun)

    Il est possible que la classe renvoyée varie selon plusieurs critères (mais je connais trop peu cette API pour citer ces critères).

    a++

  8. #8
    Candidat au Club
    Inscrit en
    Juin 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Ok merci,

    concernant la déclaration suivante :

    Sequencer testSeq = MidiSystem.getSequencer();

    pour moi cela signifie qu'un objet MidiSystem existe déjà dans le programme.
    Or je ne voie nulle part une déclaration du genre :

    ClasseInconnue MidiSystem = new ClasseInconnue();

    Est-ce que cela est caché dans import javax.sound.midi.* ?


    Edit : merci pour ta réponse adiGuba mais pour la classe Sequencer, j'ai pris cela au hasard, je cherche juste à comprendre le concept car des appels de ce genre, j'en vois plein sur le net dès qu'on doit créer un objet du framework

  9. #9
    Membre chevronné
    Avatar de CheryBen
    Inscrit en
    Mai 2005
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 599
    Points : 2 197
    Points
    2 197
    Par défaut
    Citation Envoyé par Antonio81 Voir le message
    Sequencer testSeq = MidiSystem.getSequencer();
    Ici, MidiSystem n'est pas un nom de variable, mais bien le nom d'une classe. La méthode getSequencer est static, on peut donc l'appeler directement sans avoir instancié de MidiSystem.

    FAQ : Que signifie le mot-clé static ?

  10. #10
    Candidat au Club
    Inscrit en
    Juin 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Merci à vous,

    c'est maintenant beaucoup plus clair dans mon esprit !

  11. #11
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 526
    Points
    9 526
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    OButterlin > Non ce n'est pas un singleton : chaque appel renvoi bien un nouvel objet...
    Désolé, je n'avais pas réalisé qu'il s'agissait d'une classe "officielle"
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  12. #12
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    211
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 211
    Points : 102
    Points
    102
    Par défaut
    Citation Envoyé par Pill_S Voir le message
    en gros oui, mais c'est un peu plus compliqué.

    dans le cas de factory, le but est de séparer la création des objets du reste du code. Pourquoi? parce que créer un objet avec "new" c'est super rigide, impossible de changer le type de l'objet: "new" impose que l'on connaisse la classe qui sera utilisée.
    Pill_S, pourrais-tu s'il te plaît donner un exemple d'un cas où on ne connaîtrait pas la classe au moment de l'instanciation ?

    Est-ce là le seul avantage de la factory ?

  13. #13
    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
    Points : 3 675
    Points
    3 675
    Par défaut
    Bah typiquement, lorsque ton programme gère des plugins: tu ne sais pas à l'avance lesquels sont installés, donc tu ne peux pas les créer "statiquement".

    Et oui, le gros avantage de factory c'est vraiment d'éviter l'utilisation du mot clé "new", car le gros défaut de new, c'est qu'il faut connaitre précisément la classe ET le constructeur à invoquer lorsqu'on l'utilise (c'est vraiment très très rigide).

    Factory peut aussi être pratique pour garantir l'initialisation correcte d'objets, ou de graphes d'objets (structures d'objets se référençant les uns les autres), en permettant d'exécuter du code avant même l'appel des constructeurs (y'a des situations où les constructeurs ne devraient pas être invoqués sans que l'on soit certain qu'ils ne lèveront pas d'exception, factory permet de s'assurer de cela).

    Y'aurait encore des miliers de choses à dire sur factory, mais le mieux c'est de les découvrir soi-même
    "Le plug gros problème des citations trouvées sur internet, c'est qu'on ne peut jamais garantir leur authenticité"

    Confucius, 448 av. J-C

  14. #14
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    211
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 211
    Points : 102
    Points
    102
    Par défaut
    Un truc que je ne pige pas dans ce tuto .

    Ok dans le Main on ne spécifie pas qu'on veut instancier la classe A ou la classe B mais c'est dans la fabrique A et B qu'on le précise. Désolé de faire le boulet mais je pige pas l'intérêt. On doit quand même connaître le type de la classe avant de l'instancier là... non ?

  15. #15
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    L'intérêt est que le new est centralisé dans une classe.
    Si tu veux changer d'implémentation, il te suffit de faire les modifs seulement à cet endroit, et non pas à tous les new de ton projet.

  16. #16
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    211
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 211
    Points : 102
    Points
    102
    Par défaut
    Okay super

    Merci

  17. #17
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    211
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 211
    Points : 102
    Points
    102
    Par défaut
    Bon le temps que j'y suis et comme c'est une question assez triviale, il y a une question que je me pose par rapport à cet exemple. Je sais c'est la base du polymorphisme mais je ne comprend pas trop son intérêt.

    Quand on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Fabrique lFactoryA = new FabriqueA();
            Fabrique lFactoryB = new FabriqueB();
    Pourquoi ne pas mettre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    FabriqueA lFactoryA = new FabriqueA();
            FabriqueB lFactoryB = new FabriqueB();
    Est-ce par exemple pour pouvoir faire éventuellement un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Fabrique lFactoryA = new FabriqueB();
    par la suite ?

    Autre question qui peut paraître bête mais si je fais un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Fabrique lFactoryA = new FabriqueA();
    comment mon objet IFactoryA a-t-il accès aux méthodes définies dans la classe FabriqueA sachant qu'il a une référence de type Fabrique (qui ne connait pas les méthodes propres à sa classe fille, la classe FabriqueA) ?

    Je sais c'est des notions vraiment très basiques mais j'ai un peu de mal là ...

  18. #18
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par nicofromChina Voir le message
    Bon le temps que j'y suis et comme c'est une question assez triviale, il y a une question que je me pose par rapport à cet exemple. Je sais c'est la base du polymorphisme mais je ne comprend pas trop son intérêt.
    C'est le principe de l'abstraction des types.
    Dans l'exemple Fabrique est une classe abstraite qui définit en autre une méthode creerClasse() permettant de créer un objet de type AbstractClasse. Cette classe étant également abstraite...

    En fait l'intérêt est de coder quelque chose sans se soucier du type réel : il peut y avoir plusieurs implémentations différentes mais on continuera toujours à l'utiliser de la même manière.

    Si demain tu dois modifier ta fabrique et que tu as utilisé en dur FabriqueB, alors tu devras changer cela partout... alors que ce n'est pas le cas avec Fabrique.


    L'exemple le plus parlant est peut-être celui des collections. Prenons par exemple le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class MaClasse {
     
    	private final LinkedList<String> list;
     
    	public MaClasse(LinkedList<String> list) {
    		this.list = list;
    	}
     
    	public LinkedList<String> getList() {
    		return list;
    	}
     
    }
    Une simple classe qui utilise une LinkedList, que l'on retrouve dans le constructeur et en retour d'une méthode.

    Le problème de cette classe vient du fait que tu forces l'utilisation d'une LinkedList, alors qu'il existe plusieurs types de liste et qu'on pourrait avoir besoin d'un autre type.

    Si demain tu dois utiliser une ArrayList, tu devras soit dupliquer la classe, soit la modifier et la rendre incompatible avec le code existant.

    Maintenant, si dès le début tu avais fait abstraction du type réel et utiliser un type abstrait, tu n'aurais pas ce problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class MaClasse {
     
    	private final List<String> list;
     
    	public MaClasse(List<String> list) {
    		this.list = list;
    	}
     
    	public List<String> getList() {
    		return list;
    	}
     
    }
    On utilise désormais List, qui est une interface décrivant les méthodes de base d'une liste. Alors bien sûr il y a certaines méthodes spécifiques à ArrayList ou LinkedList qui ne sont pas défini dans List, mais leurs utilité est moindre car très spécifique (et dans ce cas là on ne pourrait pas faire de code générique).



    Bref en utilisant un type abstrait, on conserve la possibilité de changer facilement le type réel, et on améliore donc la généricité du code.

    Dans l'exemple on utilise une Fabrique pour créer des AbstractClasse, et à la rigueur on n'a pas besoin de savoir s'il s'agit d'une FabriqueA qui créera des ClasseA ou une FabriqueB qui créera des ClasseB...



    Citation Envoyé par nicofromChina Voir le message
    Autre question qui peut paraître bête mais si je fais un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Fabrique lFactoryA = new FabriqueA();
    comment mon objet IFactoryA a-t-il accès aux méthodes définies dans la classe FabriqueA sachant qu'il a une référence de type Fabrique (qui ne connait pas les méthodes propres à sa classe fille, la classe FabriqueA) ?
    Tu as accès à toutes les méthodes définies dans le type de la référence. Donc ici tu peux appeler les méthodes définies dans la classe abstraite Fabrique (et les méthodes des classes parentes dont Object).

    Par contre en Java par défaut toutes les méthodes sont "virtuelles". C'est à dire qu'à l'exécution la JVM va vérifier le type réel de l'objet, et appeler la méthode correspondante. Ainsi lorsque tu fais ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Fabrique lFactory = new ????();
     
    AbstractClasse c = lFactory.creerClasse();
    On appelera la méthode creerClasse() sur un type Fabrique, mais à l'exécution cela dépendra du type réel indique dans les "????"...



    a++

  19. #19
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    211
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 211
    Points : 102
    Points
    102
    Par défaut
    EXCELLENT ! Mille mercis !

    Ça me débloque sur pas mal de truc, là j'ai bien pigé

    Sacrée JVM

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

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