[Risolto] Interfacce e implementazione realizzativa

di il
13 risposte

[Risolto] Interfacce e implementazione realizzativa

Innanzitutto salve a tutti, ho cercato una sezione apposita per presentarmi ma non sono riuscito a trovarla
Vorrei prima di tutto presentarmi: sono uno studente di Informatica e da poco più di 2 mesi ho iniziato ad interessarmi al java sia per passione sia perché a breve dovrò sostenere un esame specifico riguardante appunto questo linguaggio. Sono parecchio inesperto con questo linguaggio anche se so programmare ad un livello principiante (pur non conoscendo ancora algoritmi notevoli e tecniche particolari), nel senso che le basi (avendo utilizzato linguaggi come python) le ho acquisite e ho anche realizzato dei piccoli giochini senza interfaccia grafica oppure programmi con interfaccia grafica minimale. Però in questi due mesi, pur avendo studiato tutto ciò che potevo, mi sto trovando un po' male sugli ultimi argomenti trattati dal professore sia perché ho avuto dei problemi personali sia perché ho avuto un periodaccio...e adesso sono rimasto indietro e mi ritrovo con molti dubbi sull'utilizzo di questo linguaggio.
Vi presumo che io prima di 2 mesi fa non sapevo quasi nulla sulla programmazione orientata agli oggetti, quindi andateci piano

Gli ultimi argomenti trattati dal professore sono stati l'ereditarietà, il polimorfismo, le interfacce e le espressioni lambda.
Riguardo ereditarietà e polimorfismo credo di aver capito bene o male, mentre con le interfacce sto facendo molta difficoltà perché non ne capisco il senso e in questo vorrei un aiuto da parte vostra, se potete. da quel che ho capito le interfacce sono un elenco di metodi astratti che non vanno implementati perché sarà una classe a dover implementare l'interfaccia e quindi a impostare e realizzare i vari metodi. Pertanto l'interfaccia a cosa mi serve? Potreste darmi un esempio concreto? Vi ringrazio in anticipo
Sto anche svolgendo degli esercizi, ma non ci riesco. Prima di parlarvene però vorrei avere delle risposte sulla "teoria".

P.S Secondo voi il manuale di java 8 di Claudio De Sio Cesari è un buon libro per iniziare? Oppure dovrei scerglierne un altro? Fino ad ora sono andato avanti usando le slide che il professore ci fornisce dopo ogni lezione, ma ora sembra non bastino più.

13 Risposte

  • Re: [Risolto] Interfacce e implementazione realizzativa

    Buonasera grazie mille per la risposta.

    Vorrei farti delle domande su ciò che hai detto:

    1- Come faccio a visualizzare i packages standard di java?
    2- L'interfaccia Comparable quindi se ho capito bene ha l'obiettivo di fornire l'indicazione di un solo metodo astratto (che nell'interfaccia non è descritto) e che sarebbe compareTo, il quale va implementato nella classe in cui si esegue il sort di qualunque collezione di oggetti, giusto? E allora il criterio di ordinamento dipende dall'implementazione di compareTo della classe stessa?
    3- Menomale che non l'ho comprato il libro di De Sio Cesari! Ma come mai non è un buon testo? In molti dicono che sia un libro fantastico, sai ero quasi tentato...ma in effetti già prima non mi fidavo più di tanto delle recensioni positive e infatti non l'ho acquistato.
    Riguardo invece al testo di Herbert Schildt, si lo conosco e infatti si dice sia davvero un ottimo libro, infatti era già una delle mie possibili scelte.
  • Re: [Risolto] Interfacce e implementazione realizzativa

    1) nel javadoc associato alla versione di Java che usi
    2) esatto, pero' c'e' anche la possibilita' di usare un oggetto terzo che implementa l'interfaccia Comparator, ed in questo caso puoi scegliere il tipo di confronto. Comparable e' utile quando esiste un ordine naturale, o da usare per default, per quel tipo di oggetti.
    3) e' un problema legato alla conoscenza della materia: il ziovine virgulto che non conosce la materia, non si accorge delle sciochezze che vengono scritte (corrette, ma non sufficientemente contestualizzate)

    E' evidente che non puoi fidarti delle recensioni sperticate scritte da persine con un limitato bagaglio culturale: se anche ci dovessero essere 1.000.000 di recensioni, scritte da studenti, che dicono che e' ottimo, ed 1 di un docente che insegna, a chi dovresti credere?
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Vi ringrazio molto per le preziose e dettagliate risposte
    Credo di iniziare a capire a cosa servano le interfacce, ma ancora non ci sono, soprattutto perché sto cercando di svolgere un esercizio e credo di essermi confuso. L'esercizio chiede di progettare una gerarchia di classi di animali e non so se sto seguendo il ragionamento giusto. Viene richiesto di progettare Uccello (che vola e becca) e le sue sottoclassi Pinguino (che becca e nuota) e Aquila (che vola e becca). In questo caso come dovrei fare? Non capisco se devo creare 3 interfacce, una per ogni azione o metodo (vola, becca, nuota), visto che non sono tutte in comune nelle classi di riferimento, oppure se devo fare in altro modo...sapete aiutarmi? Vi ringrazio molto e vi auguro una buona giornata
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Grazie per la risposta
    Ma non ho capito una cosa, se nella classe Uccello sono previsti i metodi vola() e becca(), mentre nella classe Pinguino sono previsti nuova() e becca(), quando vado ad estenderla, la classe Pinguino non eredita anche il metodo vola che invece non dovrebbe possedere? Dovrei quindi fare un override del metodo vola (il quale lancia un'eccezione) e poi fargli lanciare l'eccezione quando richiamato? Non l'ho mai fatto e non so se si possa fare, chiedo scusa per l'incertezza
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Ora ho capito...questo tipo di tecnica non la conoscevo, ti ringrazio molto. Provo a fare l'esercizio e vi faccio sapere.
    Grazie ancora per la disponibilità e l'aiuto
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Si è vero
    Comunque ho provato a risolvere questa parte dell'esercizio, ho creato prima un'interfaccia volatile che possiede i metodi void vola() e becca() e poi ho creato la superclasse Uccello (introducendo gli attributi nome e taglia) e le classi figlie Pinguino e Aquila. Vi posto il codice, se vi va date un'occhiata, così magari mi dite se ho fatto le cose nel modo corretto:
    
    public interface Volatile
    {
    	void vola() throws NonVolaException;
    	void becca();
    }
    
    
    
    
    public abstract class Uccello implements Volatile
    {
    	
    	public enum Taglia
    	{
    		Grande, Media, Piccola;
    	}
    	
    	protected String nome;
    	protected Taglia taglia;
    	protected boolean vola;
    
    	
    	
    	public Uccello(String nome, Taglia taglia)
    	{
    		this.nome = nome;
    		this.taglia = taglia;
    	}
    	
    	public void becca() { System.out.println("l'uccello sta beccando"); }
    	
    	public void vola() throws NonVolaException 
    	{ 
    		if (!vola) throw new NonVolaException();
    		System.out.println("l'uccello vola in alto"); 
    	}
    
    }
    
    
    
    public class Pinguino extends Uccello 
    {
    	protected static final Taglia taglia = Taglia.Piccola;
    	
    	public Pinguino(String nome)
    	{
    		super(nome,taglia);	
    		this.vola=false;
    	}
    	
    	@Override
    	public void becca() { System.out.println("il pinguino sta beccando"); }
    	
    	@Override
    	public void vola() throws NonVolaException
    	{
    		throw new NonVolaException();
    	}
    	
    	public void nuota() { System.out.println("il punguino sta nuotando"); }
    	
    	
    }
    
    
    public class Aquila extends Uccello 
    {
    	public static final Taglia taglia = Taglia.Grande;
    	
    	public Aquila(String nome)
    	{
    		super(nome,taglia);
    		this.vola = true;
    	}
    	
    	@Override
    	public void becca() { System.out.println("l'aquila sta beccando"); }
    	
    	@Override
    	public void vola() throws NonVolaException
    	{
    		if (!vola) throw new NonVolaException();
    		else System.out.println(" L'aquila sta volando...");
    	}
    }
    
    
    
    
    public class NonVolaException extends Exception
    {
    	public NonVolaException() 
    	{
    		super("Il soggetto non può volare");
    	}
    }
    
    
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Ah...io da quel che avevo capito se dichiaro una classe astratta, posso comunque definire in maniera "aspecifica e quindi astratta" i suoi metodi...l'ho fatto perché anche se uccello essendo astratto non è buildabile, potrei comunque aver bisogno di avere ben presente lo "scheletro" dei suoi metodi. Anche il professore del corso, in una lezione dedicata mostrandoci come si progetta un essere vivente, ha implementato in maniera minimale alcuni metodi e aveva assolutamente dichiarato la classe come astratta. Non so dirti perché lo abbia fatto però! Credevo si dovesse ragionare così...Oppure non è così che si fa? In ogni caso, dovrei rimuovere tutte le implementazioni dei metodi, però gli stati e l'enumerazione posso lasciarli giusto?
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Personalmente, anche se non sono un esperto, io trovo assolutamente sensato implementare i metodi in una classe astratta.
    O, quanto meno, ha senso se poi non vai a ridefinirli completamente in ogni sottoclasse, a quel punto sarebbe sì superfluo, ma se c'è della logica comune tra le sottoclassi trovo giusto che stia in Uccello.

    A me pare invece "molto brutto" il fatto che le sottoclassi di Uccello come Pinguino ereditino dalla classe madre il membro :
    
    protected Taglia taglia; 
    
    E poi definiscano qualcosa come :
    
    protected static final Taglia taglia = Taglia.Piccola;
    
    Questo crea un sacco di conclusione.

    Se vuoi puoi leggere questo link : http://stackoverflow.com/questions/685300/is-there-a-way-to-override-class-variables-in-java.

    Nei commenti della discussione tra l'altro viene linkata un'altra discussione utile : http://stackoverflow.com/questions/24289070/why-we-should-not-use-protected-static-in-java.

    Io in questo caso non utilizzerei quelle variabili statiche, dichiarerei Taglia come final nella classe Uccello (se immagini che la taglia possa cambiare, allora non avrebbe avuto senso dichiararla come final nelle sottoclassi) e lascerei che sia il costruttore di ogni sottoclasse a passare al costruttore della superclasse Taglia.Piccola etc.

    Se non siete d'accordo ditemi assolutamente
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Hai ragione riguardo la taglia, mi sono basato su un esercizio simile svolto dall'esercitatore del corso e in effetti non mi convinceva molto...forse dovrei fare così:
     
     
     public class Pinguino extends Uccello 
    {
    	
    	public Pinguino(String nome)
    	{
    		super(nome,Taglia.Piccola);	
    		this.vola = false;
    	}
    	
    	.........
    	
    
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Ho capito...grazie
    Invece per quanto riguarda le interfacce ho ancora qualche dubbio: non so perché ma non riesco ancora a vederne l'utilità...cioè in teoria dovrebbero semplificarmi la vita, ma poi quando vado a implementarle mi sembra solo uno spreco di tempo. Non capisco davvero perché, ho anche visto le interfacce Comparable e Iterable ma non capisco ugualmente. Scusatemi ma sono duro di comprendonio
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Shark95 ha scritto:


    per quanto riguarda le interfacce ho ancora qualche dubbio: non so perché ma non riesco ancora a vederne l'utilità...cioè in teoria dovrebbero semplificarmi la vita, ma poi quando vado a implementarle mi sembra solo uno spreco di tempo.
    Non riuscirei a spiegarti l'utilità delle interfacce meglio di quanto non facciano i post precedenti, tra l'altro le uso poche anch'io (nei miei programmi intendo, quelle del framework standard sono molto utili) e dovrei fare molta esperienza prima di essere un "buon consigliere".

    Posso darti la visione che ho io fino a questo momento, magari ti sarà utile magari no

    Ci sono delle parti di codice in cui non hai bisogno di sapere concretamente il tipo dell'oggetto che hai davanti o come è realizzato, ma ti basta sapere che ha una certa caratteristica, che può fare una determinata cosa etc.
    L'interfaccia in questi casi ti viene in aiuto, è un'astrazione posta a un livello superiore che lega in una sorta di vincolo le classi che la implementano, perché tali classi sono costrette ad avere quella certa caratteristica che l'interfaccia si prefigge di avere, o di saper fare quella certa cosa.

    Ti è già stato fatto l'esempio di Comparable, per me questo è uno degli esempi più chiari dell'utilità delle interfacce.
    Quando ordini una lista, ad esempio, non ti interessa sapere se questa contenga banane, motorini o cos'altro, ti basta sapere che la lista possa essere ordinata in un qualche modo, quindi che i suoi elementi possano essere confrontati tra di loro.
    Implementare Comparable soddisfa questo vincolo, tu stai dicendo che è possibile confrontare gli elementi di una certa classe, quindi potranno anche essere ordinati.

    Potresti chiederti nel tuo esempio a cosa serva un'interfaccia Volatile, visto che stai utilizzando anche una classe astratta Uccello, che può sembrare molto simile a un'interfaccia ma ti permette in più di "definire uno scheletro dei metodi".

    Beh per prima cosa deve essere utile per te avere qualcosa che modelli solo il concetto di Volatile, senza nulla di più (ovviamente esistono volatili che non siano anche uccelli).
    Nel senso che ci sarà nello specifico qualche metodo in un'altra classe (in generale non è detto che debba esistere per forza subito, può anche essere utile prevederne l'esistenza) che avrà a che fare con un Volatile, ad esempio ricevendolo come argomento di un metodo, aspettandosi di poter richiamare il metodo vola su quel volatile senza preoccuparsi del tipo effettivo di Volatile che avrà concretamente.
    Se pensi che questo non possa esserti utile in nessun modo, forse non hai bisogno di scrivere l'interfaccia Volatile.

    In secondo luogo potresti chiederti perché non definire Volatile come classe astratta, visto che ti eviterebbe lo "spreco di tempo" di definire il metodo vola nelle classi che potrebbero ereditare la versione base del metodo, senza doverne fare l'ovveride.
    Una prima risposta a questa domanda è che le interfacce sono molto più flessibili di una classe astratta: il vincolo di eredità è forte, perché una classe può estendere una sola classe per volta, mentre può implementare diverse interfacce.

    Immagina di aver definito una gerarchia di classi in questo modo, dove Volatile è una classe astratta come Uccello :
    
    Volatile -> Uccello extends Volatile -> Pinguino extends Uccello
                                         -> Aquila extends Uccello
    					                 -> ....
    	     -> Pipistrello extends Volatile
    

    A un primo sguardo la cosa potrebbe funzionare, la classe Volatile avrà il metodo vola già definito, e le classi che la estendono non dovranno preoccuparsi di ridefirlo, ad eccezione di quelle che devono cambiarne il comportamento, come Pinguino.
    Uccello potrebbe aggiungere il metodo becca che non sarà più in volatile. Le sottoclassi poi avranno tutti i loro metodi propri, ad ora è irrilevante.

    Ma questo schema con solo ereditarietà è abbastanza fragile, e rischia di rompersi non appena la tua realtà di interessa si allarga di poco.
    Immagina ora di avere una realtà di interesse che contiene altri mammiferi oltre al pipistrello, e di aver bisogno di scrivere metodi in Mammifero che debbano essere ereditati da tutti i figli.
    Ecco che avresti già rotto la tua gerarchia, tu vorresti che Pipistrello estendesse sia Mammifero che Volatile, per poter ereditare le caratteristiche di entrambi, ed ovviamente non puoi fare in modo che mammifero estenda volatile o viceversa.

    Perdona l'esempio, che può sembrare parecchio stupido, ma il succo è che l'ereditarietà può causare una serie tremenda di forzature che le interfacce invece non presentano.

    Altri esempi concreti che siano un po' più adeguati non me ne vengono in mente ora, io ad esempio uso molto le interfacce del package java.awt.event, ma se non hai mai visto awt e swing per realizzare applicazioni desktop non hai familiarità con questi argomenti.

    Tieni presente che ti ho dato solo un modo di vedere la cosa, anche abbastanza banale magari, qui nel forum ci sono tanti che potranno darti indicazioni ed esempi molto più validi, che sarebbero utili anche a me
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Grazie mille ragazzi, credo di aver finalmente capito.
    In sostanza l'interfaccia esiste e va creata e poi implementata perché (se ho capito bene) nel momento in cui io vado ad istanziare gli oggetti, per usare i metodi che hanno in comune, i quali rappresentano proprio la loro caratteristica di "far tutti parte di qualcosa", è necessario creare gli oggetti con un tipo corrispondente a quello dell'interfaccia in modo tale che sfruttino i loro diversi ma anche simili metodi e far fare loro qualcosa di comune ma implementato in maniera differente.

    Ad esempio se io avessi un'interfaccia molto semplice chiamata Iterabile che dispone dei metodi:

    1- Boolean hasNext();
    2- Object next();

    e se poi io creassi due classi chiamate Tipo1 e Tipo2, le quali implementano entrambe l'interfaccia, allora significherebbe che sto ammettendo che queste due classi hanno quelle caratteristiche in comune e pertanto se io volessi iterare su questi due oggetti una volta istanziati potrei farlo dichiarando due variabili del tipo Iterabile che però sono costruite a partire dal Tipo1 e dal Tipo2, dove Tipo1 e Tipo2 rappresentano sequenze di qualche oggetto. In questo modo nello stack ci sono le due variabili riferimento che puntano ai due oggetti di tipo Iterabile nello heap, i quali a loro volta contengono gli oggetti Tipo1 e Tipo2 ecc... A questo punto potrei costruire un array con solo questi due oggetti e anziché assegnargli il tipo Object, potrei assegnargli il tipo Iterabile, ovvero sto costruendo un array di 2 oggetti iterabili (ognuno iterabile a modo suo). In questo modo se io impostassi un for each su questo array e chiamassi ogni volta che viene selezionato un elemento dell'array (per esempio) il metodo next() finché la sequenza di Tipo1 o Tipo2 non termina, mi verrebbero restituiti gli oggetti di quel tipo che formano la sequenza.
    Quindi praticamente l'interfaccia serve a fare cose di questo genere.

    Correggetemi se sbaglio.
    Grazie ancora
  • Re: [Risolto] Interfacce e implementazione realizzativa

    Lo so, non sono riuscito a spiegarlo meglio, forse del codice avrebbe reso più semplice il mio discorso.
    Comunque si io intendevo "anche" per questo genere di cose
    Ora cerco di fare un po' di esercizi e poi passerò alle interfacce funzionali e alle espressioni lambda.
    Grazie a tutti per il prezioso aiuto.

    P.S. Per chiudere la discussione devo anteporre [risolto] al titolo?
Devi accedere o registrarti per scrivere nel forum
13 risposte