Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


[Dispenza] Programmazione III (Java e OOP), Dispense di Programmazione Orientata agli Oggetti

Dispenza scritta in Latex sulla programmazione ad oggetti e Java

Tipologia: Dispense

2019/2020

In vendita dal 08/06/2020

Anasegros
Anasegros 🇮🇹

3

(4)

15 documenti

1 / 61

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Appunti - Programmazione III
Giuseppe Cianci Pio - 0124001064
Indice lp
1 Introduzione 5
1.1 Ambiente di sviluppo e JDK . . . . . . . . . . . . . . . . . . . . . . . . . 6
2 La programmazione ad oggetti 6
2.1 Caratteristiche principali . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.1 Glioggetti............................... 7
2.1.2 Leclassi................................ 7
2.2 Lincapsulamento............................... 8
2.2.1 Il mascheramento delle informazioni . . . . . . . . . . . . . . . . . 8
2.3 Lereditariet`a ................................. 9
2.3.1 La gerarchia delle classi . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.2 Leinterfacce.............................. 9
2.4 Ilpolimorfismo ................................ 9
2.4.1 Il polimorfismo ereditario / Overriding dei metodi . . . . . . . . . 10
2.4.2 Il polimorfismo parametrico . . . . . . . . . . . . . . . . . . . . . 10
2.4.3 Il polimorfismo ad hoc . . . . . . . . . . . . . . . . . . . . . . . . 11
3 Tipi di dato 11
3.1 Il tipo di dato primitivo . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.1.1 Lapromotion ............................. 12
3.1.2 Inizializzazione ............................ 12
3.2 Tipi di dato non primitivo . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4 Java e l’OOP 12
4.1 Astrazioneeriuso............................... 13
4.1.1 Lastrazione.............................. 13
4.1.2 Ilriuso................................. 13
4.2 Incapsulamento ................................ 13
4.2.1 Il concetto dei package . . . . . . . . . . . . . . . . . . . . . . . . 14
4.2.2 I modificatori di accesso . . . . . . . . . . . . . . . . . . . . . . . 14
4.2.3 Il modificatore static ........................ 15
4.2.4 Il modificatore final ......................... 16
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d

Anteprima parziale del testo

Scarica [Dispenza] Programmazione III (Java e OOP) e più Dispense in PDF di Programmazione Orientata agli Oggetti solo su Docsity!

Appunti - Programmazione III

 - Giuseppe Cianci Pio - 
  • 1 Introduzione Indice lp
    • 1.1 Ambiente di sviluppo e JDK
  • 2 La programmazione ad oggetti
    • 2.1 Caratteristiche principali
      • 2.1.1 Gli oggetti
      • 2.1.2 Le classi
    • 2.2 L’incapsulamento
      • 2.2.1 Il mascheramento delle informazioni
    • 2.3 L’ereditariet`a
      • 2.3.1 La gerarchia delle classi
      • 2.3.2 Le interfacce
    • 2.4 Il polimorfismo
      • 2.4.1 Il polimorfismo ereditario / Overriding dei metodi
      • 2.4.2 Il polimorfismo parametrico
      • 2.4.3 Il polimorfismo ad hoc
  • 3 Tipi di dato
    • 3.1 Il tipo di dato primitivo
      • 3.1.1 La promotion
      • 3.1.2 Inizializzazione
    • 3.2 Tipi di dato non primitivo
  • 4 Java e l’OOP
    • 4.1 Astrazione e riuso
      • 4.1.1 L’astrazione
      • 4.1.2 Il riuso
    • 4.2 Incapsulamento
      • 4.2.1 Il concetto dei package
      • 4.2.2 I modificatori di accesso
      • 4.2.3 Il modificatore static
      • 4.2.4 Il modificatore final
    • 4.3 L’ereditariet`a
      • 4.3.1 La classe Object
      • 4.3.2 Ereditariet`a e costruttori
      • 4.3.3 La keyword super
      • 4.3.4 Ereditariet`a e inizializzatori
    • 4.4 Il modificatore abstract
      • 4.4.1 Ereditariet`a multipla
      • 4.4.2 Le interfacce
      • 4.4.3 Differenza fra interfacce e classi astratte
    • 4.5 Il Polimorfismo
      • 4.5.1 I reference e la loro rappresentazione
      • 4.5.2 Il polimorfismo per metodi
      • 4.5.3 Il polimorfismo per dati
  • 5 Eccezioni e asserzioni
    • 5.1 Eccezioni, errori e asserzioni
      • 5.1.1 Gerarchie e categorizzazioni
      • 5.1.2 Il lancio e cattura di un’eccezione-errore
      • 5.1.3 Meccanismo per la gestione delle eccezioni
      • 5.1.4 Try with resource
      • 5.1.5 Eccezioni principali e personalizzate
      • 5.1.6 La propagazione delle eccezioni
      • 5.1.7 Eccezioni ed override
    • 5.2 Le asserzioni
      • 5.2.1 Compilazione con assert
      • 5.2.2 Progettazione per contratto
  • 6 Classi innestate ed Enumerazioni
    • 6.1 Le classi innestate
      • 6.1.1 Classe innestate: definizione
      • 6.1.2 Classe innestate: propriet`a
      • 6.1.3 Quando usare le classi innestate
    • 6.2 Classi anonime
      • 6.2.1 Quando usare la classi anonime
    • 6.3 Gli enumeratori
      • 6.3.1 Ereditariet`a e polimorfismo con enum
      • 6.3.2 Metodi, Variabili, costruttori e tipi innestati in un’enumerazione
      • 6.3.3 Enumeratori e metodi specifici degli elementi
  • 7 I tipi generici
    • 7.1 Generics e tipi parametro
      • 7.1.1 Generics e collection
      • 7.1.2 Tipi primitivi e autoboxing-autounboxing
      • 7.1.3 L’Interfaccia Iterator
    • 7.2 Ereditariet`a dei tipi generici e Type erasure
      • 7.2.1 Le Wildcard
      • 7.2.2 Wildcard e parametri bounded
      • 7.2.3 Metodi generici
  • 8 Il package java.lang
    • 8.1 La classe string
      • 8.1.1 Metodi della classe string
    • 8.2 La classe Object
    • 8.3 La classe System
    • 8.4 La classe Runtime
    • 8.5 La classe Class e reflection
      • 8.5.1 istanziare oggetti Class
      • 8.5.2 La reflection
      • 8.5.3 Istanziare oggetti tramite Class
      • 8.5.4 Il parametro di Class
    • 8.6 Le classi wrapper
      • 8.6.1 I metodi principali delle classi wrapper
      • 8.6.2 Autoboxing-Autounboxing
      • 8.6.3 Assegnazione di null ad un wrapper
    • 8.7 Operatori di confronto e wrapper
    • 8.8 La classe Math
    • 8.9 Le interfacce Comparable e Comparator
      • 8.9.1 Comparable
      • 8.9.2 Comparator
  • 9 Le annotazioni - 9.0.1 Prima delle annotazioni
    • 9.1 Definizione di annotazioni
      • 9.1.1 Dichiarazione delle annotazioni
      • 9.1.2 Utilizzo delle annotazioni
    • 9.2 Tipologie di annotazioni
      • 9.2.1 Le annotazioni ordinarie (o Complete)
      • 9.2.2 Le annotazioni a valore singolo (o unico)
      • 9.2.3 Le annotazioni marcatrici (o segnalibro)
    • 9.3 Annotare le annotazioni: Le meta-annotazioni
      • 9.3.1 Retention
      • 9.3.2 Target
      • 9.3.3 Documented
      • 9.3.4 Inherited
      • 9.3.5 Repeatable
    • 9.4 Annotazioni Standard
      • 9.4.1 Override
      • 9.4.2 Deprecated
      • 9.4.3 SuppressWarnings
      • 9.4.4 FunctionalInterface
      • 9.4.5 Native
  • 10 La gestione dei Thread
    • 10.1 La classe Thread e la dimensione temporale
      • 10.1.1 Il thread principale (o corrente)
      • 10.1.2 Il thread secondari e l’interfaccia Runnable
    • 10.2 Il modificatore volatile
    • 10.3 La concorrenza
  • 11 Le espressioni lambda
    • 11.1 La sintassi delle espressioni lambda
      • 11.1.1 Comprendere la sintassi
    • 11.2 Espressioni lambda vs Classi anonime
      • 11.2.1 Sinteticit`a
      • 11.2.2 Regole e visibilit`a
      • 11.2.3 Dinamicit`a
      • 11.2.4 Gestione delle eccezioni
    • 11.3 Reference dei metodi
      • 11.3.1 Sintassi dei reference a metodi
  • 12 Design pattern - 12.0.1 Struttura di un Pattern - 12.0.2 Classificazione dei pattern
    • 12.1 Pattern Creazionali
    • 12.2 Pattern Strutturali
    • 12.3 Pattern Comportamentali

1 Introduzione lp

In informatica Java e un linguaggio di programmazione orientato agli oggetti a tipizza- zione statica, specificatamente progettato per essere il piu possibile indipendente dalla piattaforma di esecuzione. Uno dei principi fondamentali del linguaggio e espresso dal motto WORA (write once, run anywhere, ossia ”scrivi una volta, esegui ovunque”): il codice compilato che vie- ne eseguito su una piattaforma non deve essere ricompilato per essere eseguito su una piattaforma diversa. Si tratta infatti di un linguaggio interpretato ed il prodotto della compilazionee infatti in un formato chiamato bytecode che pu`o essere eseguito da una qualunque implementazione di un processore virtuale detto Java Virtual Machine.

Java risulta essere uno dei linguaggi di programmazione pi`u usati al mondo, special- mente per applicazioni client-server, con un numero di sviluppatori stimato intorno ai 9 milioni.

Le caratteristiche principali del linguaggio sono:

  • Sintassi: Il linguaggio deriva gran parte della sua sintassi dai linguaggi Simula, C e C++, ma ha meno costrutti a basso livello e implementa in modo pi`u puro (rispetto al C++) il paradigma object-oriented;
  • Gratuito: Open source, libero e senza la necessit`a di pagare licenze per l’utilizzo e la commercializzazione.
  • Robustezza: Attraverso un meccanismo estremamente funzionale del controllo di eccezioni e un compilatore molto ”severo” in modo tale da evidenziare gli errori in fase di compilazione piuttosto che in esecuzione. Java dispone anche di un meccanismo di gestione autonoma della memoria, il Garbage Collection che esonera il programmatore dalla de-allocazione manuale della memoria. In fine Java non permette un utilizzo esplicito dei puntatori.
  • Librerie e standardizzazione: Dispone di una grandissima quantita di libre- rie standardizzate estremamente documentate per ogni tipo di problema. In ol- tre seguendo le specifiche di oracle ogni compilatore dovra essere standardizzato produrre lo stesso bytecode per consentire la portabilit`a.
  • Indipendenza dalla piattaforma: Java viene eseguito leggendo il bytecode at- traverso una macchina virtuale, la Java Virtual Machine. In questo modo il lin- guaggio risulta estremamente portabile su qualsiasi piattaforma sia in grado di eseguirla.
  • Aperto: Il linguaggio risulta estremamente aperto e versatile e si integra bene con moltissime tecnologie e anche con altri linguaggi. In oltre essendo open source ognuno pu`o contribuire al miglioramento e all’evoluzione dello stesso.
  • semplice, orientato agli oggetti e familiare.

Quindi essenzialmente si raggruppano in una sola zona i dati e le procedure che operano sugli stessi astraendo un oggetto dalla realt`a.

2.1.1 Gli oggetti lp

Un oggetto reale `e:

  • Un oggetto e un’entita dotata di determinate caratteristiche e funzionalita. Po- tremmo dire che qualsiasi entita reale o immaginaria pu`o essere considerata come oggetto.
  • Lo stato di un oggetto `e rappresentato dai dati che ne descrivono le caratteristiche ad un certo istante.
  • Le funzionalita di un oggetto sono le operazioni che puo svolgere quando glielo si richiede (ossia quando riceve un messaggio).

Un oggetto software `e:

  • Un’astrazione di un oggetto reale dotato di un sottoinsieme delle sue caratteristiche e funzionalit`a, ovvero solo quelle necessarie alla sua modellazione e al suo utilizzo in ambito software.
  • Lo stato interno e i suoi Dati sono chiamati Attributi.
  • Le funzionalit`a e le operazioni che si possono svolgere sui dati sono chiamate Metodi.

2.1.2 Le classi lp

Viene detta classe la struttura di un oggetto, e il modello astratto da cui creare oggetti, cioe la dichiarazione dell’insieme degli elementi che comporranno un oggetto. Un oggetto e quindi il risultato di una classe. In realta si dice che un oggetto e una istanza di una classe, ragione per cui si puo parlare indifferentemente di oggetto o di istanza. Una classe `e composta da due parti:

  • Gli attributi (detti anche dati membri): Si tratta dei dati che rappresentano lo stato dell’oggetto cioe delle variabili e/o costanti che definiscono le caratteristiche o proprieta degli oggetti instanziabili invocando la classe; i valori inizializzati degli attributi sono ottenuti attraverso il cosiddetto costruttore;
  • I metodi (detti anche funzioni membri): si tratta delle operazioni applicabili agli oggetti e agli attributi dell’oggetto stesso.

Le classi dunque definiscono dei tipi di dato e permettono la creazione degli oggetti secondo le caratteristiche definite nella classe stessa. Una classe `e identificabile, dunque, come un tipo di dato astratto che descrive l’astrazione di un concetto, implementata in un software.

2.2 L’incapsulamento lp

L’incapsulamento e la proprieta per cui i dati che definiscono lo stato interno di un og- getto e i metodi che ne definiscono la logica sono accessibili solo ai metodi dell’oggetto stesso, mentre non sono visibili ai client ovvero chi utilizza l’oggetto. Per alterare lo stato interno dell’oggetto, e necessario invocarne i metodi pubblici, ede questo lo scopo principale dell’incapsulamento. Infatti, se gestito opportunamente, esso permette di ve- dere l’oggetto come una black-box, cioe una ”scatola nera” di cui, attraverso l’interfaccia,e noto cosa fa, ma non come lo fa. E dunque la tecnica di nascondere il funzionamento interno – deciso in fase di progetto

  • di una parte di un programma, in modo da proteggere le altre parti del programma e dei dati da eventuali modifiche volontarie o involontarie che porterebbero ad errori e problemi.

L’incapsulamento e un meccanismo che consiste nel raccogliere i dati e i metodi al- l’interno di una struttura nascondendo l’implementazione dell’oggetto, cioe impedendo l’accesso ai dati con altri mezzi diversi dai servizi proposti. L’incapsulamento permette quindi di garantire l’integrit`a dei dati contenuti nell’oggetto. Non si consente alle altre componenti del software (funzioni, strutture dati, modulo) di accedere ai dati se non tramite una funzione ad hoc che li manipola in modo sicuro e controllato.

2.2.1 Il mascheramento delle informazioni lp

L’utente di una classe non deve per forza conoscere in che modo sono strutturati i dati nell’oggetto, cioe none tenuto a conoscere l’implementazione. Cosı, impedendo all’utente di modificare direttamente gli attributi, e obbligandolo ad usare le funzioni definite per modificarli (dette interfacce), si assicura l’integrita dei dati (si potra ad esempio assicurare che il tipo di dati forniti sia conforme alle nostre attese, oppure che i dati si trovino effettivamente nell’intervallo atteso). L’incapsulamento permette di definire dei livelli di visibilita degli elementi della classe. Questi livelli di visibilita definiscono i diritti di accesso ai dati a seconda che vi si acceda con un metodo della classe stessa, di una classe ereditaria, oppure di una classe qualsiasi. Esistono in generale tre livelli di visibilita:

  • pubblica: le funzioni di tutte le classi possono accedere ai dati o ai metodi di una classe definita con il livello di visibilita pubblica. Si tratta del piu basso livello di protezione dei dati
  • protetta: l’accesso ai dati e riservato alle funzioni delle classi ereditarie, cioe dalle funzioni membri della classe invece che dalle classi derivate
  • privata: l’accesso ai dati e limitato ai metodi della classe stessa. Si tratta del livello piu elevato di protezione

2.4.1 Il polimorfismo ereditario / Overriding dei metodi lp

La possibilita di ridefinire un metodo in classi ereditiere di una classe di base viene detta specializzazione. E quindi possibile denominare il metodo di un oggetto senza preoccu- parsi del suo tipo intrinseco: si tratta del polimorfismo ereditario. Questo permette di estrarre dei dettagli delle classi specializzate da una famiglia di oggetto, nascondendole in un’interfaccia comune (che `e la classe di base). Permette che gli oggetti appartenenti alle sottoclassi di una stessa classe rispondano diversamente agli stessi utilizzi. Attra- verso delle funzioni di nome identico, che usate su due sottoclassi eseguono codice diverso.

Ad esempio, supponiamo di avere una gerarchia in cui le classi Quadrato e Cerchio discendono dalla superclasse Figura2D. Quest’ultima definisce un metodo getArea(), le cui specifiche sono: Restituisce l’area della figura. I due metodi getArea() definiti nelle classi Quadrato e Cerchio si sostituiscono a quello che ereditano da Figura2D e, rispettivamente, restituiscono l’aria della figura calcolata con le opportune formule.

In questo modo e possibile produrre algoritmi piu generali che consentono di operare sulle superclassi e rispondono in maniera diversa a seconda del tipo di oggetto. I metodi che vengono ridefiniti in una sottoclasse sono detti polimorfi, in quanto lo stesso metodo si comporta diversamente a seconda del tipo di oggetto su cui e invocato. Il binding ovvero il collegamento fra oggetto e il suo metodo puo avvenire in due modi:

  • Il binding statico avviene in fase di compilazione: in questa fase tutto cio chee possibile collegare staticamente viene collegato. Cerchio c(.); ... c.getArea(); → Pu`o essere fatto in fase di compilazione perch´e si conosce la classe.
  • Il binding dinamico puo avvenire solo in fase di esecuzione (run-time): in que- sta fase vengono collegati i metodi che non possono essere collegati a tempo di compilazione (perch´e mancano le informazioni su quale sia la classe reale che verra utilizzata). A tempo di compilazione non e possibile sapere a priori quale tipo di oggetto venga utilizzato tramite polimorfismo: Figura2D f(.); ... f.getArea(); → Puo essere fatto solo in run time perch´e non si conosce la classe. Quando dovra essere eseguito il metodo sull’oggetto f verra applicato il binding dinamico (chiamato anche late-binding) che andra a collegare il metodo dell’og- getto opportuno (In questo caso Quadrato oppure Cerchio ). Ovviamente cio non puo essere fatto a tempo di compilazione: quando compili la tua applicazione non sai a priori che oggetti andra a creare l’utente, che la user`a dopo...

2.4.2 Il polimorfismo parametrico lp

Il polimorfismo parametrico, detto genericita, rappresenta la possibilita di definire pi`u funzioni di nome identico ma con parametri diversi (in numero e/o tipo). Il polimorfismo parametrico rende quindi possibile la scelta automatica del metodo corretto da adottare

secondo il tipo di dato definito. Cosı, si possono ad esempio definire piu metodi omonimi addition() che effettuano una somma di valori.

  • Il metodo int addition (int, int) definisce la somma di due numeri interi;
  • Il metodo float addition (float, float) definisce la somma di due float;
  • Il metodo char addition(char, char) definisce la somma di due caratteri.
  • ecc.

Viene chiamata firma il numero e il tipo (statico) di argomenti di una funzione. E quindila firma di un metodo a determinarne il nome. E disponibile solo per linguaggi tipizzati.

2.4.3 Il polimorfismo ad hoc lp

Il polimorfismo ad hoc definisce degli operatori il cui uso sar`a diverso secondo il tipo di parametri che gli sono passati. E cos`` ı possibile effettuare un overloading dell’operatore ’+’ e fargli realizzare delle azioni diverse a seconda se si tratti di un’operazione tra due numeri interi (addizione) o tra due stringhe di caratteri (concatenazione).

3 Tipi di dato lp

Essenzialmente in Java `e possibile distinguere due tipi di dato:

  • primitivo;
  • oggetto. Qualsiasi sia per`o il tipo in Java il passaggio dei tipi alle funzioni e metodi avviene sempre per valore.

3.1 Il tipo di dato primitivo lp

Definiamo come tipi di dato primitivi i seguenti tipi:

  • Tipi interi: byte, short, int, long;
  • Tipi floating point: float, double;
  • Tipo testuale: char;
  • Tipo logico-booleano: bool;

In particolare in Java non esistono i tipi di dato unsigned essi sono codificati usando i tipi interi normali (interi con segno rappresentati con complemento a 2).

Questi dati sono detti primitivi in quanto propri del linguaggio e non derivanti da altri tipi, in Java non sono resi attraverso una classe pertanto non e possibile utilizzare metodi su di essi e la loro copia/assegnamento avviene dunque per valore. Per risolvere questo ”problema”e comunque possibile utilizzare le classi wrapper che

  • Incapusamento;
  • Ereditariet`a;
  • Polimorfismo.

Questi sono i concetti fodamentali ma ovviamente ve ne sono altri considerati ”meno importanti” in quanto non strettamente legati alla OOP.

4.1 Astrazione e riuso lp

Sono concetti non appartenenti solamente alla programmazione orientata agli oggetti ma comunque molto importanti.

4.1.1 L’astrazione lp

L’astrazione se pur non facente parte strettamente della OOP rappresenta un concetto estremamente importante. Possiamo definire l’astrazione come l’abilita di concentrarsi solamente sui dettagli veramente importanti e necessari di un’entita in modo da poterla tradurre tramite codice, dunque astraendola.

Possiamo dividere il concetto di astrazione in tre categorie:

  • Astrazione funzionale: esso riguarda prettamente le funzioni e i metodi e ci consente di astrarre un’oggetto in base alle sue funzioni e al suo utilizzo all’interno del codice, considerato solo a livello funzionale e non implementativo;
  • Astrazione dei dati: esso contiene l’astrazione funzionale e riguarda la classe i suoi attributi, metodi e dati;
  • Astrazine del sistema: esso contiene l’astrazione dei dati e riguarda le varie classi scelte per astrarre il problema e necessarie alla sua risoluzione.

4.1.2 Il riuso lp

Il riuso rappresenta un’altro elemento fondamentale e riguarda l’abilita nel riusare, ap- punto, il codice scritto nel modo piu efficace ed efficiente possibile; scrivendo un minor numero di linee di codice e riusando quelle gi`a scritte attraverso i vantaggi dell’OOP.

4.2 Incapsulamento lp

L’incapsulamento e la chiave della programmazione orientata agli oggetti, tramite si ot- tengono caratteristiche di robustezza, indipendenza e riusabilita; in oltre le operazioni di modifica e manutenzione risultano pi`u semplici al programmatore.

Il principio base `e quello di nascondere il funzionamento interno della classe, limitando il suo utilizzo e la sua modifica a dei metodi creati ad hoc che fungono da interfaccia stessa alla classe. In questo modo:

  • Ogni modifica dello stato interno della classe deve essere effettuata da opportu- ni metodi, getter e setter, che effettuando controlli sui valori permettono di garantire sempre uno stato coerente dell’oggetto.
  • Si nascondono i dettagli implementativi, mostrando solo i metodi necessari all’u- tilizzo della classe;
  • Eventuali modifiche, aggiunte di vincoli, correzioni etc... che sono localizzate solo allo stato della classe sono facilmente effettuabili semplicemnete aggionrando i metodi getter e setter e nessun’altra parte del codice.

L’incapsulamento e ottenuto attraverso i cosiddetti modificatori di accesso, ovvero delle keyword che specificano se quel determinato metodo/attributoe accessibile o meno dell’esterno della classe.

Una cosa molto importante da dire all’interno delle classi e possibile accedere agli attributi/metodi privati di oggetti dello stesso tipo della classe, infatti: public double distance ( Point p ) { return sqrt ( pow ( this .x - p .x ,2) + pow ( this .y - p .y ,2) ) ; } In questo casoe possibile accedere ad x e y come se fossero pubblici; ovviamente questo approccio e estremamente sconsigliato in quanto viola l’incapsulamento e sfavorisce la manutenibilita del codice.

4.2.1 Il concetto dei package lp

Java permette una semplice organizzazione di file e classi attraverso il concetto di Package. Essi non sono altro che cartelle all’interno delle quali sono posizionati i sorgenti delle varie classi in modo da raggrupparle e organizzarle. Per indicare l’appartenenza di una data classe ad un certo package si usa la notazione:

package .

dove con l’operatore dot si possono indicare delle sottocartelle del package. Tale istruzione deve essere la prima nel file .java. I package pero oltre a permettere l’organizzazione di classi consento anche di limitare l’accesso e la visibilita delle stesse.

4.2.2 I modificatori di accesso lp

Si tratta di paricolari keyword che consentono di limitare l’accesso ad un metodo, un attributo o una classe; essi sono alla base dell’incapsulamento.

  • public: Si tratta di un modificatore utilizzabile sia per metodi/attributi si per le classi.

Quando dichiaro un’attributo static il suo valore sara in comune con tutte le istanze della classe stessa, tuttavia tale attributo non sara inizializzato istanziando l’oggetto come di consueto, poich´e a tutti gli effetti non si tratta di una variabile di istanza.

Gli istanziatori static La keyword static puo essere utilizzata anche come marcatore per identificare un blocco di istruzioni, all’interno di una classe (ma al di fuori di un metodo), che deve essere eseguito quando la classe verra caricata in memoria, addirittura prima di un’eventuale costruttore.

... static{ System.out.println("Sono un istanziatore statico.");} ...

Dunque ogni volta che la classe e caricata in memoria verra eseguito il blocco di istruzioni definito dal modificatore. Attributi static, metodi static, inizializzatori static, imposrt static, quando usare sta- tic.

Gli istanziatori d’istanza oltre all’istanziatore static, esiste anche un’altro tipo di istanziatore, eseguito quan- do l’oggetto viene istanziato, anch’esso, prima del costruttore. Il blocco di codice da eseguire viene indicato racchiudendolo fra una coppia di parendtesi graffe:

... { System.out.println("Sono un istanziatore d’istanza.");} ...

Dunque ogni volta che la classe e istanziata verra eseguito il blocco di istruzioni definito dalle parentesi.

4.2.4 Il modificatore final lp

Si tratta di una particolare keyword il cui significato varia in base all’elemento su cui `e posto:

  • Attributi/Variabili: Si comporta esattamente come il const di altri linguaggi ren- dendo costante e immutabile il valore associato a quella variabile;
  • Metodi: Impedisce l’overriding del metodo: ovvero non `e consentito riscrivere il metodo ereditato nella classe figlia;
  • Classi: Impedisce alla classe di essere ereditata.

4.3 L’ereditariet`a lp

L’ereditarietae un’altra caratteristica estremamente importante del paradigma OOP. La programmazione orientata agli oggetti si basa appunto su oggetti che astraggono elementi ed entita presenti nella realta. Tramite l’ereditarietae possibile catturare le re- lazioni di generalizzazione o specializzazione che si vengono a creare fra due o pi`u classi, estendendo dunque la classe di partenza con nuovi attributi e metodi.

Utilizzando l’ereditarieta si viene a creare una relazione di specializzazione fra la classe base e quella derivata, in cui quest’ultima aggiunge nuovi metodi e attribuiti a quelli ereditati dalla classe base, con tutto vantaggio in termini di riusabilita, astrazione e scrittura del codice.

Gestione dell’ereditarieta Come e quali attributi o metodi sono ereditati dalle classi figlie viene gestito ad hoc dal programmatore attraverso l’utilizzo di opportuni modificatori di visibilita: public, protected, private e final.

L’ereditariet`a in Java viene effettuata ettraverso la keyword extends:

public class extends {}

4.3.1 La classe Object lp

Si tratta di una particolare classe built-in nel linguaggio che astrae il concetto di oggetto generico ogni classe ll’interno del linguaggio deriva implicitamente da essa; anche se non lo facciamo noi stessi, e il compilatore ad estendere la classe quantoe creata. Attraverso questo meccanismo `e possibile per ogni oggetto avere a disposizione i metodi ereditati dalla suddetta classe.

4.3.2 Ereditariet`a e costruttori lp

Il concetto di ereditarieta tuttavia none applicato ai costruttori poich´e per come sono stati definiti nel linguaggio:

  1. Hanno lo stesso nome della classe a cui appartengono;
  2. Non hanno tipo di ritorno;
  3. E’ chiamato automaticamente e solamente quando un’oggetto della classe a cui appartiene `e istanziato;
  4. E’ presente in ogni classe;

dunque secondo questa definizione il costruttore della classe base non potrebbe esse- re chiamato quando viene istanziata la classe figlia. Tuttavia cioe risolto attraverso un’ultima regola:

  1. Un qualsiasi costruttore (anche quello di default), come prima istruzione, invoca sempre un costruttore della superclasse.

Esso puo essere dunque considerato come l’opposto del modificatore final: Una classe final non puo essere estesa mentre una classe abstract deve essere estesa. Per ovvi motivi i due modificatori non possono essere dunque combinati.

4.4.1 Ereditariet`a multipla lp

A contrario della realta dove un’entita puo essere specializzazione di piu entita contem- poraneamente cio non e possibile in Java; ovvero none consentita l’ereditarieta multipla. Cio nasce dall’esigenza di eliminare possibili paradossi che potrebbero crearsi con un loro uso scorretto, come ad esempio: the deadly diamond of death.

4.4.2 Le interfacce lp

Le interfacce possono essere considerate un’evoluzione del concetto di classe astratta e una possibile soluzione alla mancanza di eredit`a multipla.

Le interfacce - pre-Java 8 Sino a Java 7 un’interfaccia per definizione poteva possedere solo:

  • metodi dichiarati implicitamente public e abstract;
  • variabili dichiarate implicitamente public, static e final.

Indipendentemente dal fatto che questi modificatori fossero usati o meno, infatti ancge non esplicitando manualmente questi modificatori `e il compilatore stesso ad inserirli per metodi e variabili.

Proprio come le classi, le interfacce devono essere scritte e memorizzate all’interno di file che hanno esattamente lo stesso nome dell’interfaccia che definiscono. Un’interfaccia, inoltre, non si puo istanziare poich´e none una classe; per essere utilizzata ha bisogno di essere implementata.

  • Un’interfaccia puo estendere solamente altre interfacce; rendendo possibile quindi l’ereditarieta fra interfacce.
  • Una classe puo in un certo senso essere ”estesa” attraverso interfacce con la key- word implements. La differenza sta nel fatto che una classe puo estendere un numero arbitrario di interfacce, in questo modo si e in grado di risolvere il pro- blema dell’ereditarieta multipla. Si e in grado di ereditare solamente metodi e attributi statici ma non i dati. Prima di Java 8 le interfacce potevano essere considerate come un contratto da ono- rare: avendo tutti metodi astratti ogni classe che le implementava era tenuta a definirli a meno che quest’ultima non sia anch’essa astratta. Con il passare del tempo ed in particolare con la nuova versione di Java il funzionamento delle interfaccee cambiato, sono diventate si piu potenti e versatili ma anche piu complesse.

In un’interfaccia `e illegale dichiarare inizializzatori.

Le interfacce - post-Java 8 Con le nuove versioni del linguaggio le potenzialit`a delle interfacce si sono estese, sono effettuabili operazioni che prima non erano consentite:

  • Metodi statici nelle interfacce: Da Java8 in poi e consentito utilizzare all’interno delle interfacce anche metodi statici; in realta non c’era nessun motivo perche questo non potesse accadere pri- ma, sembrava solamente ”non in linea” con l’idea originaria di interfaccia.

E’ possibile dunque creare delle interfacce che contengono solamente metodi statici e pubblici in modo da avere funzioni raggruppate da richiamare usando l’operatore dot e il nome stesso dell’interfaccia. Tali metodi non vengono ereditati dalle classi.

  • Modificatore default Da Java 8 e consentito dichiarare all’interno di un’in- terfaccia, mediante il modificatore default, dei metodi concreti; ovvero metodi che saranno ereditati dalle classi figlie senza la necessita dunque di doverli re- implementare. Se necessario sar`a comunque possibile effettuare l’overraiding riscrivendo il metodo.

Le interfacce che contengono un solo metodo astratto sono dette interfacce fun- zionali oppure SAM - Single Abstract Method, chiamate cosı perch´ee come se esistessero solamente per dichiarare una funzione da implementare.

4.4.3 Differenza fra interfacce e classi astratte lp

Essenzialmente classi astratte e interfacce sono du elementi del linguaggio molto simili tra di loro, entrambi infatti, obbligano le sottoclassi ad implementare comportamenti. Tuttavia, mentre le classi astratte rappresentano classi troppo generiche per essere istan- ziate, le interfacce rappresentano un’astrazione comportamentale che la sottoclasse deve rispettare. Infatti spesso le interfacce sono nominate con aggettivi o comportamenti, ad indicare appunto questa differenza.

4.5 Il Polimorfismo lp

Si tratta forse del paradigma OOP piu importante, potente e versatile ma al tempo stessa anche uno dei piu complessi da comprendere e implementare. Il termine polimorfismo deriva dal greco ”molte forme” ed e anch’esso un concetto deri- vato dalla realta tramite il quale e possibile riferirci con un unico termine a piu ”entita” permettendo un comportamento polimorfo del nostro codice il cui funzionamento puo essere diverso in base al contesto.