Visualizzazione dei risultati da 1 a 1 su 1
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361

    Usare newInstance di Constructor per classe generica

    Ciao, parto subito a spiegare la mia situazione perché non sapevo bene come riassumere

    Nella mia applicazione ho un grande insieme di frames "figli" di una classe che estende JFrame.
    Ora vorrei aggiungere ad ognuno di questi frame un pulsantino che apra una finestra di personalizzazione dell'interfaccia, una volta effettuate le modifiche il frame deve "ricaricarsi" per poter visualizzare le modifiche.

    Quindi quello che avevo pensato io era di gestire questo comportamento dalla classe madre: il pulsantino con relativo listener viene aggiunto nel costruttore della madre, sempre nella madre aggiungo il metodo recreateFrame() che verrà richiamato dal listener, e in cui effettuo il dispose della vecchia finestra e poi costruisco una nuova istanza.
    Ovviamente nella madre non conosco a prescindere quale figlia dovrà ricreare, quindi avevo pensato a tre modi diversi per impostare il metodo recreateFrame() :

    - controllo nella classe madre il tipo di istanza con una catena di instanceof (oppure getClass) e di caso in caso richiamo il costruttore della figlia appropriato.
    - estendo il metodo recreateFrame() in tutte le sottoclassi (da un punto di vista logico mi pare il metodo più pulito)
    - nel metodo recreateFrame() della madre controllo il tipo di classe della figlia e ne richiamo il costruttore in modo automatico.

    Quest' ultima alternativa mi affascinava particolarmente perché non avevo mai fatto qualcosa del genere, quindi ho provato ad implementarla.

    Ho visto che Class ha il metodo getDefaultConstructors() che restituisce un array dei costruttori dichiarati nella stessa classe, quindi nel mio caso posso "avere" il costruttore richiesto semplicemente prendendo il primo elemento dell'array.

    Poi da Constructor posso invocare il costruttore con il metodo newInstance(Object... initArgs), ma a questo punto devo avere disponibili per la madre tutti i parametri da passare alla classe figlia.

    Ho risolto la cosa definendo nella classe madre il vettore di Object defaultParameters, e popolandolo nel costruttore di ogni classe figlia.
    Posto il codice di un esempietto che mi sono fatto:

    codice:
    import java.awt.*;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.awt.event.*;
    import javax.swing.*;
    public class Mother extends JFrame
    {
        Object[] defaultParameters;
        public Mother(String title)
        {
            super(title);
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            JButton recreate=new JButton("Recreate instance");
            recreate.addActionListener(new Listener(this));
            getContentPane().add(recreate);
            setSize(new Dimension(300,100));
            setLocation(this instanceof FirstDaughter?300:(this instanceof SecondDaughter? 600:900),500);
        }
        public void recreateInstance()
        {
            Class clazz = this.getClass();
            try{
                Constructor constructor=clazz.getDeclaredConstructors()[0];
                dispose();
                ((Mother)constructor.newInstance(defaultParameters)).setVisible(true);
            }
            catch(Exception ex){
                System.out.print("\nCan't instantiate");
            }
        }
        public static void main(String[] args)
        {
            SwingUtilities.invokeLater(new Runnable(){
                public void run()
                {
                    new FirstDaughter(3).setVisible(true);
                    new SecondDaughter("DefaultValue",false).setVisible(true);
                    new ThirdDaughter().setVisible(true);
                }
            });
        }
    }
    class FirstDaughter extends Mother
    {
        public FirstDaughter(int intParameter)
        {
            super("First Daughter");
            defaultParameters=new Object[]{intParameter};
            getContentPane().add(new JLabel("Il mio argomento e' : "+intParameter),BorderLayout.SOUTH);
        }
    }
    class SecondDaughter extends Mother
    {
        public SecondDaughter(String stringParameter,boolean booleanParameter)
        {
            super("Second Daughter");
            defaultParameters=new Object[]{stringParameter,booleanParameter};
            getContentPane().add(new JLabel("I miei argomenti sono "+stringParameter+" e "+booleanParameter),BorderLayout.SOUTH);
        }
    }
    class ThirdDaughter extends Mother
    {
        public ThirdDaughter()
        {
            super("Third Daughter");
        }
    }
    class Listener implements ActionListener
    {
        Mother mother;
        public Listener(Mother mum)
        {
            mother=mum;
        }
        public void actionPerformed(ActionEvent e){
            mother.recreateInstance();
        }
    }
    Volevo sapere a grandi linee se l'approccio implementato è sensato: immagino che questo genere di procedure vengano usati in contesti ben più complessi e che nel mio caso, dove tutto è noto e non devo importare parametri da file esterni o cose del genere, sia più logico ridefinire il metodo recreateFrame() in tutte le sottoclassi.

    Ma l'idea mi affascina molto, può comunque andare ed essere affinata ?
    Ultima modifica di Ansharja; 05-05-2016 a 14:56

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.