Problema con interface e classi

di il
12 risposte

Problema con interface e classi

Buongiorno a tutti sono nuovo della programmazione ad oggetti, e mi sono trovato davanti ad un problema.
Allora io ho una classe Nodo che mi deve usare un tipo generico T e io ho deciso di dividere il lavor in due parti:

public interface Iterator <T> {

 	 int Iterator(T o);
	
}

e richiamarlo in Node.java

import java.lang.*;
public class Node implements Iterator<Node>  {}
così mi da errore dicendo che

Multiple markers at this line
	- The type Node must implement the inherited abstract method 
	 Iterator<Node>.Iterator(Node)
	- The type Node must implement the inherited abstract method 
	 Iterator<Node>.Iterator(Node)
Io ammetto di non capirci ancora molto avrei bisogno di una spiegazione.
Grazie in anticipo.

12 Risposte

  • Re: Problema con interface e classi

    surapazzo ha scritto:


    
    Multiple markers at this line
    	- The type Node must implement the inherited abstract method 
    	 Iterator<Node>.Iterator(Node)
    	- The type Node must implement the inherited abstract method 
    	 Iterator<Node>.Iterator(Node)
    
    Io ammetto di non capirci ancora molto avrei bisogno di una spiegazione.
    Grazie in anticipo.
    Innanzitutto, quale è il senso/significato di una interfaccia Iterator che ha un metodo Iterator che riceve un oggetto T?

    Se guardassi il java.util.Iterator del framework, vedresti che Iterator è una interfaccia che offre i metodi per iterare, avendo hasNext()/next().

    Poi comunque, per tornare al tuo errore, se crei una classe "concreta" (non astratta) come la tua Node e implementi una interfaccia, allora naturalmente devi implementare concretamente tutti i metodi della interfaccia, ovvero nel tuo caso devi implementare quel int Iterator(T o) .

    Ma ripeto: prima chiarisci(ti) il concetto della tua interfaccia.
  • Re: Problema con interface e classi

    Ok e chiaro il discorso.... la mia domanda era data dal fatto che devo implementare delle liste quindi iterator mi serviva per scorrere la lista con il metodo next() mi pare...
    Pero ho le idee molto confuse perchè non so come usare iterator perchè non ho capito il funzionamento...
    Riesci a darmi una mano?
  • Re: Problema con interface e classi

    surapazzo ha scritto:


    Ok e chiaro il discorso.... la mia domanda era data dal fatto che devo implementare delle liste quindi iterator mi serviva per scorrere la lista con il metodo next() mi pare...
    Pero ho le idee molto confuse perchè non so come usare iterator perchè non ho capito il funzionamento...
    Riesci a darmi una mano?
    Innanzitutto quando si deve implementare una lista "linkata" ci sono alcune cose da valutare:
    - se deve essere linkata singola (i puntamenti dei nodi sono solo in avanti) o doppia (puntamenti avanti e indietro).
    - se gli oggetti dei nodi devono essere nascosti (chi usa la lista non "sa" nulla dei nodi) oppure esposti e/o anche ricevuti dalla lista.

    Se i nodi sono nascosti, l'iteratore è fondamentale. Il design pattern Iterator descrive infatti lo scenario in cui di una collezione si vuole scorrere i suoi elementi, senza dover far conoscere o esporre al di fuori della collezione i dettagli della implementazione della collezione.
    L'iteratore insomma nasconde questi dettagli ed è l'oggetto iterator che ha una connessione più o meno "intima" con la struttura dati della collezione.

    Se invece i nodi sono esposti e il "client" (chi usa la lista) puoi navigare tra i nodi per conto suo, l'iterator è meno fondamentale ma comunque utile.

    In un certo momento puoi avere più oggetti iterator, ciascuno ad una posizione anche differente nella lista. Per questo motivo mi pare ovvio che l'oggetto Iterator non è la lista e nemmeno il nodo! Quindi un "Node implements Iterator" è comunque inappropriato.

    Mi sembra di capire che devi ancora implementare la lista e i nodi. Inizia quindi da questi ... non dall'iterator. Implementa correttamente la lista, con tutti i metodi che vuoi o che ti sono stati richiesti/imposti (add, remove ecc....).
    Poi la implementazione del Iterator ti verrà abbastanza naturale se hai implementato bene la lista.
    Nota: generalmente la classe che implementa la interfaccia Iterator si fa con una inner-class privata nella classe della collezione. Poi si fa restituire una nuova istanza del'iteratore facendola vedere solo con il tipo astratto della interfaccia.

    Prova e se hai dubbi, chiedi pure.
  • Re: Problema con interface e classi

    OK perfetto, molto chiaro ora volevo chiederti ancora una cosa.
    La mia lista è singolarmente linkata e implementa solo metodi base base tipo cambiare il valore al nodo, cercare in base all' indice dato e cose del genere.... ora la mia domanda è: riesci a farmi un esempietto velocissimo di metodo dove mi scorre la lista per capire come richiamre l iterator() e come utilizzarlo all 'interno.
    i nodi sono privati.

    ex
    -il nodo ha un campo int e il next.
    - la lista ha un campo nodo e i suoi metodi per modificarne il contenuto.
    Perchè venendo dal c dal c++ l'idea di non avere i puntatori mi urta un sacco
    No a parte gli scherzi mi manca il passaggio mentale da capire come si trasmutano i puntatori in iterazioni.
    Grazie mille
  • Re: Problema con interface e classi

    surapazzo ha scritto:


    riesci a farmi un esempietto velocissimo di metodo dove mi scorre la lista per capire come richiamre l iterator() e come utilizzarlo all 'interno.
    i nodi sono privati.
    In una collezione, il metodo che tira fuori l'iteratore tipicamente può essere una cosa del tipo:
    public Iterator<T> iterator() {
        return new IteratorImpl();
    }
    Dove IteratorImpl è tipicamente una inner-class privata (quindi nascosta) interna alla collezione.

    L'iteratore in generale deve tenere lo stato che permette di sapere a che punto è arrivato. Nelle liste linkate, l'iteratore banalmente può tenere il riferimento ad un nodo "corrente". All'inizio, alla creazione dell'iteratore, il nodo corrente è il primo, quindi il primo next() eseguito ritornerà quello. E l'iteratore andrà avanti così.

    surapazzo ha scritto:


    Perchè venendo dal c dal c++ l'idea di non avere i puntatori mi urta un sacco
    No a parte gli scherzi mi manca il passaggio mentale da capire come si trasmutano i puntatori in iterazioni.
    La semantica dei puntatori C/C++ è praticamente quasi uguale a quella dei reference in Java.
    I puntatori C/C++ offrono ovviamente di più, un puntatore è indirizzo di cui puoi stamparne il valore, puoi aggiungerci/sottrarci una quantità (la "aritmetica dei puntatori"), ecc...

    In Java un reference a runtime diventa sotto-sotto anch'esso un indirizzo in memoria. Solo che per il programmatore Java un reference è qualcosa di molto "opaco". Non sai che valore ha, non sai quanto occupa in bit e non puoi farci alcunché di particolare con esso.
    Cosa è realmente un reference a runtime, dipende dalla piattaforma, dalla implementazione della JVM (anche il fatto se è 32 o 64 bit) e da altri fattori. Ma è comunque sempre un "valore" anch'esso.

    Ma la semantica è praticamente uguale: l'operatore == confronta il valore di due puntatori/reference (stesso valore = stesso oggetto), se passi un puntatore/reference, passi una copia del valore del puntatore/reference.
  • Re: Problema con interface e classi

    Quello che non mi è chiaro se iterator è una classe già nota quindi la posso utilizzare come se fosse una libreria per capirci e quindi includendo il package adatto se io chiamo i metodi con iterator(), sono utilizzabili o no.
    Per intenderci se io faccio le mie classi linkelist e Node e possibile inserire nei loro metodi funzioni apparteneti ad iterator()?
  • Re: Problema con interface e classi

    surapazzo ha scritto:


    Quello che non mi è chiaro se iterator è una classe già nota quindi la posso utilizzare come se fosse una libreria per capirci e quindi includendo il package adatto se io chiamo i metodi con iterator(), sono utilizzabili o no.
    Per intenderci se io faccio le mie classi linkelist e Node e possibile inserire nei loro metodi funzioni apparteneti ad iterator()?
    Un tipo "iteratore" esiste già nel framework, è java.util.Iterator. È una interfaccia, quindi ovviamente va implementata. Le collezioni standard del framework hanno un metodo iterator() che tira fuori un oggetto Iterator che è implementato in una classe interna, nascosta.

    Se vuoi usare quel Iterator e non hai altre controindicazioni, ok. Se invece ti è stato chiesto (presumibilmente per motivi "didattici") di fare tu una interfaccia Iterator ... allora è un altro conto, chiaramente spetta a te idearla.
  • Re: Problema con interface e classi

    E infatti non posso usare l interfaccia iterator

    Quindi come si potrebbe pensare di progettare?
  • Re: Problema con interface e classi

    surapazzo ha scritto:


    E infatti non posso usare l interfaccia iterator

    Quindi come si potrebbe pensare di progettare?
    Se non puoi usare il Iterator del framework ... ok! Puoi farla tu, è una banale interfaccia con almeno 2 metodi, che significano semplicemente: "dimmi se c'è un altro elemento" e "dammi il prossimo elemento". Li puoi anche denominare come vuoi ....

    Il punto non è tanto l'interfaccia (2 metodi in croce senza corpo) ma ovviamente la classe che la implementa. La tua lista dovrà avere un metodo che fornisce all'esterno un nuovo iteratore.
    E l'avevo detto anche prima, non sono né la lista, né il nodo che devono implementare la interfaccia dell'iteratore.
  • Re: Problema con interface e classi

    Scusami continuo a non capire perchè mi sono piantato...
    ipoteticamente faccio la mia interfaccia anche se non ho la minima idea di come farla, ma tolto questo poi come faccio a farla "leggere" alle mie classi?

    Grazie e scusa la durezza di comprendonio ma sono proprio cotto e non sono ancora entrato bene nei maccanismi OO.
  • Re: Problema con interface e classi

    surapazzo ha scritto:


    ipoteticamente faccio la mia interfaccia anche se non ho la minima idea di come farla
    Ok, ma ti ho già indicato in precedenza che i metodi che hanno senso nell'iteratore sono principalmente almeno 2: uno che significa "dimmi se c'è ancora almeno un elemento" e l'altro "dammi il prossimo elemento". Poi si potrebbe anche avere il "remove" (come avviene in java.util.Iterator) ma non è obbligatorio se la fai tu da zero.

    Non ti linko il javadoc di Iterator di Java 8, perché in Java 8 ci sono importanti novità sulle interfacce che hanno coinvolto anche Iterator. Ma quello di Java 7 sì, eccolo:

    http://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html

    Sono 3 metodi in croce. Ignora remove, se non ti serve e rimangono i due metodi che ho descritto prima. Il punto/problema non è affatto la interfaccia, sono almeno 2 metodi in croce e senza corpo (perché sono abstract nella interfaccia).

    La vera questione è la implementazione. Come ho già detto in precedenza, chi usa la tua lista potrebbe richiedere più iteratori e iterare con tempi o velocità differenti. Ogni oggetto iteratore deve quindi avere il suo "stato" per tenere le informazioni sull'elemento "corrente".
    Ed è quindi ovvio che non è la tua classe Lista a poter implementare Iterator e nemmeno la tua classe Nodo. Deve essere un'altra classe, che generalmente viene tenuta nascosta all'interno della collezione.

    surapazzo ha scritto:


    ma tolto questo poi come faccio a farla "leggere" alle mie classi?
    L'hai detto un po' impropriamente. Ti butto giù allora lo scheletro (molto molto abbozzato) per una classe Lista in cui la classe nodo e la implementazione dell'iteratore sono nascosti e non visibili dall'esterno della lista.
    public class Lista<E> {
        private Nodo<E> testa;
    
        // .......
    
        public Iterator<E> iterator() {
            return new IteratorImpl();
        }
    
    
        private class IteratorImpl implements Iterator<E> {
            // ......
    
            // ... implementazione di es. hasNext() / next()
        }
    
    
        private static class Nodo<T> {
            // ......
        }
    }
    La classe IteratorImpl è una "inner class" dentro Lista. Le inner class hanno una peculiarità: una istanza della inner-class ha un legame molto speciale con la istanza della classe contenitore, principalmente perché può accedere direttamente a membri, anche private, della classe contenitore. In questo caso è utile poiché IteratorImpl quasi sicuramente userà lo "stato" di Lista, ad esempio quel 'testa'.

    Il Nodo invece è una "nested (static) class", che non ha alcun legame speciale con Lista. Non è necessario perché ogni nodo può stare per conto suo, al massimo avendo solo il riferimento ad un altro Nodo successivo(/precedente).
  • Re: Problema con interface e classi

    Ok grazie ora mi e tutto più chiaro...
    Cerco di andare avanti e vedo cosa riesco a fare
    Grazie mille...
Devi accedere o registrarti per scrivere nel forum
12 risposte