Visualizzazione dei risultati da 1 a 6 su 6
  1. #1

    Classi astratte ed interfacce utilità

    Ciao a tutti,

    mi sto avvicinando a Java, e tra le varie cose mi sono imbattuto nelle classi astratte ed interfacce. A grandi linee ho capito come lavorano, ma non riesco a capirne l'utilità, o meglio, se comunque da queste va derivata una classe concreta che implementa i metodi definiti nell'astratta, tanto vale creare una classe ex-novo completa di metodi necessari etc senza derivarla da un'altra, oppure mi sfugge qualcosa / il vantaggio di derivare da una classe astratta o interfaccia ?

    Potete chiarirmi, o meglio, darmi un esempio pratico / vantaggioso di tale cosa ?

    Grazie

    Rick

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da rick.card82 Visualizza il messaggio
    mi sto avvicinando a Java, e tra le varie cose mi sono imbattuto nelle classi astratte ed interfacce. A grandi linee ho capito come lavorano, ma non riesco a capirne l'utilità, o meglio, se comunque da queste va derivata una classe concreta che implementa i metodi definiti nell'astratta, tanto vale creare una classe ex-novo completa di metodi necessari etc senza derivarla da un'altra, oppure mi sfugge qualcosa / il vantaggio di derivare da una classe astratta o interfaccia ?
    Innanzitutto quando vedi la parola "abstract" (su classi o metodi) devi pensare a qualcosa di "incompleto". Perché qualcosa dovrebbe poter non essere completo ... beh, questo è un discorso un po' più ampio che ti sarà più chiaro con una visione più estesa sulla programmazione ad oggetti.

    La OOP consente due cose importanti: riutilizzo del codice ed estensione/specializzazione del codice altrui. Nei linguaggi non object-oriented (es. "C") è facilissimo riusare funzioni (anche fatte da altri) ma è estremamente difficile (se non impossibile) estendere e soprattutto "specializzare" codice altrui. In OOP invece è possibile e banale grazie al meccanismo della ereditarietà.

    Ma nella OOP bisogna cercare quindi di pensare in termini di tipi che sono correlati tra di loro secondo una relazione di generalizzazione/specializzazione. Un Veicolo ha certe caratteristiche e certi comportamenti. Una Automobile la deriviamo da Veicolo, poiché saprà fare tutto ciò che Veicolo sa fare, magari con qualche operazione implementata diversamente ("specializzazione") o magari con qualcos'altro in più. Una Ferrari la deriviamo da Automobile perché anche qui farà tutto ciò che sa fare Automobile con qualcosa di meglio o in più. E così via.

    La questione di classi astratte e interfacce è per fornire degli elementi di "astrazione", per rappresentare entità più generiche o tipicamente non concrete. Spesso faccio questo esempio basilare: una gerarchia di classi per rappresentare oggetti "solidi".

    - Classe Solido
    - Classe Cubo che estende Solido
    - Classe Sfera che estende Solido
    ecc...

    Ha senso poter istanziare Solido? Solido che cosa? No, infatti non ha granché senso. Solido è un concetto generale, non qualcosa di reale, concreto che puoi misurare e toccare.
    E in Java (come altri linguaggi ad oggetti) c'è un modo per far sì che Solido possa essere definito come qualcosa di non concreto, appunto una classe "astratta". Che fa sì che la classe NON possa essere istanziata direttamente ma che debba essere estesa in qualche modo più concreto per fare qualcosa di utile e reale.

    Una interfaccia è da vedere concettualmente come una classe astratta al 100% (dimentichiamo per un attimo le novità di Java 8 sulle interfacce). La differenza tra classi astratte e interfacce sta nella ampiezza d'uso, dovuta anche e soprattutto al fatto che in Java una classe può estendere UNA sola classe ma può implementare N interfacce.
    Le interfacce quindi si possono applicare a più classi anche "trasversalmente" in gerarchie differenti. E sovente una interfaccia serve per rappresentare la capacità di saper fare qualcosa.

    Una interfaccia Pesabile che dichiara un double getPeso() potrebbe essere applicata sia alla gerarchia di Veicolo, sia alla gerarchia di Solido (con i dovuti dati necessari). Ma potrebbe anche essere applicata ad una gerarchia che ha alla base la classe Persona.
    Ultima modifica di andbin; 29-11-2016 a 00:44
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Ciao,

    il concetto mi è chiarissimo, è che faccio un po fatica a trovarne l'utilità nella pratica, nel senso:
    ovviamente non istanzio un Solido astratto, ma istanzio un Cubo che è di per se un solido, cioè, che vantaggio ho nella programmazione pratica derivare da una classe astratta?
    Se parliamo di derivare una classe da un'altra che ha già metodi e proprietà utilizzabili ne vedo l'utilità, derivare da una che ha solo definizioni senza "ciccia" dentro non riesco a trovarlo utile o forse mi manca qualche pezzo ;(

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da rick.card82 Visualizza il messaggio
    ovviamente non istanzio un Solido astratto, ma istanzio un Cubo che è di per se un solido, cioè, che vantaggio ho nella programmazione pratica derivare da una classe astratta?
    Se parliamo di derivare una classe da un'altra che ha già metodi e proprietà utilizzabili ne vedo l'utilità, derivare da una che ha solo definizioni senza "ciccia" dentro non riesco a trovarlo utile o forse mi manca qualche pezzo ;(
    Innanzitutto una classe marcata abstract può benissimo contenere metodi tutti concreti. Il principio è che se almeno un metodo è abstract, allora la classe DEVE essere marcata abstract. Ma se una classe è abstract non ha di per sé alcun obbligo di avere metodi astratti. Cosa una classe abbia di concreto o no, dipende chiaramente dal senso/livello della classe.

    In Solido, a parte il fatto che non ha senso istanziarlo, ci sono due operazioni che Solido da solo non saprebbe cosa farci: calcolare la superficie e il volume. Quindi una classe Solido potrebbe essere:

    codice:
    public abstract class Solido {
        public abstract double calcolaSuperficie();
        public abstract double calcolaVolume();
    }

    Qui in effetti è tutto astratto. Ma le sottoclassi come Cubo e Sfera, che si presume siano naturalmente "concrete", dovranno per forza di cose implementare questi due metodi. Quindi gli oggetti che istanzierai avranno sicuramente questi metodi implementati.

    E comunque con la ereditarietà entra in gioco il polimorfismo e il correlato "principio di sostituibilità": dove è richiesto un tipo X è lecito passare/assegnare un oggetto di tipo X o di un sottotipo di X. Ovunque sia richiesto un tipo Solido, è lecito passare un qualunque sottotipo, es. un oggetto Cubo o Sfera.

    Se ci fosse un metodo che riceve un array di oggetti Solido es.

    public static double totaleVolume(Solido[] solidi) { .... }

    Nota che è assolutamente lecito usare e istanziare un array di un tipo astratto. A quel punto si potrebbe fare:

    codice:
    Solido[] mieiSolidi = new Solido[2];
    mieiSolidi[0] = new Cubo( ...... );
    mieiSolidi[1] = new Sfera( ...... );
    
    double totVol = totaleVolume(mieiSolidi);

    E tutto questo sarebbe assolutamente lecito e sensato. Il metodo totaleVolume "vede" gli oggetti passati solamente come dei Solido. Ma può benissimo invocare il metodo calcolaVolume() sugli oggetti. Il fatto che calcolaVolume sia astratto in Solido NON è un problema. Gli oggetti che passi sono per forza concreti quindi in questi i metodi calcolaSuperficie/calcolaVolume CI SONO, esistono e sono usabili.
    Ultima modifica di andbin; 29-11-2016 a 10:37
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Ciao,
    da quello che ho letto le classi astratte non sono istanzanziabili, nel tuo esempio crei un array di due elementi Solido con new, non stai istanziando in questo modo?

    Forse mi sfugge un concetto, provo a spiegarmi con un esempio :
    se classe B estende (aggiungendo un suo metodo) classe A (che ha suoi metodi, variabili etc), io mi ritrovo che, se istanzio un oggetto di tipo B, ho un qualcosa che comprende tutte le caratteristiche di un tipo A pi� tutto ci� che � definito nel tipo B, quindi vedo un valore aggiunto (sfrutto tutto le caratteristiche di A in pi� aggiungo le caratteristiche implementate in B), � corretta questa cosa? La classe derivata in questo caso � sicuramente pi� ricca della classe padre ?
    In questo caso io chiaramente potrei fregarmene di come � scritto il codice dentro classe A, ne sfrutto le caratteristiche "finali" estendendola tramite la mia classe B.

    Nelle classi astratte invece, quello che sto cercando di dire, �: se comunque l'astratta padre non la posso istanziare in quanto astratta, dovr� per forza istanziare la derivata dove sono implementati i metodi che nell'astratta sono vuoti, tanto vale istanziare una classe completa di tutto senza derivarla da quella astratta (che non mi da un valore aggiunto). Oppure � una questione di scope/incapsulamento che mi sfugge?
    Cosa sfrutto di "utile" della astratta estendendola?

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da rick.card82 Visualizza il messaggio
    da quello che ho letto le classi astratte non sono istanzanziabili, nel tuo esempio crei un array di due elementi Solido con new, non stai istanziando in questo modo?
    new Solido[2] istanzia un array di tipo Solido[] (NON oggetti Solido!). Questo è lecito. Cioè è perfettamente possibile dichiarare variabili e istanziare array di tipi astratti.
    Se ciò non fosse possibile, non si potrebbero avere dei "contenitori" di oggetti che siano in grado di contenere tutti i sottotipi.

    Quote Originariamente inviata da rick.card82 Visualizza il messaggio
    se classe B estende (aggiungendo un suo metodo) classe A (che ha suoi metodi, variabili etc), io mi ritrovo che, se istanzio un oggetto di tipo B, ho un qualcosa che comprende tutte le caratteristiche di un tipo A pi� tutto ci� che � definito nel tipo B, quindi vedo un valore aggiunto (sfrutto tutto le caratteristiche di A in pi� aggiungo le caratteristiche implementate in B), � corretta questa cosa? La classe derivata in questo caso � sicuramente pi� ricca della classe padre ?
    Corretto.

    Quote Originariamente inviata da rick.card82 Visualizza il messaggio
    Nelle classi astratte invece, quello che sto cercando di dire, �: se comunque l'astratta padre non la posso istanziare in quanto astratta, dovr� per forza istanziare la derivata dove sono implementati i metodi che nell'astratta sono vuoti,
    Ti ribadisco che una classe astratta PUÒ avere costruttori, variabili di istanza e anche metodi "concreti".

    Quote Originariamente inviata da rick.card82 Visualizza il messaggio
    tanto vale istanziare una classe completa di tutto senza derivarla da quella astratta (che non mi da un valore aggiunto).
    No il valore aggiunto è appunto la "astrazione" ed anche il "contratto" che le sottoclassi concrete devono rispettare andando ad implementare quei metodi eventualmente astratti.

    Se Cubo/Sfera non derivassero da Solido (ma solamente implicitamente da Object), allora in Cubo potresti avere un getVolume() e un getSuperficieCalcolata() mentre in Sfera potrebbe esserci un calcolaIlVolume() e un calcolaLaSuperficie().

    Entrambi sanno calcolare volume/superficie ma con nomi di metodi differenti e quindi NON potresti "accomunarli" usando un tipo più generico. Potresti metterli in un array di Object ( Object[] ) ma Object non "sa" nulla di questi metodi e quindi NON potresti invocarli.
    Insomma non avresti una "astrazione" di questi due tipi.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.