[Risolto] Problema su oggetti

di il
13 risposte

[Risolto] Problema su oggetti

Ho la seguente problematica. Vorrei che Il metodo getInteractions potesse eseguire le stesse operazioni su liste di oggetti diversi a seconda del valore della variabile typo. Com'e' scritto ora non funziona perche' devo inizializzare la variabile ih con non so cosa per poterla poi assegnare alla lista di oggetti che mi interessa.
Stessa cosa il ciclo for che per ora cicla solo su un tipo di oggetto, quando invece dovrebbe ciclare sul tipo definito dalla condizione della variabile typo

C'e' un modo per poterlo fare o devo scrivere un metodo per ciascun tipo?
  public Result getInteractions() {
        DynamicForm requestData = Form.form().bindFromRequest();
        Integer lig_id = Integer.parseInt(requestData.get("lig_id"));
        Integer typo = Integer.parseInt(requestData.get("typo"));
        if(typo == 1) {
            List<InteractionHbond> ih = ihbond.findByLigId(lig_id);
        } else {
            List<InteractionVdw> ih = ivwd.findByLigId(lig_id);
        }
        String data = "<table class=\"table table-bordered\">\n" +
                "                    <thead>\n" +
                "                        <th>Ligand Atom</th>\n" +
                "                        <th>Neighbour Atom</th>\n" +
                "                        <th>Distance (&Aring;)</th>\n" +
                "                    </thead>\n" +
                "                    <tbody>\n";

        for(InteractionHbond ib: ih) {
            for(Atom at: ib.getAtoms()) {
                data += "<tr>";
                data += "<td>" + at.getLig_atom_str() + "</td>";
                data += "<td>" + at.getNeigh_atom_str() + "</td>";
                data += "<td>" + at.getDistance().toString() + "</td>";
                data += "</tr>";
            }
        }

        data += "                    </tbody>\n" +
                "                </table>";
        return ok(data);
    }
}

13 Risposte

  • Re: [Risolto] Problema su oggetti

    Ciao Morellik,
    Non so se ho capito bene, però se vuoi sapere il tipo di oggetto potresti usare "instanceof".
  • Re: [Risolto] Problema su oggetti

    Folle Calzolaio ha scritto:


    Ciao Morellik,
    Non so se ho capito bene, però se vuoi sapere il tipo di oggetto potresti usare "instanceof".
    Purtroppo il problema non e' questo. Vorrei creare un metodo che crei una lista di oggetti X e che cicli su tali oggetti dato che lo stesso metodo lo dovrei far girare su oggetti differenti ma con le stesse caratteristiche. Invece di creare un metodo per ogni oggetto o comunque duplicare del codice, chiedevo se esisteva una soluzione per poterlo rendere generico.

    Del metodo in oggetto (getInteractions), le uniche due righe che dovrebbero differire sono:
    List<InteractionHbond> ih = ihbond.findByLigId(lig_id);
    List<InteractionVdw> ih = ivdw.findByLigId(lig_id);
    e
    for (InteractionHbond ib : ih) {
    for (InteractionVdw ib : ih) {
  • Re: [Risolto] Problema su oggetti

    Potresti utilizzare una lista di Object e fare il cast oppure avendo le stesse caratteristiche potresti fare un oggetto tuo custom
  • Re: [Risolto] Problema su oggetti

    morellik ha scritto:


    Stessa cosa il ciclo for che per ora cicla solo su un tipo di oggetto, quando invece dovrebbe ciclare sul tipo definito dalla condizione della variabile typo

    C'e' un modo per poterlo fare o devo scrivere un metodo per ciascun tipo?
    Grosso modo sì ma si dovrebbero valutare delle cose (che io ovviamente non so). Che relazione c'è (se esiste) tra InteractionHbond e InteractionVdw? Ci saranno da gestire altri tipi?
    Cosa devi fare di "differente" da uno all'altro? Insomma, cosa puoi generalizzare e cosa invece dovresti specializzare?

    E comunque, comporre HTML "a mano" con le stringhe e oltretutto iniettando testi senza neanche considerare (se non è scontato che non serve) l'escaping dei caratteri speciali .... è da brividi ..
  • Re: [Risolto] Problema su oggetti

    andbin ha scritto:


    Grosso modo sì ma si dovrebbero valutare delle cose (che io ovviamente non so). Che relazione c'è (se esiste) tra InteractionHbond e InteractionVdw?
    Sono due oggetti attraverso cui si accede a dei documenti MongoDB. A parte il nome, hanno comportamenti e caratteristiche identiche.
    Ci saranno da gestire altri tipi?
    No.
    Cosa devi fare di "differente" da uno all'altro? Insomma, cosa puoi generalizzare e cosa invece dovresti specializzare?
    Come ho scritto sopra, una volta che ho inizializzato la list ih, le uniche due righe di codice che dovrebbero differire per essere generalizzate, sono:
    List<InteractionHbond> ih = ihbond.findByLigId(lig_id);
    List<InteractionVdw> ih = ivdw.findByLigId(lig_id);
    e
    for (InteractionHbond ib : ih) {
    for (InteractionVdw ib : ih) {
    E comunque, comporre HTML "a mano" con le stringhe e oltretutto iniettando testi senza neanche considerare (se non è scontato che non serve) l'escaping dei caratteri speciali .... è da brividi ..
    E' scontato che non serve (l'utente non interagisce in nessun modo) e comunque, al momento, e' solo per vedere la rapidita' di creazione di pagine complesse utilizzando MongoDB. In un secondo momento ritornero' un oggetto JSON da far processare a jquery.
  • Re: [Risolto] Problema su oggetti

    morellik ha scritto:


    Sono due oggetti attraverso cui si accede a dei documenti MongoDB. A parte il nome, hanno comportamenti e caratteristiche identiche.
    Li puoi "accomunare" con un super-tipo (classe base o interfaccia comune)? Ovviamente il super-tipo deve esporre tutte le informazioni che servono poi nel for.
    Se sì, è fatta, diventa banalissimo.

    morellik ha scritto:


    e' solo per vedere la rapidita' di creazione di pagine complesse utilizzando MongoDB. In un secondo momento ritornero' un oggetto JSON da far processare a jquery.
    Ok, no prob.
  • Re: [Risolto] Problema su oggetti

    andbin ha scritto:


    morellik ha scritto:


    Sono due oggetti attraverso cui si accede a dei documenti MongoDB. A parte il nome, hanno comportamenti e caratteristiche identiche.
    Li puoi "accomunare" con un super-tipo (classe base o interfaccia comune)? Ovviamente il super-tipo deve esporre tutte le informazioni che servono poi nel for.
    Se sì, è fatta, diventa banalissimo.
    Non so se si puo' fare. Al momento InteractionVdw estende InteractionHbond dato che entrambe hanno le stesse caratteristiche eccetto per quella che Morphia (driver per MongoDB) chiama Entity e che e' il documento a cui ogni oggetto fara' riferimento.
    @Entity(value = "interactions_vdw", noClassnameStored=true)
    public class InteractionVdw extends InteractionHbond {
    
    }
    Inoltre per fare le query c'e' un altro oggetto nel mezzo, una specia di DAO, per ogni documento, che viene "iniettato" nel controller
    
    @Inject private InteractionHbondRepository ihbond;
    @Inject private InteractionVdwRepository ivwd;
    , per cui in
    List<InteractionVdw> ih = ivwd.findByLigId(lig_id);

    InteractionVdw e' l'oggetto che rappresenta la struttura del documento e ivwd e' l'oggetto che permette di fare query.

    Quindi, sebbene i due oggetti InteractionVdw e InteractionHbond siano identici, fanno comunque riferimento a due entita' differenti.

    Non so se mi sono spiegato abbastanza da capire il problema, ma la vedo dura. Mi sa che alla fine mi tocchera' duplicare un po' di codice.
  • Re: [Risolto] Problema su oggetti

    morellik ha scritto:


    Al momento InteractionVdw estende InteractionHbond dato che entrambe hanno le stesse caratteristiche
    E allora sì (potevi dirlo prima ...) si può fare.
    List<? extends InteractionHbond> interactions;
    
    if (typo == 1) {
        interactions = ihbond.findByLigId(lig_id);
    } else {
        interactions = ivwd.findByLigId(lig_id);
    }
    
    
    for (InteractionHbond interaction : interactions) { ....... }
    Se tutti i metodi che ti servono NEL for sono quelli noti già in InteractionHbond, questo mostrato è quello che serve.
  • Re: [Risolto] Problema su oggetti

    andbin ha scritto:


    morellik ha scritto:


    Al momento InteractionVdw estende InteractionHbond dato che entrambe hanno le stesse caratteristiche
    E allora sì (potevi dirlo prima ...) si può fare.
    Sorry
    List<? extends InteractionHbond> interactions;
    
    if (typo == 1) {
        interactions = ihbond.findByLigId(lig_id);
    } else {
        interactions = ivwd.findByLigId(lig_id);
    }
    
    
    for (InteractionHbond interaction : interactions) { ....... }
    Se tutti i metodi che ti servono NEL for sono quelli noti già in InteractionHbond, questo mostrato è quello che serve.
    Sei un grande. Funziona perfettamente.

    Grazie
  • Re: [Risolto] Problema su oggetti

    morellik ha scritto:


    Funziona perfettamente.


    Ti è chiaro perché ho usato List<? extends InteractionHbond> e non altro? Quello è il punto essenziale.
  • Re: [Risolto] Problema su oggetti

    andbin ha scritto:


    morellik ha scritto:


    Funziona perfettamente.


    Ti è chiaro perché ho usato List<? extends InteractionHbond> e non altro? Quello è il punto essenziale.
    Non osavo chiedere , ho dato una scorsa al De Sio Cesari, ma e' ancora un po' nebuloso. Se mi puoi dare maggiore delucidazione faresti di me un uomo che ne sa un po' di piu' .

    Grazie 1000
  • Re: [Risolto] Problema su oggetti

    morellik ha scritto:


    Se mi puoi dare maggiore delucidazione faresti di me un uomo che ne sa un po' di piu' .
    I generics, per come sono stati ideati e implementati, funzionano ben diversamente rispetto agli array.

    Gli array sono "covarianti", ovvero ad esempio String[] è un sottotipo di Object[]. Pertanto si può fare:

    Object[] arr = new String[10];

    Il fatto che arr sia di tipo Object[] farebbe pensare che in arr (i qualunque indice valido) si possa mettere qualunque cosa visto che la variabile è Object[]. Non è così.

    arr[0] = new Long(1234);

    compila perfettamente ed è lecita per il compilatore ma a runtime FALLISCE (con ArrayStoreException). Questo perché all'interno dell'oggetto array istanziato (il String[]) vengono mantenute tutte le informazioni sul tipo, ovvero da qualche parte nell'oggetto è mantenuta la informazione "gli elementi sono di tipo String". Quindi la virtual machine Java PUO' impedire che nell'array vengano messi dati inappropriati per il tipo dell'array.


    I generics invece sono stati implementati per "erasure". In pratica esistono solo a livello di compilazione mentre a runtime non viene mantenuta alcuna informazione all'interno degli oggetti. Un oggetto ArrayList<String> non "sa" (non ha nulla all'interno) di contenere solo String né di essere parametrizzato <String>. Quindi non è possibile fare controlli come per gli array.
    Se la covarianza fosse possibile per i generics, tutta la teoria dei generics verrebbe completamente ravanata.

    I generics sono stati quindi resi "invarianti", cioè List<String> NON è un sottotipo di List<Object>.

    Quindi

    ArrayList<Object> list = new ArrayList<String>(); // NON compila

    Questa è sostanzialmente una limitazione. Per fornire una sorta di "polimorfismo" anche sui generics, sono stati introdotti i wildcard (con/senza bound).

    Esempio: List<?> lista;

    Questo <?> NON vuol dire che la lista può contenere "qualunque cosa" (una lista che può contenere qualunque cosa è List<Object>). Invece <?> vuol dire un'altra cosa: una lista di cui non si conosce la parametrizzazione concreta (cioè una lista con una parametrizzazione reale assegnata alla variabile).

    Con un bound (limitazione):

    List<? extends Number> nums;

    Anche qui non si sa quale è la parametrizzazione concreta ma c'è una informazione in più: è sicuramente Number o un sottotipo di Number.

    Quindi:
    nums = new ArrayList<Integer>(); // OK
    nums = new ArrayList<Long>(); // OK
    nums = new ArrayList<String>(); // NON compila perché String è fuori dal bound

    Con il bound in extends c'è una restrizione: non puoi inserire nulla nella lista (eccetto un null letterale), proprio perché la parametrizzazione della lista reale non la sai (se inserisci Long ma la lista assegnata fosse <Integer> ?)

    Pertanto con

    List<? extends InteractionHbond> interactions;

    puoi assegnarci sia un XyzList<InteractionHbond> che un XyzList<InteractionVdw>. Non puoi inserirci nulla ma puoi estrarre (il for-each estrae) solo come tipo del bound che è InteractionHbond. Ecco perché funziona.


    Ci sarebbe molto altro ma ho già detto molto.
  • Re: [Risolto] Problema su oggetti

    Sei veramente una cima, spiegazione eccezionale. Mai pensato di scrivere un libro?
Devi accedere o registrarti per scrivere nel forum
13 risposte