Scienze  
Syllabus ItalianoSyllabus IngleseindexlogoutArea Personale UNITN
Programmazione 2 forum Messaggi del Thread
 
Programmazione 2 - forum
Messaggi del Thread

Autore Messaggio
stefano.chirico
Thread
  Post Postato: 18 aprile 2005
   Titolo: JDeveloper e Interfacce.
 

Provo a scrivere qui una soluzione alle domande sull'esercizio delle Collection, visto che non riesco a rispondere al post (Errore interno al server... mah):

public class MiaClasse implements Collection 

     QUI <--- 

Ti metti (QUI) e vai su Tools. Quindi scegli "Implement Interface...". 

Per il punto 2 rimani in ascolto ;) 
Ciao
francesco.lago
  Post Postato: 18 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

Straordinariamente comodo!! Grazie mille ^^;
Aspetto con ansia il punto 2, ho fatto anche dei test e ho appurato che il problema occorre solo quando tento di dare un'istruzione del tipo a = b, dove a e b sono due Object (allocati come, per esempio, Integer); mentre se scrivo una cosa come 
((Integer)a).campoqualsiasi = valore;
allora si modifica anche il campo del rispettivo oggetto passato alla funzione dal main...
francesco.lago
  Post Postato: 18 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

tra l'altro, già che ci sono metto a disposizione la mia versione della Pila che implementa Collection in versione beta (problema #2 da risolvere)

(uso questo thread perchè l'altro effettivamente non sembra più funzionare)

Allegato:   File [ PilaCollection.rar ( 7637 bytes)]
stefano.chirico
  Post Postato: 19 aprile 2005
   Titolo: Re: Re: JDeveloper e Interfacce.
 

Ho dato un'occhiata veloce al tuo codice.
Da quello che ho capito si deve implementare uno Stack in modo che sia compatibile con l'interfaccia Collection. Questa interfaccia (stando alla documentazione ufficiale di Sun) utilizza il metodo remove(Object o) per eliminare dallo Stack l'elemento passato come parametro (o), sempre che questo sia presente, e quindi restituire true se l'operazione e' andata in porto o false in caso contrario. Quello che stai cercando di implementare tu, invece, e' il metodo pop (che estrae un elemento dallo stack). Ti consiglio di implementare questo metodo (o l'equivalente estrai()) dando come elemento di ritorno l'oggetto estratto (senza parametri in ingresso):

public Object pop();

L'estrai del tuo codice (il metodo remove), ha un piccolo errore:
invece che decrementare l'index (index--) fai solo una diminuizione senza assegnazione (in pratica index non cambia mai di valore) :)

P.S.
Leggendo sempre la documentazione di Sun, viene fuori che i metodi add, addAll, clear, remove, removeAll, retainAll, sono facoltativi (optional operation). Quindi non e' necessario implementarli. Per uno Stack, in fin dei conti, questi metodi non servono. Noi dobbiamo creare i metodi push e pop ed implementare tutti gli altri presenti nell'interfaccia Collection (isEmpty, size, toArray, ec...). Almeno, io ho interpretato l'esercizio in questo modo. Spero di non sbagliarmi.
Ciao.
aaron.ciaghi
  Post Postato: 19 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

stefano.chirico wrote:
Leggendo sempre la documentazione di Sun, viene fuori che i metodi add, addAll, clear, remove, removeAll, retainAll, sono facoltativi (optional operation). Quindi non e' necessario implementarli.

Vanno comunque implementate delle funzioni vuote, altrimenti il compilatore di Jdev restituisce un errore.
In ogni caso, penso non ci serva creare i metodi push e pop, ma semplicemente implementare add e remove in maniera adeguata allo stack.
Saluti.
francesco.lago
  Post Postato: 19 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

Non capisco dove sia l'errore di indice... ho scritto "index--", quindi il campo index dopo l'operazione di estrazione dovrebbe diminuire di uno (infatti funziona^^)

Ad ogni modo, è vero che il metodo remove sarebbe fatto per scopi diversi da quello che voglio fare, però se implemento un *nuovo* metodo da zero (non presente nella Collection) e poi lo richiamo da main, perdo completamente il polimorfismo e il senso dell'utilizzo dell'interfaccia... 
Il problema è che il metodo Remove non è progettato per restituire un Oggetto (quello rimosso), ma come hai detto tu, per rimuoverne uno speficico.  Questo contrasta un po' con quello che abbiamo sempre fatto per pile e code (il metodo pop, appunto).
Inoltre mi rimane sempre un mistero il fatto che gli Object passati per riferimento non si possano copiare con una semplice operazione di assegnazione "="; pensavo che così facendo cambiasse semplicemente il riferimento all'oggetto, ma evidentemente non è così..
stefano.chirico
  Post Postato: 19 aprile 2005
   Titolo: Re: Re: OOP, Collection, StackCollection
 

francesco.lago wrote:
Non capisco dove sia l'errore di indice... ho scritto "index--", quindi il campo index dopo l'operazione di estrazione dovrebbe diminuire di uno (infatti funziona^^)

Hai ragione, scusa. Aprendo il sorgente con l'editor di WinRar non avevo notato che i "-" erano 2, mi sembrava uno solo :P


francesco.lago wrote:
Ad ogni modo, è vero che il metodo remove sarebbe fatto per scopi diversi da quello che voglio fare, però se implemento un *nuovo* metodo da zero (non presente nella Collection) e poi lo richiamo da main, perdo completamente il polimorfismo e il senso dell'utilizzo dell'interfaccia... 
Il problema è che il metodo Remove non è progettato per restituire un Oggetto (quello rimosso), ma come hai detto tu, per rimuoverne uno speficico.  Questo contrasta un po' con quello che abbiamo sempre fatto per pile e code (il metodo pop, appunto).

Nella programmazione orientata agli oggetti si dovrebbe mantenere la coerenza tra classi "imparentate" tipo la nostra pila e l'interfaccia Collection. Nella logica degli Stack, pero', il metodo remove (che permette di eliminare un determinato oggetto) non vi rientra affatto (visto che si deve implementare una tecnologia LIFO). Io farei cosi': Implementerei il metodo add() in modo che funzioni come il classico push() degli stack, ed aggiungerei il metodo push() (che non fa altro che richiamare add()), solo per coerenza con le "specifiche" degli stack. Non implementerei il metodo remove (gli farei restituire sempre false) ma aggiungerei il classico metodo pop() presente in tutti gli stack.

Per AAron: Certo che bisogna implementare tutti i metodi dell'interfaccia (e per questo ci viene in aiuto JDeveloper :))). La nostra classe permette istanze di oggetti e quindi i suoi metodi devono essere tutti definiti. Per ovviare a questo si poteva creare una classe astratta che implementa l'interfaccia Collection e quindi ereditare da questa la nostra classe (in modo da implementare solamente i metodi che ci interessano) :P
aaron.ciaghi
  Post Postato: 19 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

stefano.chirico wrote:
Non implementerei il metodo remove (gli farei restituire sempre false) ma aggiungerei il classico metodo pop() presente in tutti gli stack

E' anche possibile implementare il metodo remove come un pop() passando sempre null come parametro quando lo si richiama nella classe che testa lo stack, mantenendo così coerenza con l'interfaccia (e al massimo si può sempre aggiungere un metodo pop() che richiama remove...).
francesco.lago
  Post Postato: 19 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

Non capisco tuttavia il senso di implementare nuovi metodi pubblici quando stiamo implementando un'interfaccia... a questo punto perdiamo il polimorfmismo, perchè il main va modificato, e il senso di usare un'interfaccia mi sfugge a questo punto.

Ad ogni modo, sto provando ad implementare l'interfaccia iterator con una classe PilaIterator, ma non capisco come fargli capire alla classe PilaIterator che si sta lavorando su una Pila... come faccio ad implementare i metodi quando non ho nessun riferimento alla classe Pila di cui voglio fare l'iteratore?
stefano.chirico
  Post Postato: 19 aprile 2005
   Titolo: Stack, Collection, Iterator.
 

francesco.lago wrote:
Non capisco tuttavia il senso di implementare nuovi metodi pubblici quando stiamo implementando un'interfaccia... a questo punto perdiamo il polimorfmismo, perchè il main va modificato, e il senso di usare un'interfaccia mi sfugge a questo punto.

Perche' noi non stiamo implementando una "semplice" collezione, ma una collezione che ha le funzionalita' dello Stack. Quindi estendiamo il concetto di collezione ad una logica LIFO classica dello Stack. Visto che la generica collezione non e' pensata per ragionare in "LIFO"-Style, dobbiamo aggiungere i metodi adatti (push() e pop()).

francesco.lago wrote:
Ad ogni modo, sto provando ad implementare l'interfaccia iterator con una classe PilaIterator, ma non capisco come fargli capire alla classe PilaIterator che si sta lavorando su una Pila... come faccio ad implementare i metodi quando non ho nessun riferimento alla classe Pila di cui voglio fare l'iteratore?

Se la classe PilaIterator (che implementa l'interfaccia Iterator) la crei come classe interna a PilaCollection, avrai accesso a tutti gli elementi interni al tuo Stack, in modo da poter restituire in modo corretto l'iteratore (e nascondendo allo stesso tempo l'implementazione di questa funzionalita').
nbrugnolli
  Post Postato: 19 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

1. selezionare la classe (il sorgente o l'icona nel diagramma delle classi). Dal memu primcipale selezionare Tools -> Implements Interface
Selezionare l'interfaccia (in questo caso java.util.Collection). Confermando l'operazione verranno implementati in modo "banale" tutti i metodi definiti dall'interfaccia.

2. Fate attenzione al significato dei metodi che dovete implementare, per sapere come si devono comportare leggete la documentazione dell'interfaccia java.util.Collection. Per il metodo remove troviamo:
"
        remove 

        public boolean remove(Object o)
       
        Removes a single instance of the specified element from this collection, if it is present (optional operation). More formally, removes an element e such that (o==null ? e==null : o.equals(e)), if this collection contains one or more such elements. Returns true if this collection contained the specified element (or equivalently, if this collection changed as a result of the call).
        Parameters:o - element to be removed from this collection, if present.
        Returns:true if this collection changed as a result of the call
"
quindi ci si aspetta che faccia esattamente questo (attenzione al significato del parametro e del valore ritornato). Se volete implementare il metodo estrai(), vi consiglio di chiamarlo remove (senza parametri come il nostro vecchio estrai) o semplicemente estrai (in ogni caso e' un metodo diverso dal Collection.remove(Object o)).

Suggerimento: per aprire la documentazione delle classi di libreria: selezionate nel codice il nome della classe e, usando il menu che si apre con il pulsante destro del mouse, selezionate "Go to Javadoc".

A parte queste considerazioni sul metodo remove, vediamo qual'e' stato il problema con il passaggio per riferimento dell'oggetto da rimuovere.


public boolean remove(Object element){
     
       //...
       element = contenuto[index-1] ;
       //...
}

public static void main(String arg[]){

       //...
       Object anObject;
       //...
       Pila pila;

       pila.remove(anObject);

     
}

In fase di esecuzione del metodo remove, anObject ed element sono due riferimenti allo stesso oggetto. Con l'istruzione element = ..
stai assegnando all'identificatore element il riferimento ad un altro oggetto (appunto quello contenuto nell'array) senza modificare anObject.
francesco.lago
  Post Postato: 19 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

.. è vero, non ci avevo pensato.
C'è un modo per copiare un Object in un altro in modo che si modifichino tutti i campi di quello passato quindi?

Non mi è per nulla chiara questa storia delle interfacce.  Se implementiamo un'interfaccia è perchè vogliamo che il codice, ad esempio da main, sia polimorfo, ovvero valga per qualsiasi tipo di collection (una pila, una coda, un cumulo di macerie, una mailing list, un branco di lupi), o almeno l'avevo capita in questo modo.  Se però noi andiamo a definire dei nuovi metodi all'interno della classe che implementa l'interfaccia, che senso ha l'implementazione? A questo punto non è meglio fare un extend tra pila e coda?

Inoltre mi è ultimamente sorto un ulteriore dubbio... dato che tutte le funzioni dell'interfaccia Collection possono tranquillamente essere implementate senza iteratori, l'implementazione di questi che fine ha? Presumo abbia un fino non utile immediatamente al programmatore di quesot livello, am eventualmente ad uno di livello più alto, giusto?
stefano.chirico
  Post Postato: 20 aprile 2005
   Titolo: Re: Re: JDeveloper e Interfacce.
 

francesco.lago wrote:
.. è vero, non ci avevo pensato.
C'è un modo per copiare un Object in un altro in modo che si modifichino tutti i campi di quello passato quindi?

Il problema era che i parametri dei metodi vengono sempre passati per copia e quindi e' impossibile modificarne il valore.
Attraverso la sola assegnazione a = b (dove a e b sono due riferimenti ad oggetti ed a e' il parametro del metodo), si modifica il valore di a ma non quello della variabile passata al metodo dall'esterno:

metodo(Object a)
{
   a = b;
}

main
{
   Object pippo = new Object();
   oggetto.metodo(pippo);
}

In questo pezzo di codice, quando si entra nel "metodo" si modifica il valore del "puntatore" ma appena si esce l'oggetto pippo mantiene il suo vecchio valore (e quindi punta sempre allo stesso oggetto e non a quello cui avremmo voluto noi).

Per copiare un oggetto in un altro esiste il metodo clone() ereditato dalla classe Object. C'e', pero', un problema: un generico Object non ha nulla da clonare ed infatti il suo metodo clone() e' protetto (non lo si puo' richiamare)... Per utilizzare il metodo remove come vuoi tu, dovresti "specializzare" lo Stack in modo che accetti solamente elementi di un certo tipo (il cui metodo clone() venga definito), oppure utilizzare Java 1.5 che ha introdotto i generics :P (ma questo e' un altro discorso ;)).


francesco.lago wrote:
Non mi è per nulla chiara questa storia delle interfacce.  Se implementiamo un'interfaccia è perchè vogliamo che il codice, ad esempio da main, sia polimorfo, ovvero valga per qualsiasi tipo di collection (una pila, una coda, un cumulo di macerie, una mailing list, un branco di lupi), o almeno l'avevo capita in questo modo.  Se però noi andiamo a definire dei nuovi metodi all'interno della classe che implementa l'interfaccia, che senso ha l'implementazione? A questo punto non è meglio fare un extend tra pila e coda?

Beh, secondo me le intefracce in Java servono per due cose fondamentali:
1. Permettere di realizzare l'ereditarieta' multipla
2. Permette di avere coerenza tra classi che svolgono lo stesso tipo di funzione. Ad esempio grazie alla interfaccia collection, le code, gli stack, le liste ecc... avranno metodi coerenti tra loro.

Sul tuo ultimo dubbio, non ho capito la domanda :P
Ciao :)
marco.ronchetti
  Post Postato: 20 aprile 2005
   Titolo: Re: Re: Re: JDeveloper e Interfacce.
 

stefano.chirico wrote:

Per copiare un oggetto in un altro esiste il metodo clone() ereditato dalla classe Object. C'e', pero', un problema: un generico Object non ha nulla da clonare ed infatti il suo metodo clone() e' protetto (non lo si puo' richiamare)...


Corretto: Clone lo vedremo in classe in una prossima lezione perchè è un argomento delicato.
francesco.lago
  Post Postato: 22 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

Dunque..
Ho provato a implementare come consigliato il metodo "Object estrai()" nella Classe Pila che implementa Collection.
Il problema però è esattamente quello di cui mi preoccupavo, ovvero: nel Main per richiamare tale metodo devo dare un'istruzione del tipo 
oggettoditipoPila.estrai();

ma oggettoditipoPila l'ho dichiarata come variabile Collection!
(Collection oggettoditipoPila = new Pila;)

quindi Jdev si arrabbia e mi dice (secondo me abbastanza logicamente): method not found in java.util.Collection

Ora, il rimedio suppongo sia quello di castare, per un risultato del tipo 

((Pila)oggettoditipoPila).estrai();

facendo così abbiamo bruciato tutto il bel polimorfismo che ci eravamo costruiti, perchè allocando nella variabile di tipo Collection (in una futura riedizione del programma) un oggetto di tipo, ad esempio, Coda, dobbiamo riscrivere *svariate* righe del main.

Creare una nuova interfaccia che implementi Collection a cui aggiungere il metodo estrai, sinceramente mi semrbra un po' troppo... oppure è proprio questo che si deve fare?

Come posso fare?_?
stefano.chirico
  Post Postato: 22 aprile 2005
   Titolo: Re: Re: JDeveloper e Interfacce.
 

francesco.lago wrote:
Dunque..
Ho provato a implementare come consigliato il metodo "Object estrai()" nella Classe Pila che implementa Collection.
Il problema però è esattamente quello di cui mi preoccupavo, ovvero: nel Main per richiamare tale metodo devo dare un'istruzione del tipo 
oggettoditipoPila.estrai();

ma oggettoditipoPila l'ho dichiarata come variabile Collection!
(Collection oggettoditipoPila = new Pila;)

quindi Jdev si arrabbia e mi dice (secondo me abbastanza logicamente): method not found in java.util.Collection

Ora, il rimedio suppongo sia quello di castare, per un risultato del tipo 

((Pila)oggettoditipoPila).estrai();

facendo così abbiamo bruciato tutto il bel polimorfismo che ci eravamo costruiti, perchè allocando nella variabile di tipo Collection (in una futura riedizione del programma) un oggetto di tipo, ad esempio, Coda, dobbiamo riscrivere *svariate* righe del main.

Creare una nuova interfaccia che implementi Collection a cui aggiungere il metodo estrai, sinceramente mi semrbra un po' troppo... oppure è proprio questo che si deve fare?

Come posso fare?_?

Scusa se ti rispondo solo adesso...
Non e' JDev che si arrabbia ma proprio il compilatore Java :) Questo per il semplice fatto che il tuo oggetto e' di "tipo" Collection ed il "tipo" Collection non prevede il metodo estrai (che e' proprio di Pila). In realta', pero', l'oggetto che vai a costruire e' effettivamente una Pila (anche se il compilatore non lo sa...).
Facendo come hai fatto tu, ti trovi un oggetto Pila che pero' e' di tipo Collection. Per utilizzarlo come Pila devi fare in "downcasting", cioe' un cast che specializza una classe (Collection) in una sua sottoclasse (Pila). Per fare cio' devi forzare il casting (devi fare un cast esplicito) e quindi devi scrivere il codice proprio come hai fatto tu: 

((Pila)oggettoditipoPila).estrai();

Per il nostro esercizio penso che la soluzione migliore sia quella di creare un oggetto di tipo Pila. Questo oggetto potra', comunque, essere utilizzato ovunque si puo' utilizzare una generica Collection.
francesco.lago
  Post Postato: 23 aprile 2005
   Titolo: Re: JDeveloper e Interfacce.
 

E' proprio questo punto che mi sfugge, io facevo questo esercizio con una mentalità che prevede il polimorfismo.  In altre parole, pensavo di fare un codice in modo che successivamente, cambiando semplicemente UNA parola del main (la parola "Pila" della riga Collection nome = new Pila) per un'altra classe implementata allo stesso modo, il programma funzionasse.
Se noi andiamo a mettere nel main dei metodi scritti *apposta* per la nostra classe, perdiamo il livello di astrazione che ci eravamo prefissati tramite l'utilizzo dell'interfaccia collection, e anche tutto il senso che ha tale utilizzo.
Comunque a questo punto aspetto con ansia le nuove lezioni :_D
stefano.chirico
  Post Postato: 23 aprile 2005
   Titolo: Re: Re: JDeveloper e Interfacce.
 

francesco.lago wrote:
E' proprio questo punto che mi sfugge, io facevo questo esercizio con una mentalità che prevede il polimorfismo.  In altre parole, pensavo di fare un codice in modo che successivamente, cambiando semplicemente UNA parola del main (la parola "Pila" della riga Collection nome = new Pila) per un'altra classe implementata allo stesso modo, il programma funzionasse.
Se noi andiamo a mettere nel main dei metodi scritti *apposta* per la nostra classe, perdiamo il livello di astrazione che ci eravamo prefissati tramite l'utilizzo dell'interfaccia collection, e anche tutto il senso che ha tale utilizzo.
Comunque a questo punto aspetto con ansia le nuove lezioni :_D

Il polimorfismo permette di non cambiare alcuna parola all'interno del codice sorgente . Il nostro codice polimorfico si adattera' in modo automatico anche a codice scritto in futuro e non previsto da noi .
L'esercizio prevede di scrivere una classe che si comporti come uno Stack ma che fosse, anche, un tipo di Collection.
Quando vuoi utilizzare un oggetto come Stack e' bene che lo dichiari di tipo Stack (o Pila). Lo stesso oggetto potra' essere utilizzato tranquillamente come Collection in qualsiasi parte di codice si faccia riferimento a delle Collection.
Se nel main vuoi utilizzare esclusivamente Collection, puoi dichiarare il tuo oggetto di tipo Collection (anche se poi istanzi una Pila), ma a questo punto potrai solamente utilizzare i metodi previsti da Collection (e non quelli specifici per uno Stack, che altro non e' se non una "specializzazione" di Collection). Penso che in classe tutta questa teoria sulla OOP ci verra' spiegata meglio . Vedrai, ti innamorerai di cio' che si riesce a fare con la programmazione orientata agli oggetti .
Ciao.
 
Progetto eLeaf
Contact eLeaf team