Spiegazione dei principali termini utilizzati nella programmazione ad oggetti.
La programmazione ad oggetti nasce dalla necessità di creare un progetto facilmente realizzabile, portabile e aggiornabile. Per raggiungere questi obbiettivi vengono creati dei moduli (classi) ognuno dei quali con compiti ben definiti. Ogni classe deve essere il più possibile indipendente dalle altre, ma nonostante questo, se necessario deve poter comunicare con altre classi/oggetti.
Classico esempio di utilizzo delle classi è il modello ISO-OSI. E' composto da 7 diverse classi, ognuna padre della classe di livello inferiore (esclusa la classe del livello fisico). Nonostante le diverse caratteristiche ogni classe comunica con quella di livello inferiore tramite interfaccia e comunica con classi di livello paritario tramite protocolli.
Gli ADT:
La definizione di oggetto nasce da quella di ADT: Abstract Data Type (tipo di dato astratto). Un ADT è un insieme di variabili e di funzioni che agiscono sulle variabili. Inoltre ADT di tipo diverso devono essere in grado di comunicare tra di loro.
Non sarebbe infatti corretto agire sulle variabili dell'oggetto dall'esterno di esso. Questo per avere la massima indipendenza, infatti se il codice o altri dettagli dell'oggetto dovessero cambiare (nome variabili interne, tipo di una certa variabile etc...) lasciando però intatta la funzionalità dell'oggetto, ogni programma che lo utilizzava deve poter continuare ad essere perfettamente funzionante. Inoltre questo permette di creare o modificare un progetto con una logica modulare senza preoccuparsi per quanto possibile del codice di altre classi, di chi lo ha scritto o dei programmi che ne fanno uso. Nonostante questo spesso è utile creare delle parentele tra oggetti in modo che una classe erediti proprietà da una classe padre non dimenticando però che ogni classe deve essere per quanto possibile indipendente dalle altre. La progettazione di un programma ad oggetti viene fatta attravesro lo standard UML che permette di dividere un problema in una serie di sottoproblemi logicamente divisi in classi di appartenenza.
Classe: ogni classe è un insieme di oggetti che hanno le stesse proprietà. Si parla di classe nella parte di codice dove viene definita e dichiarata, oppure nella parte di analisi di un progetto.
Oggetto: quando si crea una variabile di una classe la variabile si chiama oggetto.
Metodo: funzione appartenente ad una classe/oggetto
Proprietà: variabile appartenente ad una classe/oggetto
Istanza: creazione di un oggetto di una certa classe. Un oggetto viene istanziato quando, in una porzione di programma, si assegna ad una variabile (spesso un puntatore) una porzione di memoria in vengono caricate proprietà e metodi della relativa classe.
Definizione e dichiarazione: porzione di codice che definisce le proprietà ed i metodi di una classe.
Ereditarietà: una classe che viene definita come figlia di un altra (o altre) ne eredita tutte le proprietà ed i metodi.
Costruttore: in una classe può essere presente uno o più metodi che vengono definiti con lo stesso nome della classe (tra loro si differenziano per tipo o numero di argomenti). Questo metodo viene invocato automaticamente quando un oggetto viene istanziato e solitamente serve per inizializzare le proprietà dell'oggetto. Se una classe ha uno o più padri anche i costruttori dei padri vengono automaticamente invocati.
Distruttore: in una classe può essere presente un solo metodo distruttore che viene invocato quando un oggetto viene distrutto tramite "delete NomeVariabileOggetto;". Solitamente veniva utilizzato per deallocare la memoria occupata dall'oggetto, ormai nei linguaggi orientati agli oggetti (C++, java, visual C++, Delphi, etc...) l'operazione di deallocazione viene eseguita in automatico. Il distruttore è definito con la sintassi " ~NomeClasse () " (senza argomenti).
Invocazione: un metodo viene invocato quando una certa porzione di codice ne fa uso.
Overloading: una classe figlio può ridefinire (quindi usando stesso nome metodo, numero e tipo argomenti ) un metodo definito nella classe padre. Se viene invocato verrà utilizzato quello della classe figlio, come se nella classe padre non esistesse.
--NUOVO CHIARIMENTO -- Con il termine overloading si indica principalmente la definizione,in una stessa classe,di più funzioni con stesso nome ma argomenti differenti.IN JAVA è inoltre possibile effettuare un overloading in classi figlio ridefinendo metodi della classe padre anche utilizzando la medesima firma. Non servono particolari parole chiave per effettuare questa operazione, e non è obbligatorio invocare il metodo ridefinito della classe padre, nonostante spesso sia utile. Questa particolare operazione di ridefinizione di metodi con uguale firma prende anche il nome di Overriding
--FINE NUOVO CHIARIMENTO--
Overriding: Particolare operazione di overloading su metodi con uguale firma ma appartenenti a classi diverse, ma in parentela tra loro. Spesso in un metodo ridefinito è utilizzata l'invocazione di un metodo della classe padre nella definizione della classe figlio. Se ne fa spesso uso per invocare il costruttore della classe padre o per invocare metodi in overloading (sempre dalla classe figlio verso una delle classi padri).
Interfaccia: Metodo di collegamento tra due o più oggetti che permette il trasferimento di dati da uno all'altro.
this: Parola chiave che viene utilizzata solo all'interno di una classe. "this" indica l'oggetto che ha invocato il metodo. Solitamente this è indicato come l'oggetto (e non la classe!) che attualmente stà eseguendo il metodo.
Presto un box esplicativo con esempi IN JAVA.
Confusione
C'è un po' di confusione tra la definizione di overriding ed overloading: overriding è la ridefinizione di un metodo in una classe figlia di un metodo definito in una classe padre, oveloading è la definizione di più metodi con lo stesso nome ma firma diversa, ovvero i parametri invocati sono differenti per numero, tipo od entrambi.
RispondiTrova Massimo di un oggetto
Ho un piccolo problema con un programma. Dopo aver creato una lista di oggetti con costo,nome e tipologia.inserendo un nome vorrei trovare l'oggetto con costo massimo con quel nome.Come posso fare?qualcuno di voi potrebbe aiutarmi?
RispondiRe:File in java
L' argomento che chiedi non e' semplice ma neanche impossibile comunque ci vorrebbe + di un topic per affrontare in modo esauriente i File in java. Comunque io ti consiglio di andare a visitare il sito ufficial www.sun.com o www.jguru.com dove troverai ottimi tutorial, altrimenti se hai difficolta' con l' inglese prova a cercare -mattone su mattone- una buana guida in italiano che con qualche ricerca puoi trovare sul web. Buon Lavoro!!!
RispondiFile in java
Vorrei sapere se è possibile come creare nel linguaggio java, i file di oggetti, possibilmente in modo comprensibile! Grazie
Rispondialtre fonti terminologiche
Devo scrivere un articolo *in italiano* sull'applicazione della programmazione ad oggetti nelle scienze sociali, ma trovandomi in America mi mancano fonti su OOP in italiano. Questa termonologia e' utile ma limitatissima... Esistono altri siti o risorse WWW? Grazie in anticipo per qualsiasi suggerimento.
Rispondibello ma..
a parte che imo la pila ISO/OSI non c'entra nulla con le relazioni padre figlio.. bell'articoletto :)
Certo, sarebbe più interessante se si parlasse di Python (2.3) o Ruby o Smalltalk, insomma roba veramente a oggetti (no, java non è completamente a oggetti, checchè se ne dica)
Re: risposta
Sono d'accordo con te con cio' che dici sulle differenze tra i vari linguaggi che rendeno ognuno di questi importanti per il loro scopi.
D'altraparte con il termine overloading continuo a dissentire.
Cio' che viene detto da Al e' corretto, se non ci sono dimenticanze la memoria e' gestita correttamente (altrimenti sarebbe un bel problema), spesso pero' in un programma di grandi dimensioni possono sfuggire diverse allocazioni che sicuramente non sfuggono al garbage collector di Java che si occupa appunto di deallocare tutte le risorse allocate che non hanno piu' riferimenti. In Java non esiste l'operatore delete perche' la deallocazione e' automatica, in C++ non lo e' e dobbiamo chiamare delete per ogni singolo oggetto (o zona di memoria) allocato.
Questo e' tutto. Infine mi scuso se sono stato (e lo sono stato) un po' scortese ma non ci sarebbero discussioni se fossimo stati gia' d'accordo. Io ci metterei un bel Ciauz!
PS:
daltra parte anche quelli che hannibal chiama oggetti interni sono oggetti creati (new) e distrutti (delete) a loro volta, dunque il problema non sussiste a meno di mancanze dei programmatori......
Rispondirisposta
la risposta sull'overloading era:
daltraparte è così....
(mi scuso per non averlo puntualizzato, ma mi sembrava abbastanza chiaro)
In ogni caso sono daccordo per quanto riguarda il C.E' sicuramente uno dei linguaggi migliori prorpio per la libertà che lascia al programmatore e per la velocità d'esecuzione data la mancanza di quasi ogni tipo di controllo su dati,spazi di memoria etc...l'unico motivo per cui preferisco il Java (o il PHP spesso) è per la portabilità del programma che spesso in C causa diverse problematiche per chi programma. Daltraparte tutto si paga, o in velocità o in memoria o in portabilità o in molte altre cose.
Addio
Java Vs C++? No! Java & C++
Sfortunatamente non hai mai avuto bisogno di ottime prestazioni se hai usato linguaggi come Java per programmare ad oggetti. Il C/C++ da la possibilita' di fare quello che vuoi con la memoria grazie a quel sacrosanto e adorato tipo di variaibile che e' il puntatore. Nel C++ che e' un linguaggio orientato agli oggetti allochiamo e deallochiamo gli oggetti con new (che appunta alloca memoria) e delete (che appunto libera la memoria). Delete "chiama il distruttore", all'interno del distruttore dobbiamo inserire i vari delete per tutti gli oggetti o array che abbiamo allocato con "new" all'iterno delle funzioni della classe. Ora non si tratta di reimplementare new, delete, malloc, free e quant'altro, piuttosto di utilizzarne per allocare, deallocare la memoria al momeno opportunita' il che da al programmatore una flessibilita' incredibile, oltre che diversi grattacapi non nego. Non si lavora su handle di oggetti, ma sui loro indirizzi veri e propri.
"continuando a creare e distruggere lo stesso oggetto di uno stesso programma senza scrivere alcun codice nel distruttore la memoria si dovrebbe riempire fino ad ottenere un errore e' cosi'?"
Se all'interno del tuo oggetto non hai chiamato nessuna new allora non ci sara' spreco di memoria, ma se lo hai fatto saranno guai.
Java ha uno strettissimo controllo, questa capacita' di evitare questi errori hai nominato e' impossibile per un linguaggio come il C. Java e' infatti un ottimo linguaggio ma con finalita' differenti, non voglio fare Java Vs C++. Tutto cio' che hai scritto non risponde pero' alla questione dell'overloading...
Sono comunque d'accordo con tu di terminare questa disputa. Il diretto interessato non manchera' di scrivere un interessante infobox sull'argomento.
daltraparte è così.....e basta sull'argomento
Per fortuna, da quando programmo adoggetti non ho mai dovuto scrivere inutili costruttori e distruttori che allocano e deallocano lo spazio in heap per l'oggetto appena instanziato o distrutto.Solitamente in un linguaggio orientato agli oggetti sarebbe alquanto deficitario per il programmatore dover avere l'obbligo di allocarsi volta per volta la memoria da destinare ad ogni singola variabile/oggetto che viene instanziata,questa miriade di operazioni si esegue con una "new" per l'intera allocazione o con una "delete" per la deallocazione.Quando dall'ANSI C si passò al C++ si pensò di gestire automaticamente queste operazioni visto che erano logicamente gestibili e ripetitive.Certo, che chi ha pensato bene che sarebbe stato limitativo non permettere ad un programmatore di allocare o deallocare memoria a suo piacimento.Sicuramente molte volte può essere utile quando non si riesce a pensare come realizzare una gestione completamente ad oggetti.Inoltre chi ha scritto il compilatore deve aver pensato che comunque se un programmatore avrebbe voluto rieseguire le stesse operazioni già implementate non sarebbe stato un problema,solo un inutile spreco di codice.
In ogni caso se avessi ragione per quanto riguarda la memoria, continuando a creare e distruggere lo stesso oggetto di uno stesso programma senza scrivere alcun codice nel distruttore la memoria si dovrebbe riempire fino ad ottenere un errore. E' cosi?
Nei linguaggi evoluti naturalmente no.
Il Java ha uno strettissimo controllo sulla memoria e sullo spazio di ogni processo,trhead e variabile (i.e. non è possibile come in C/C++ accedere ad un array dichiarato come array[n] all'indice n+k | k>0 (per evitare imprecisioni accuratamente segnalate)).Linguaggi come C++ (Visual C++ è solo a scopo esplicativo, non tecnico, daltraparte un box JUNIOR è pensato non tanto per chi conosce,ma per chi non conoscendo vuole sapere),anchessi evoluti hanno simili funzionalità ma implementate all'interno di un processo e non in un interprete esterno come accade con la JVM in Java.
Per evitare l'inutile prolungamento di questa futile disputa propongo "a chiunque fosse interessato" di scrivere un bel box che tratti di questi argomenti in modo più preciso, o magari di un intero topic sul C++, così si potrà creare un altro topic sulle differenze tra Java e C++
Overloading e oltre
Purtroppo sono costretto a rispondere perche' nonostante tutto cio' che viene detto si abusa ancora del termine overloading. Un po' di esperienza di codice ne ho anche io quindi:
non ha senso dire che si tratta di overloading quando si chiama un metodo della classe figlio uguale di nome e parametri a quello della classe madre, questo significa ridefinizione, cioe' overriding. E' proprio questa la differenza tra overloading e overriding. Inoltre cio' implica la differenza tra il binding anticipato che si ottiene tramite i metodi sottoposti a overloading e binding ritardato che si ottiene tramite i metodi sottoposti a overriding.
Inoltre ci sono altre inesattezze nell'infobox. Il distruttore di cui nell'infobox viene detto "Solitamente veniva utilizzato per deallocare la memoria occupata dall'oggetto, ormai nei linguaggi orientati agli oggetti (C++, java, visual C++, Delphi, etc...) l'operazione di deallocazione viene eseguita in automatico" e' senza subbio sottovalutato in quanto non e' affato vero che in C++ la memoria viene deallocata automaticamente, chi ha scritto probabilmente non ha mai codato in C++ e non si e' mai trovato di fronte a dei segmentation fault e ai memory leak. Inoltre dubito fortemente che VC++ possa essere considerato un linguaggio, VC++ e' un ambiente di programmazione che utilizza particolari strutture dati e classi (vedi MFC), ma non e' un linguaggio a parte.
Ancora chiarimenti
Dato l'acceso dibattito ho deciso di inserire dei chiarimenti nel BOX.In oltre vedere il link per ulteriore approfondimenti.
Oltre a questo sarebbe necessaria una conoscenza basilare di java (visto che l'argomento non è semplice e servirebbe un po' di esperienza con il codice), poichè, come ho più volte scritto, in java oltre al normale overloading è possibile eseguire un overriding, cioè un particolare overloading: in una classe figlio si ridefinisce un metodo della classe padre con uguale FIRMA (quindi nome, numero e tipo di parametri).Una volta instanziato un oggetto della classe figlio,quando il famoso metodo di cui sopra viene invocato, la JVM (java virtual machine) andrà ad eseguire il codice presente nel metodo della classe figlio,senza preoccuparsi dello stesso metodo nella classe padre, che può essere invocato dal metodo del figlio utilizzando il particolare costrutto "super.nomeMetodo()".Naturamlente se viene instanziato un oggetto della classe padre,la JVM non si preoccuparà della classe che ereditano da essa,quindi non si pone il problema.
Il linguaggio C++ è completamente diverso per molte ragoni ed è stato deciso di utilizzare un altro modo per effettuare la stessa operazione.Ma in java è stato scelto un orientamento all'indipendenza tra i moduli (classi) per cui doveva essere possibile effettuare la maggior parte delle operazioni senza dovere modificare altro codice, tra queste operazioni c'è l'overriding.
Al più presto sarà presente un link al file del corso di programmazione dell'Università degli Studi di Milano Bicocca che tratta questo argomento.
Overloading & Overriding
Il termine Overloading si indica solo per indicare una definizione/dichiarazione di un metodo/funzione con firma diversa. L'Overloading puo' esistere anche nella programmazione non orientata agli oggetti e consiste nell'assegnare lo stesso nome a due funzioni che abbiano almeno parametri diversi in tipo o in numero.
Se si parla di programmazione Object 0riented l'overloading diventa un argomento piu' delicato quando capita spesso che vogliamo definire un metodo presente nella classe padre con lo stesso nome nella classe figlio. Se nome e parametri del metodo della classe figlio non differiscono siamo in presenza di una ridefinizione del metodo (e non overloading) che sia in Java sia in C++ avviene esattamente nello stesso modo. In Java si ha pero' la possibilita' di ridefinire il metodo chiamando prima il metodo della classe base (attraverso la keyword super) e poi scrivendo codice aggiuntivo, in C++ no. Un'altra differenza in caso di ridefinizione (o overriding) e' che Java automaticamente capisce che si sta trattando un metodo che vogliamo sia polimorfico, in C++ invece per fargli capire cio' dobbiamo mettere la keyword virtual prima della definizione ma solo nella classe base e non necessariamente in quella derivata.
Se invece i parametri differiscono dal metodo base allora C++ e Java si comportano in modo differente: Java considera il nuovo metodo come un overloading del metodo di base e aggiunge tale metodo a quelli gia' disponibili nella super-classe, il C++ invece sostituisce il metodo della classe figlio a quelli della classe padre che quindi vengono nascosti.
Cio' e' stato fatto in C++ per evitare errori durante la ridefinizione. Infatti in Java si puo' accidentalmente eseguire un overloading di un metodo che in realta' si vuole ridefinire, causando cosi' errori difficili da scovare.
In sostanza le differenze (principali) tra C++ e Java riguardano solamente il secondo caso.
Ma il mio intento non era quello di paragonare C++ a Java ma quello di "criticare" la definizione di overloading data nell'InfoBox che cito: "una classe figlio puo' ridefinire (quindi usando stesso nome metodo, numero e tipo argomenti ) un metodo definito nella classe padre. Se viene invocato verra' utilizzato quello della classe figlio, come se nella classe padre non esistesse." Innanzitutto con il termine overloading non si intende "ridefinire", poi come abbiamo scritto e ribadito entrambi, si usano stesso nome ma diverso numero e tipo di argomenti, infine l'ultima frase esprime il concetto di polimorfismo. Quindi riformulerei in:
Overriding: "una classe figlio puo' ridefinire (quindi usando stesso nome metodo, numero e tipo argomenti ) un metodo definito nella classe padre".
Polimorfismo: "Se viene invocato verra' utilizzato quello della classe figlio, come se nella classe padre non esistesse."
Overloading...continua
E' vero che con il termine Overloading si indica anche una definizione/dichiarazione di un metodo con firma diversa. In pratica i metodi non sono definiti solo attraverso il nome, ma anche grazie al tipo e numero di parametri, permettendo così di definire più metodi con lo stesso nome ma che accettano diversi tipi di dati in ingresso. In una stessa classe non si possono però definire due metodi con uguale nome,numero e tipo di parametri, questo può essere fatto esclusivamente in una classe figlio,per ridefinire o modificare metodi della classe padre. In Java non serve una particolare sintassi se non per quanto riguarda l'Overriding che utilizza la parola chiave "super". In C++ è necessaria una dichiarazione formale per definire entrambi i metodi come virtuali.
RispondiOverloading
Secondo me, Java è molto più avanzato per quanto riguarda l'overloading, infatti mentre in C++ per avere un overloading su un metodo della classe padre con la stessa firma è necessario dichiarare come virtuali entrambi i metodi (sia nella classe padre che nella classe figlio), in Java non è necessario, automaticamente definendo un metodo con una firma uguale ad uno nella classe padre si effettua l'overloading. Questo principalmente perchè la classe padre potrebbe già essere stata precompilata e non potendola modificare si è vista la necessità di rendere il tutto indipendente.
RispondiTerminologia nella programmazione ad oggetti
Ciò che viene detto a riguardo di overloading mi sembre più attinente al concetto di funzione virtuale (almeno in C++) . Overloading infatti (che può essere eseguito su qualsiasi funzione o membro) prevede che il i parametri devono cambiare o in tipo o in numero.