PPX.2 Object Orientation .

PPX.2 Object Orientation .

INTRODUCO I CONCETTI


CONFRONTO

PROGRAMMAZIONE PROCEDURALE
  • dati memorizzati in variabili
  • agisco sui dati per mezzo di funzioni
PROGRAMMAZIONE OOP
  • i dati sono strutturati differentemente, quindi si chiamano oggetti, caratterizzati da
    • stato → serie di variabili (attributi) che caratterizzano l’oggetto
    • comportamenti (metodi) che agiscono sullo stato dell’oggetto modificandolo o ispezionandolo
  • VANTAGGIO = INCAPSULAMENTO = modificare lo stato di un oggetto per mezzo dei suoi attributi
    • ogni oggetto incapsula al suo interno sia i dati (nella forma di attributi o variabili) che le funzioni (nella forma di metodi) che operano su questi dati. Sono intoccabili dall’esterno, e li creo ioo!!

ESEMPIO PRATICO

1. Definizione della Classe Auto

public class Auto { // Attributi (variabili di istanza) private String modello; // Modello dell'auto private String colore; // Colore dell'auto private int velocita; // Velocità dell'auto // Costruttore della classe public Auto(String modello, String colore) { this.modello = modello; this.colore = colore; this.velocita = 0; // Inizializza la velocità a 0 } // Metodo per accelerare public void accelera(int incremento) { velocita += incremento; // Aumenta la velocità System.out.println("L'auto accelera a " + velocita + " km/h"); } // Metodo per frenare public void frena(int decremento) { velocita -= decremento; // Diminuisce la velocità if (velocita < 0) { velocita = 0; // Assicura che la velocità non sia negativa } System.out.println("L'auto frena a " + velocita + " km/h"); } // Metodo per ottenere il modello dell'auto public String getModello() { return modello; // Restituisce il modello } // Metodo per ottenere il colore dell'auto public String getColore() { return colore; // Restituisce il colore } }

2. Utilizzo della Classe Auto

public class Main { public static void main(String[] args) { // Creazione di un oggetto Auto Auto miaAuto = new Auto("Fiat 500", "Rosso"); // Chiamata ai metodi dell'oggetto miaAuto.accelera(50); // L'auto accelera a 50 km/h miaAuto.frena(20); // L'auto frena a 30 km/h // Accesso agli attributi tramite i metodi System.out.println("Modello: " + miaAuto.getModello()); // Modello: Fiat 500 System.out.println("Colore: " + miaAuto.getColore()); // Colore: Rosso } }
Ha creato l’oggetto auto, definito degli attributi (modello, colore, velocità) e definito dei metodi (accelerare, frenare, visualizza modello, visualizza colore) → attributi e metodi costituiscono la classe.
  • Quindi decido io oggetto, attributi e metodi secondo le mie necessità!!!
  • Tutti gli oggetti della stessa classe hanno stessi metodi e stato.
Prima di creare e utilizzare l’oggetto devo definire la classe, ovvero il tipo di dato in cui il mio oggetto può rientrare.
Quindi in ordine abbiamo:
  1. definisco la classe
    1. stato → attributi (variabili)
    2. metodi (operazioni sulle variabili)
  1. creo e utilizzo degli oggetti

CASO SPECIFICO

Classi prive di stato e contenenti solo metodi → si applicano solo a dei parametro

PRIMI APPUNTI SINTATTICI (molto generico)

  • il programma va scritto dentro il metodo main, contenuto nella classe Main. Per convenzione il metodo inizia per minuscola e la classe per maiuscola
  • le classi iniziano con la lettera maiuscola
    • public class Main { public static void main(String[] args){ //...convenuto... } }
PACKAGE
  • insieme di classi, interfacce e sotto-package
  • per convenzione hanno lo stesso nome della cartella in cui si trova il file
  • ora non mi serve
IMPORT
  • utilizzare le classi di un pacchetto senza dover specificare il package corrispondente ogni volta.
  • non posso fare import di 2 classi con stesso nome
  • ESEMPI:
COMPILAZIONE
  • compilare = creare eseguibili = file che saranno letti dalla macchina per eseguire il programma
  • java compila in bytecode per permettere a qualsiasi computer di eseguire il programma. Infatti il btyecode può essere tradotto da qs pc grazie ad una virtual machine che si occupa di tradurlo in linguaggio macchina (quello specifico del pc in cui esso si trova)

2 TIPI DI VARIABILI (nello stack)

  • primitivi
    • generati sullo stack
    • Esempi: int, char, double, boolean, etc.
  • riferimento
    • L'heap è la parte della memoria in cui vengono allocate le istanze delle classi, cioè gli oggetti
    • gli oggetti non sono generati sullo stack, nello stack hanno solo un riferimento (puntatore) che indica la loro posizione nell’heap
    • Esempi: ArrayList e nome delle classi
      • dato i un riferimento a array (nota che in Java se stampi il riferimento esce l’indirizzo di memoria, non il contenuto dell’oggetto puntato)

OGGGETI MUTABILI E IMMUTABILI

  • MUTABILITA’: Un oggetto è mutabile se i suoi campi possono essere modificati dopo che l'oggetto è stato creato. Questo può accadere in vari modi, come la presenza di metodi che modificano lo stato (metodi setter) o la modifica diretta degli attributi.
  • IMMUTABILITA’: Un oggetto è immutabile se il suo stato interno non può essere modificato dopo che l'oggetto è stato creato. Per creare oggetti immutabili, in genere segui queste regole:
    • Tutti i campi devono essere privati e final.
    • Non devono esserci metodi setter o altri metodi che modificano i campi interni.

STACK VS HEAP

  • Stack: struttura di memoria di tipo LIFO (Last In, First Out), dove gli elementi vengono aggiunti e rimossi in ordine inverso rispetto a come sono stati aggiunti.
    • allocazione statica: la dimensione delle variabili deve essere nota a tempo di compilazione.
    • quando una funzione termina, tutte le variabili locali vengono automaticamente rimosse.
  • Heap: struttura di memoria utilizzata per l'allocazione dinamica della memoria
    • allocazione dinamica: la memoria nell'heap può essere allocata e liberata in qualsiasi momento durante l'esecuzione del programma.
    • utilizzato per allocare memoria per oggetti e dati che devono persistere oltre la vita della funzione che li ha creati

COME CREO ATTRIBUTI?

SPIEGAZIONE INTRODUTTIVA E INCOMPLETA, vai qui
Per completezza ho definito una classe con tutte le sue proprietà ma mi concentro sugli attributi
public class Auto { private String modello; private String colore; // Costruttore public Auto(String modello, String colore) { this.modello = modello; // Inizializza l'attributo colore this.colore = colore; // Inizializza l'attributo colore } // Metodi public void mostraDettagli() { System.out.println("Modello: " + modello + ", Colore: " + colore); } }
  • modificatori di accessi: public / private parole chiave utilizzate per controllare l'accesso ai membri di una classe (attributi e metodi)
    • private = esempio di incapsulamento
    • ES. private String colore; : significa che l'attributo colore è accessibile solo all'interno della classe Auto
  • costruttore metodo speciale utilizzato per inizializzare gli attributi (costruttore pk appunto lo userè per costruire un oggetto)
    • (specifica anche in che sequenza scrvere i parametri di un oggetto, in base all’attributo)
    • Parametri → sono variabili che vengono dichiarate all'interno delle parentesi di un metodo (o di un costruttore). Quando il costruttore viene chiamato per creare un nuovo oggetto, i valori forniti durante questa chiamata vengono passati ai parametri → come le funzioni
    • Attributi → con private ho specificato il tipo di accesso e creato l’etichetta, invece nel costruttore assegno un parametro ad un attributo
      • non puoi assegnare più parametri a un singolo attributo
      • this.modello = modello;
        • traduzione: this."attributo" = "parametro";
        • this. è usato per distinguere l’attributo dal parametro quando corrispondono

GESTIONE DELLA MEMORIA

  • Attributo: alloca memoria solo nel momento in cui creo un oggetto in cui lo uso
  • Parametro; alloca memoria solo quando gli assegno un valore, non appena il metodo smette di essere utilizzato la memoria del parametro è deallocata
  • Oggetti: Quando crei un oggetto di una classe, l'intera istanza dell'oggetto alloca memoria per tutti gli attributi definiti nella classe. Gli oggetti sono allocati nell'heap.
    • Ogni volta che crei un oggetto utilizzando new, stai allocando memoria per tutti gli attributi di quell'oggetto.
 
 
 

FOCUS SINTASSI


INVOCAZIONE METODO DINAMIO

qui più completo
oggeto.metodo(parametro, parametro,…)
notion image
  • l’invocazione di un metodo può essere realizzato pure a partire da un altra chiamata a un metodo [riassuntivamente indicata con f(x)] che chiama un oggetto e tra i parametri posso avere altre chiamate di metodo [g(x)]
    • in verità g[x] in quanto metodo dovrebbe essere

DEFINIZIONE METODO

qui più completo
notion image
  • visibilità
    • public = ci possono accedere tutti
    • private = incapsulamento
  • scope = dove posso accedere a questo metodo
    • static = il metodo è definito su una classe (metodo di classe)
  • definisco il tipo del valore di ritorno
    • void se non ritorna nulla
  • parametri formali pk i nomi devono essere accompagnati dal loro tipo di dato
 

OVERLOADING

💡
dichiarare più metodi con lo stesso nome e diversi parametri → ad esempio valueOf(ammette interi e stringhe)
  • serve per essere pratici semanticamente anche cambiando i parametri (cambiare nome ogni volta non è efficace)
notion image
  • la chiamata è riferita al secondo caso per inferenza
 

CONVERSIONI IMPLICITE (O CASTING IMPLICITO)

notion image
  • (somma tra 2 tipi uguali ovviamente) Java sa che può convertire int in double (equivalente di float in go) senza perdita di dati in alcuno scenario possibile, quindi lo fa in automatico
SE INVECE APPLICO IL CONCETTO CON LA CHIAMATA AL METODO SOMMA?
notion image
  • Anche in questo caso fa la conversione implicita
  • Notare che Java permette di definire la chiamata ad un metodo (somma) limitandosi al solo nome (quindi poteva escludere Prova), nel momento in cui metodo e chiamata stanno nella stessa classe.
  • Notare che ciò è possibile pk il valore di ritorno del secondo metodo è un double, altrimenti avrei perdita di dati
  • RICORDA: il nome del metodo lo decido io, come le classe. Il primo inizia con la minuscola, il secondo con la maiuscola
notion image
  • qui non ci sono conversioni implicite possibili
notion image
  • AMBIGUO: in una situazione in cui gli vanno bene molteplici conversioni implicite, lui non può fare nulla

COLLEZIONI P.1 e COME DEFINIRE UN OGGETTO

COLLEZIONE = oggetto che rappresenta un insieme di elementi.
Equivalente di array e slice in Go
notion image

COME DEFINIRE UN OGGETTO: classe oggetto = new classe()

  • new è necessario se vuoi creare un oggetto di predefinito senza immediatamente inizializzarlo con valori, altrimenti puoi mettere i valori direttamente
    • per gli oggetti personalizzati devi usare new
  • CASO PARTICOLARE
    • notion image
  • Nelle collezioni posso mettere qualunque tipo di dato
    • il metodo get mi specifica il valore all’interno di una collezione specificando il l’indice
      • notion image
      • ERRORE: assegnare il valore del metodo get alla variabile i di tipo int non ha senso, pk Arraylist è generico ed io non specifico il tipo di ogni cella, quindi Java non conoscendo il tipo da ad ogni cella il tipo object. Altrimenti faccio la conversione (casting esplicito)
        • notion image
          notion image
       
    • NOTARE: che ArrayList è una classe regolare e lo capisco pk prima di utilizzare un suo metodo ho definito in oggetto (in quanto le classi statiche richiedono sintatticamente un oggetto (su cui agiranno), tra metodo e classe).
MA SE POSSO INVENTARE IL NOME DELLE CLASSI (come gli oggetti) A COSA SERVE Arraylist?
notion image
QUESTO NON SI PUO’ FARE
  • stesso indice, 2 variabili di differente tipo: compila ma non esegue (scrive ClassastExeption)
    • notion image
  • COLLEZIONE GENERICA: Arraylist
  • COLLEZIONE SPECIFICA: Arraylist<String>

SINTESI

notion image

COLLEZIONI P.2

LE COLLEZIONI SONO DI OGGETTI, NON DI PRIMITIVI (pk sono classi)
  • ci sono tipi riferimento (nella stack) che si riferiscono per praticità ai loro oggetti corrispondenti (nella heap). Quindi anche se int è primitivo posso inserirlo in una collezione come collezione grazie al suo corrispondente tipo oggetto (nella heap)
    • ogni tipo nella stack ha un corrispondente tipo nella heap (definito con la maiuscola)
      • notion image
    • wrapping è il processo con cui converto una variabile primitita nel suo corrispondente oggetto
      • notion image
    • Il metodo Integer.valueOf(int i) è un metodo statico della classe Integer che restituisce un oggetto Integer rappresentante il valore del tipo primitivo int fornito come argomento.
      • SINTESI

        notion image
      • Wrappin statico sopra → pk avvolgo il primitivo e lo metto nella heap
      • Unwrapping dinamico sotto

      SORPRESA

      Le versioni recenti di Java fanno il Boxing/Autoboxing
    • capacità di fare Wrapping/Unwrapping in automatico con una semplice equivalenza tra 2 valori di tipo di cui uno è il tipo riferimento dell’altro
    • mi permette anche di inserire un primitivo in una collezione (e viceversa)
    • OPERATORI LOGICI
      • se io comparo 2 oggetti, comparo i rispettivi riferimenti. Quindi se comparo 2 oggetti pur con stesso nome saranno diversi pk hanno diversi riferimenti.
      • per comparare 2 oggetti uso il metodo equals
        • notion image

I/O SU TERMINALE JAVA

DEFINIRE UNO SCANNER AGGANCIATO ALL’INPUT
notion image
  • Scanner classe
  • s = oggetto
  • tra parentesi metto qc a cui agganciarsi → standard input utilizzando la classe System col suo attributo in
  • s.hasNext = per vedere se c’è una striga (boeleano)
  • s.Next = ritorna la stringa
ESEMPIO CON CICLO WHILE (fintanto che)
notion image
VARIANTE CON INT
notion image
  • In questo caso da errore pk s è una stringa

COMPENDIO spiegato parzialmente

 
notion image

Caratteristiche 1° Frammento

  • Blocchi di Istruzione: Ogni condizione if, else if e else utilizza le parentesi graffe {} per racchiudere le istruzioni da eseguire. Anche se in questo caso ci sono solo singole istruzioni, l'uso delle parentesi graffe rende il codice più chiaro e permette di aggiungere facilmente più istruzioni in futuro, senza dover modificare la struttura.
  • Facilità di Espansione: Se in futuro desiderassi aggiungere più istruzioni a una delle condizioni, puoi farlo senza preoccuparti di dover inserire le parentesi graffe, il che può rendere il codice più leggibile.

Caratteristiche 2° Frammento

  • Senza Blocchi di Istruzione: In questo caso, le istruzioni all'interno delle condizioni if, else if e else non utilizzano le parentesi graffe. Ciò è consentito in Java, ma applica una regola secondo la quale se un blocco di codice ha solo una singola istruzione, le parentesi graffe non sono necessarie.
  • Compactness: Questo codice è più compatto e può sembrare più facile da leggere per chi preferisce meno righe di codice. Tuttavia, potrebbe risultare più difficile da mantenere se in futuro si desidera aggiungere più istruzioni alle condizioni.

notion image
  • n è la variabile di iterazione
notion image
notion image