Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

di il
14 risposte

Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

Ciao.
Stavo studiando un capitolo su come usare le espressioni lambda al posto delle classi anonime.
Argomento che affrontato da uno che programma in Natural for ADABAS che non è altro che un COBOL più potenziato e linguaggio procedurale al 90%, c'è da diventare matti!!!
Facendo qualche prova, mi sono imbattuto in un problema che non riesco a risolvere, ma credo che NON si passa risolvere....
visto il codice

package matrice;
@FunctionalInterface

public interface EseguiMatrice {
	void esegui();
}
e

package matrice;

public class Matrice{
	private int[] [] matrice;
	private int dimX;
	private int dimY;
	
	public Matrice (int dimX, int dimY) {
		this.dimX = dimX;
		this.dimY = dimY;
		matrice =new int[this.dimX] [this.dimY];
	}
	
	public void riempiMatrice() {
		for (int i=0; i<dimX;i++) {
			for (int j=0; j<dimY;j++) {
				//inizio futuro override
				matrice[i][j] = (int)(Math.random()*10);
				//fine futuro override
			}
		}
	}

	public void stampaMatrice() {
		for (int i=0; i<dimX;i++) {
			for (int j=0; j<dimY;j++) {
				//inizio futuro override
				System.out.print(matrice[i][j] + " ");
				if (j == dimY-1)
					System.out.println();
				//fine futuro override
			}
			//System.out.println();  commentato e messo sopra perché voglio fare override dentro il secondo for 
		} 
	}

	public void eseguiSuMatrice(EseguiMatrice eseguiMatrice) {
		for (int i=0; i<dimX;i++) {
			for (int j=0; j<dimY;j++) {
				eseguiMatrice.esegui();
			}
		} 
	}
}
i for annidati dei metodi riempiMatrice() e stampaMatrice() sono identici a meno della funzione che dovrebbero fare, 1 o 2 istruzioni.
A questo punto, ho creato una interfaccia funzionale su nuovo metodo eseguiSuMatrice, che facendo override al volo dovrebbe o creare la matrice o stamparla.
Questo per risparmiare codice, evitando di avere blocci identici. (Si fa anche su Natural)

A questo punto però mi sono perso qualcosa. non capisco dove fare override, teoricamente dove viene creato l'oggetto matrice e richiamato il metodo eseguiSuMatrice, ma ovviamente quqlcosa non va.

public static void main(String[] args) {
		// TODO Auto-generated method stub
		Matrice m = new Matrice(5,5);
		m.riempiMatrice();
		m.stampaMatrice();
		m.eseguiSuMatrice(new EseguiMatrice() {
			public void esegui() {  <<<-------   override del metodo dell'interfaccia
				matrice[i][j] = (int)(Math.random()*10);   <<<<------- ovviamente non trova matrice ne gli indici i e j
			}
		}
				);
	}
come fare override di un metodo che dovrebbe essegnare un valore e un altro che dovrebbe stanpare, dovrei farlo sulla classe Matrice.
Ho la sensazione di aver sbagliato tutto:
forse questa tecnica si usa solo se nei due metodi iniziali , si assegnano valori formule diverse? e non nel caso uno assegna e l'altro stampa?

O dovrei astrarre anche il metodo e creare una classe solo per i cicli for?
non capisco.

Qualcuno sa aiutarmi? nel frattempo modifico e faccio tentativi.

PS in Natural la procedura esegui(), funziona solo se ha una scelta, esempio:
int scelta
if scelta=1 --> stampa;
if scelta=2 --> assegna valore;

se devo fare cosi, inutile l'intefaccia funzionale, basta un metodo privato!

Grazie

14 Risposte

  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    tagan ha scritto:


    Questo per risparmiare codice, evitando di avere blocci identici.
    E questo è assolutamente ragionevole/sensato.

    tagan ha scritto:


    A questo punto però mi sono perso qualcosa. non capisco dove fare override, teoricamente dove viene creato l'oggetto matrice e richiamato il metodo eseguiSuMatrice,
    Il punto è che con un metodo

    void esegui()

    della functional interface, ci fai ben poco! Quindi va valutata bene quale FORMA deve avere la funzione, che dipende ovviamente da cosa ci devi fare sulla Matrice.

    Vuoi una "funzione" che data la locazione riga,colonna dia in output un valore? (che va bene ad esempio per riempire la matrice) Allora trovi una functional interface già fatta (in Java 8 c'è, è IntBinaryOperator) o la fai tu.
    Vuoi una "funzione" che riceve riga,colonna,valore? (va bene per stampare i valori della matrice) Allora la realizzi tu (non ce n'è una adatta a questo in java.util.function).

    E chiaramente farai metodi diversi in Matrice che ricevono una apposita functional interface.
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    Perfetto.
    Ho modificato il codice in modo che usi l'interfaccia per Riempire la matrice con numeri casiali da 0 a 9 oppure stamparla.
    sbagliavo dove fare @Override, la facevo nel main, ma per quello che doveva vare era sbagliato.
    nel main, scelgo solo cosa fare:
    
    package matrice;
    @FunctionalInterface
    public interface EseguiMatrice {
    	void esegui();
    }
    
    e
    
    package matrice;
    
    public class Matrice{
    	private int[] [] matrice;
    	private int dimX;
    	private int dimY;
    	
    	public Matrice (int dimX, int dimY) {
    		this.dimX = dimX;
    		this.dimY = dimY;
    		matrice =new int[this.dimX] [this.dimY];
    	}
    	
    	public void eseguiSuMatrice(int scelta) {
    		for (int i=0; i<dimX;i++) {
    			for (int j=0; j<dimY;j++) {
    				if (scelta == 1) assegna(i,j);
    				if (scelta == 2) stampa(i,j);
    			}
    		} 
    	}
    	
    	private void assegna(int i, int j) {
    // qui creo la classe anonima e faccio Override di cosa voglio che faccia, in questo caso riempio la matrice con int casuali
    		new EseguiMatrice() {
    			public void esegui() {
    				matrice[i][j] = (int)(Math.random()*10);
    			}
    		}.esegui();
    	}
    
    	private void stampa(int i, int j) {
    // qui creo la classe anonima e faccio Override di cosa voglio che faccia, in questo caso stampo il contenuto della matrice 
    		new EseguiMatrice() {
    			public void esegui() {
    				System.out.print(matrice[i][j] + " ");
    				if (j == dimY-1)
    					System.out.println();
    			}
    		}.esegui();
    	}
    }
    
    il main è cosi:
    
    package matrice;
    
    public class Tester {
    	public static void main(String[] args) {
    		Matrice m = new Matrice(5,5);
    		m.eseguiSuMatrice(1);  //riempi
    		m.eseguiSuMatrice(2); //stampa
    	}
    }
    
    può essere una soluzione?

    A questo punto, volevo trasformare i metodi provati "assegna" e "stampa" usando le espressioni Lambda, .....ma c'è grossa crisi
    il seguente codice non compila, è proprio sbagliato...
    
    	private void assegnaLambda(int i, int j) {
    		new EseguiMatrice() {
    			(i,j)-> matrice[i][j] = (int)(Math.random()*10);
    		}
    	}
    
    da errore sual sulle graffe dopo EseguiMatrice() che sull'espressione Lambda e non capisco perché
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    .....e niente.
    ho capito. questa è la sintassi giusta:
    
    	private void assegnaLambda(int i, int j) {
    		EseguiMatrice e = () -> matrice[i][j] = (int)(Math.random()*10);
    		e.esegui();
    	}
    
    	private void stampaLambda(int i, int j) {
    		EseguiMatrice e = () -> {
    			System.out.print(matrice[i][j] + " ");
    			if (j == dimY-1)
    				System.out.println();
    		};
    		e.esegui();
    	}
    
    cmq, che casino....!!!!
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    tagan ha scritto:


    può essere una soluzione?
    No, proprio no!


    QUESTO:
    public class ProvaMatrice {
        public static void main(String[] args) {
            Matrice mat = new Matrice(3, 4);
    
            mat.riempi((r,c) -> (int) (Math.random()*100));
            mat.consuma((r,c,v) -> System.out.format("[%d,%d] = %d%n", r, c, v));
        }
    }
    
    
    class Matrice {
        private final int righe;
        private final int colonne;
        private int[][] matrice;
    
        public Matrice(int righe, int colonne) {
            this.righe = righe;
            this.colonne = colonne;
            matrice = new int[righe][colonne];
        }
    
        // altri eventuali metodi per accedere ai valori, es. getValore() ecc...
    
        public void riempi(MatriceSupplier supplier) {
            for (int r = 0; r < righe; r++) {
                for (int c = 0; c < colonne; c++) {
                    matrice[r][c] = supplier.supply(r, c);
                }
            }
        }
    
        public void consuma(MatriceConsumer consumer) {
            for (int r = 0; r < righe; r++) {
                for (int c = 0; c < colonne; c++) {
                    consumer.consume(r, c, matrice[r][c]);
                }
            }
        }
    }
    
    interface MatriceSupplier {
        int supply(int riga, int colonna);
    }
    
    interface MatriceConsumer {
        void consume(int riga, int colonna, int valore);
    }
    
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    andbin ha scritto:


    tagan ha scritto:


    può essere una soluzione?
    No, proprio no!
    come mai un no cosi categorico?
    Il programma funziona, ma cosa non è corretto? non è Object Oriented?
    oppure scritto codice non riusabile?

    andbin ha scritto:


    QUESTO:
    public class ProvaMatrice {
        public static void main(String[] args) {
            Matrice mat = new Matrice(3, 4);
    ........................
    ........................
    ........................
    
    Ho riportato su eclipse il tuo programma....non riesco a capirlo neache con il debug!
    Sarebbe carino un articolo sul tuo blog o un post dettagliato qui sul forum.
    Se ho capito bene, hai fatto Override con le espressioni Lambda, direttamente dal metodo main.....ma come è possibile? come fa il compilatore a capire cosa sostituire?
    Non riesco a ricostruire tutte le sovrascrizioni , come fa a funzionare!

    Daresti una bella lezione e intendo una "lezione educativa" a molte persone che si avvicinano a java, ma questo è già programmazione intermedio/avanzata.
    Hai mai scritto un manuale?
    Ciao.
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    tagan ha scritto:


    come mai un no cosi categorico?
    Il programma funziona, ma cosa non è corretto? non è Object Oriented?
    oppure scritto codice non riusabile?
    Primo: è veramente "brutto" qualcosa tipo:

    m.eseguiSuMatrice(1);
    m.eseguiSuMatrice(2);

    Che vogliono dire 1, 2 ecc... ? Non è comprensibile, bisogna andare a leggere il codice del metodo !!

    Secondo: nel eseguiSuMatrice devi fare uno switch (o "catena" di if) che oltretutto l'hai messo (ovviamente) dentro il doppio for.

    Terzo: se si vuole aggiungere una nuova funzionalità devi per forza modificare quel metodo e "inventarti" tu un altro numerino. Insomma, non è "object oriented".

    tagan ha scritto:


    Ho riportato su eclipse il tuo programma....non riesco a capirlo neache con il debug!
    Se ho capito bene, hai fatto Override con le espressioni Lambda, direttamente dal metodo main.....ma come è possibile? come fa il compilatore a capire cosa sostituire?
    Non è un "override" in senso stretto. Una lambda expression DEVE essere associata e correlata ad una functional interface. E la "funzione" rappresentata dalla lambda expression deve corrispondere alla forma del singolo metodo della functional interface.

    Il mio riempi riceve un MatriceSupplier che ha il metodo

    int supply(int riga, int colonna)

    Nel main dove c'è (r,c) -> (int) (Math.random()*100)

    a) "r" e "c" vengono dedotti di tipo int (dai due parametri del supply)
    b) il tipo di ritorno della lambda è un int ed è lo stesso tipo del ritorno di supply

    Quindi la lambda "corrisponde" al metodo supply. Poi il compilatore genera il codice per fare in modo che a runtime al riempi venga passato un OGGETTO di una classe (non nota a noi) che implementa la interfaccia e il cui metodo supply è implementato con il body della lambda.

    Agli occhi del metodo riempi, quello che riceve per lui è un normalissimo oggetto di una interfaccia, su cui invocare un metodo. Infatti al riempi potresti anche passare una implementazione di MatriceSupplier fatta con una classe normale, anonymous, ecc..
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    andbin ha scritto:


    Non è un "override" in senso stretto. Una lambda expression DEVE essere associata e correlata ad una functional interface. E la "funzione" rappresentata dalla lambda expression deve corrispondere alla forma del singolo metodo della functional interface.
    Grazie per la spiegazione. il tuo programma e le tue note, le ho allegate al manuale che sto studiando.
    magari ci fossero più persone come te che si prestano a dare consigli, correggere e a spiegare queste metodologie.
    cmq è davvero difficile uscire da un modo di pensare procedurale che dura da anni. Mi avevano detto che programmare Object-Oriented era difficile......
    proverò a fare altri esempi, seguendo quanto mi hai detto.
    Ciao, grazie
    alla prossima
    tagan
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    La programmazione OOP NON E' difficile.
    E' un po' come imparare l'inglese: fino a che si ragiona in italiano e si traduce, i risultati saranno mediocri.
    Appena si inizia a pensare direttamente in inglese, le cose migliorano
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    .. carine e pressoché inutili.
    E sono anche gentile, in realtà sono totalmente inutili.
    Una grandissima fetta del java odierno è ormai una complicazione inutile, come buona parte del c++ odierno.
    Zucchero sintattico più copioso che nella Nutella
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    Beh totalmente inutili no dai, i codici altrui sono molto più leggibili con forEach e lambda.

    @tagan

    Non è difficile cambiare paradigma in sè, è proprio Java che è l'incarnazione più ostica della programmazione object oriented. Ma per fortuna c'è andbin che spiega meglio di un professore universitario
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    @+m2+: c'e' abbondanza di spazio per nuovi linguaggi di programmazione.

    Facile dire fa schifo: non costa niente.
    Dimostra di saper fare di meglio

    I linguaggi ad alto livello sono inutili? Meglio quelli a basso livello? Assembler? Esadecimale? Ottale? Andiamo direttamente in binario?
    Invece dei chip, valvole termoioniche? Ma a questo punto perche' non pallottoliere! O meglio, nodi su una cordicella
    O meno ancora!
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    migliorabile ha scritto:


    E' un po' come imparare l'inglese: fino a che si ragiona in italiano e si traduce, i risultati saranno mediocri.
    Appena si inizia a pensare direttamente in inglese, le cose migliorano
    Eh appunto, hai confermato quello che ho detto. Bisogna cambiare totalmente modo di pensare.
    e questo non è proprio cosi facile, specialmente se sei fossilizzato da 20 anni a linguaggi come Natural o visual basi e non intendo .Net ma VB6.

    Ad esempio, per creare con metodologia OOP un programma per la creazione di schedine del superenalotto (ai miei tempi esistevamno centinaia di programmi per il totocalcio, alcuni scritti addirittura in Pascal) come si dovrebbe ragionare.
    io l'unica classe che vedo è quella per le permutazioni.
    cioè, il programma io lo vedo prettamente procedurale, scegli i numeri, eventualmente le condizioni e poi fai le permutazioni.
    Cmq su questo argomento ci aprirò un altro post.
    Secondo me per chi sta studiando potrebbe non essere banale.....fammici pensare.
    Ciao.
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    Rapidamente: ho studiato probabilmente più linguaggi di tutti i partecipanti a questo thread uniti.
    ed ho scritto il mio primo videogioco assembler 6510 33 anni fa. Ho scritto programmi prima, durante e dopo java.
    etc.
    Sono essenzialmente perdite di tempo.
    Facciamo un piccolo esempio: voglio controllare un programma java.
    Come faccio?
    Questo è un esempio di programma concreto, cui dare risposta.
    che sia in assembly, java, c, lisp o forth cambia zero.
    mentre ci si pone il problema se ridefinire un operatore o stabilire il punto fisso di una ricorsione, io ho già finito, risolvendo il problema.

    I linguaggi sono strumenti per un fine, non sono IL fine.

    Puoi fare un ponte in acciaio, in cemento armato, in legno, in pietra.
    Ma il problema è il ponte, non il materiale
  • Re: Risparmio del codice, Classi anonime, Interfacce funzionali, Lambda....sto diventanto matto!

    @+m2+: mi sa che non hai minimamente capito PERCHE' ci sono tanti linguaggi di programmazione.

    E' la stessa cosa per i ponti: certi ponti si POSSONO fare in acciaio, in cemento armato, in legno, in pietra, altri NECESSARIAMENTE in acciaio, in cemento armato, in legno, in pietra. Quindi, a volte, il problema e' il pronte E il materiale (Genova insegna !).

    Tu sei ancora nella fase SEMPLICE, dove un linguaggio vale l'altro

    Visto che hai scritto programmi DOPO java, vieni dal futuro! Forte!
    E quindi nel futuro serviranno ancora i programmatori. Grande!
    Ma la domanda sorge spontanea: che ci fai qui?
    Ti hanno scacciato?

    Comunque sono daccordo sul fatto che esistono un sacco di linguaggi di programmazione assolutamente inutili: hanno fatto fortuna solo perche' il 99% di quelli che si spacciano per programmatori non sanno quello che fanno e pensano/sperano che il linguaggio copra le loro lacune.

    Come ben sai, il Vero Programmatore programma in Fortran, i mangiatori di Ciocori' in Pascal e derivati, tutti linguaggetti per femminucce

    http://www.giun.it/bb/ciocori.ht
    http://www.magicamente.net/c/1142/196/l-informatico.html
    https://www.frisby.cc/il-vero-programmatore.htm

    (ci sono un sacco di varianti sul tema )
Devi accedere o registrarti per scrivere nel forum
14 risposte