Anche se sembra una novità, la base della programmazione orientata agli oggetti è l’oggetto. Nella vita reale tutti gli oggetti hanno una serie di caratteristiche e comportamenti. Ad esempio, una porta ha colore, forma, dimensioni, materiale … (goditi una serie di funzioni) e può essere aperta, chiusa … (ha un comportamento). Nella programmazione orientata agli oggetti, un oggetto è una combinazione di dati e routine specifici che possono operare con tali dati. Quindi i due tipi di componenti di un oggetto sono:
- campi o attributi: componenti di un oggetto che memorizza i dati. Sono anche chiamati variabili membri. Questi dati possono essere di tipo primitivo () o, a sua volta, altro tipo di oggetto (ciò che viene chiamato aggregazione o composizione di oggetti). L’idea è che un attributo rappresenta una certa proprietà di un oggetto.
- Routine o metodi: è un componente di un oggetto che esegue una determinata azione o attività con gli attributi. In linea di principio, tutte le variabili e le routine di un programma Java devono appartenere a una classe. Infatti, in Java non esiste alcuna nozione di programma principale e subroutine non esistono come unità modulari indipendenti, ma fanno sempre parte di qualche classe.
9.1 Classi
Una classe rappresenta il set di oggetti che condividono una struttura e un comportamento comune. Una classe è una combinazione specifica di attributi e metodi e può essere considerato un tipo di dati di qualsiasi tipo non primitivo. Pertanto, una classe è un tipo di modello o prototipo di oggetti: definisce gli attributi che compongono quel tipo di oggetti e metodi che possono essere utilizzati per funzionare con quegli oggetti. Sebbene, invece, una classe può anche essere composta da metodi statici che non necessitano di oggetti (come classi costruiti in precedenti capitoli contenenti un metodo statico main
). La dichiarazione di una classe segue la seguente sintassi:
class IdentificadorClase { // Declaraciones de atributos y metodos ...}
Convenzione dei programmatori in Java: gli identificatori delle classi dovrebbero essere semplici , descrittivo e sostanziale e, nel caso dei nomi composti, con la prima lettera di ciascuno delle lettere maiuscole. È conveniente usare le parole complete ed evitare acronimi, a meno che l’abbreviazione non sia molto più utilizzata rispetto al modulo non abbreviato come nell’URL o in HTML
9.2 istanze
un’istanza è un’istanza Un elemento tangibile (occupa memoria durante l’esecuzione del programma) generata da una definizione di classe. Tutti gli oggetti utilizzati in un programma devono appartenere a una determinata classe.
Sebbene il termine sia talvolta utilizzato in modo impreciso, un oggetto è un’istanza di una classe predefinita in Java o dichiarata dall’utente e referenziata da Una variabile che memorizza il tuo indirizzo di memoria. Quando si dice che Java non ha puntatori, è semplicemente indicato che Java non ha puntatori che il programmatore può vedere, poiché tutti i riferimenti dell’oggetto sono in realtà puntatori nella rappresentazione interna.
In generale, accesso At attributi viene effettuato attraverso l’operatore del punto, che separa l’identificatore del riferimento dell’identificatore di attributo (idReferencia.idAtributo
). Le chiamate ai metodi per eseguire le diverse azioni vengono eseguite separando gli identificatori dal riferimento e il metodo corrispondente con l’operatore del punto ().
Semplice Esempio di classe ed istanza
Il seguente codice mostra la dichiarazione della classe Precio
. La classe Precio
è costituito da un singolo attributo (euro
) e due metodi: uno che assegna un valore all’attributo (pone
) senza restituire alcun valore e un altro che restituisce il valore dell’attributo (da
).
/** * Ejemplo de declaracion de la clase Precio * double da() --> devuelve el valor almacenado en euros * void pone( double x ) --> almacena valor en euros */public class Precio { // Atributo o variable miembro public double euros; // Metodos public double da() { return this.euros; } public void pone(double x) { this.euros = x; }}
graficamente, una classe può essere rappresentata come rettangolo.
Figura 9.1 Rappresentazione grafica della classe Precio
Il codice precedente può essere compilato:
Generazione del file bytecodes Precio.class
. Questo file non è direttamente eseguibile dall’interprete, dal momento che il codice sorgente non include alcun metodo principale (main
).Per testare il codice precedente, un altro file può essere costruito con il codice sorgente mostrato di seguito:
/** * Ejemplo de uso de la clase Precio */public class PruebaPrecio { public static void main (String args ) { Precio p; // Crea una referencia de la clase Precio p = new Precio(); // Crea el objeto de la clase Precio p.pone(56.8); // Llamada al metodo pone // que asigna 56.8 al atributo euros // Llamada al metodo da que devuelve el valor de euros System.out.println("Valor = " + p.da()); Precio q = new Precio(); // Crea una referencia y el objeto q.euros=75.6; // Asigna 75.6 al atributo euros System.out.println("Valor = " + q.euros); }}
Figura 9.2 Rappresentazione grafica del Spazio di memoria utilizzato dai riferimenti e alle istanze della classe Precio
durante l’esecuzione del metodo main
della classe PruebaPrecio
Spiegazione dell’esempio precedente
Per essere in grado di lavorare con gli oggetti dovrai seguire un processo in due fasi. La prima cosa da fare del programma è creare un riferimento o un puntatore della classe Precio
con l’identificatore p
. Simili a come viene dichiarata una variabile di un tipo primitivo, la dichiarazione di identificatore di riferimento viene effettuata con la sintassi:
identificadorClase identificadorReferencia;// En el ejemplo anterior: Precio p;
Figura 9.3 Creazione del riferimento p
Il riferimento o puntatore, p
, è come una missione per memorizzare l’indirizzo di memoria di (punto a) i componenti dell’istanza che non è stata ancora creata o referita. In questo momento si dice che il riferimento p
, rinnovato, memorizza un indirizzo di memoria null (che non corrisponde a nessun oggetto) o . La seconda fase del processo per lavorare con oggetti porta alla creazione di una nuova istanza referenziata da p
, che viene eseguita con l’istruzione:
Figura 9.4 Creazione della nuova istanza della classe Precio
Riferenziato da p
Questa operazione è anche chiamata istanziazione. Sebbene le due precedenti operazioni (creazione del riferimento e creazione dell’istanza di riferimento) possano essere eseguite in combinazione nella stessa riga di codice:
identificadorClase identificadorReferencia = new identificadorClase();// En el codigo del ejemplo anterior: Precio q = new Precio();
Figura 9.5 Creazione del riferimento q
e la nuova istanza della classe Precio
referenziato da q
Il risultato dell’esecuzione del codice precedente è due nuove istanze della classe Precio
referenziato rispettivamente da p
e e DIV ID = “58BBA6C5D6”> . L’attributo Euro di ciascuna delle nuove istanze della classe Precio
è accessibile tramite l’identificatore di riferimento e l’operatore del punto (p.euros
e ). I metodi da
e pone
appartenente alla classe Precio
sono accessibili attraverso l’identificatore del Riferimento e il punto operatore (p.da()
e p.pone(56.8)
e q.da()
e q.pone(75.6)
, rispettivamente). Nel caso dei metodi, l’istanza mediante la quale viene effettuata la chiamata corrispondente agisce come parametro o argomento implicito del metodo.
Se un riferimento all’altro è assegnato da un’istruzione di assegnazione, non vengono copiati I valori degli attributi, ma che un’unica istanza è stata rivolta a due diversi riferimenti. Ad esempio:
q = p; // Ahora p y q referencian al mismo objeto
Figura 9.6 Risultato dell’assegnazione dei valori tra i riferimenti
in questo caso. Cosa succede con l’istanza precedentemente referenziata da q
? Detta istanza è lasciata senza riferimento (inaccessibile). Questo può essere un problema in alcuni linguaggi di programmazione, come il caso di Pascal o C, che utilizzano variabili dinamiche e che hanno bisogno di liberare esplicitamente lo spazio nella memoria riservata per le variabili che si smetteranno. La gestione dinamica della memoria è solitamente un compito ingombrante per il programmatore e molto data alla proliferazione degli errori di esecuzione. Per evitare tali inconvenienti, Java ti consente di creare tanti casi come desiderato (con l’unica limitazione della memoria che è in grado di gestire il sistema), senza che il programmatore dovesse preoccuparti di distruggere o liberarli quando non sono più necessari.L’ambiente di esecuzione Java elimina automaticamente le istanze quando rileva che non verranno utilizzate (quando si smetteranno di essere referenziati). Questo processo si chiama Garbage Collection o Collection (Garbage Collection).
9.3 Modificatori di visibilità
Il modificatore indica che il componente del componente del componente del componente Il metodo è accessibile al di fuori del codice della classe a cui appartiene il componente attraverso l’operatore del punto. Il modificatore private
indica che il componente è accessibile solo attraverso i metodi della classe stessa. Il modificatore protetto sarà visto in seguito. Nel seguente codice, l’attributo è dichiarato euros
con il modificatore private
.
/** * Ejemplo de declaracion de la clase PrecioPrivado * double da() --> devuelve el valor almacenado en euros * void pone( double x ) --> almacena valor en euros * euros --> Atributo de acceso privado */public class PrecioPrivado { // Atributo o variable miembro private double euros; private double euros; // Metodos publicos public double da() { return this.euros; } public void pone(double x) { this.euros = x; }}
Se un altro codice è costruito che tenta di utilizzare direttamente l’attributo euros
:
/** * Ejemplo de uso de la clase PrecioPrivado * double da() --> devuelve el valor almacenado en euros * void pone( double x ) --> almacena valor en euros * euros --> Atributo de acceso privado */public class PruebaPrecioPrivado { public static void main (String args ) { PrecioPrivado p = new PrecioPrivado(); // Crea instancia p.pone(56.8); // Asigna 56.8 a euros System.out.println("Valor = " + p.da()); // Asigna 75.6 a euros - ERROR p.euros=75.6; System.out.println("Valor = " + p.euros); // Tambien ERROR }}
Si verificherà un errore di compilazione:
$>javac PruebaPrecioPrivado.javapruebaPrecioPrivado.java:15: euros has private access in precioPrivado p.euros=75.6; ^ pruebaPrecioPrivado.java:16: euros has private access in precioPrivado System.out.println("Valor = " + p.euros); ^
Dal momento che l’attributo è accessibile solo tramite i metodi del metodo da
e pone
.
.
.
Utilizzo del modificatore private
serve per implementare una delle caratteristiche di programmazione orientate agli oggetti: l’occultamento di informazioni o incapsulamento. Parlando rigorosamente, la dichiarazione come pubblico di un attributo di una classe non rispetta questo principio di occultamento dell’informazione. Ritenendoli come privati, non si dispone dell’accesso diretto agli attributi dell’oggetto al di fuori del codice di classe corrispondente e non è possibile accedere solo indirettamente attraverso i metodi forniti dalla classe stessa. Uno dei vantaggi pratici di forzare l’uso di un metodo per modificare il valore di un attributo è quello di garantire la coerenza dell’operazione. Ad esempio, un metodo che assegna il valore all’attributo euros
di un oggetto della classe Precio
può garantire che un valore negativo non sarà assegnato.
9.4 Classi nidificati e interni
Una classe B può essere definita come membro di un’altra classe A. La struttura sintattica è la seguente:
class ClaseA { ... class ClaseB { ... }}
Si dice che ClaseB
è una data classe in ClaseA
. La classe nidificata può essere utilizzata solo all’interno della classe del contenitore. Questo tipo di classi viene costruita solo quando la classe nidificata viene utilizzata solo o ha senso all’interno della classe del contenitore. La classe nidificata può essere dichiarata come static
. In questo caso, la classe nidificata è chiamata classe statica nidificata. Altrimenti si chiama classe interna.
9.5 L’operatore Istanceof
L’operatore instanceof
restituisce TRUE o FALSE se un oggetto appartiene o non una data classe. Sintassi:
identificadorInstancia instanceof identificadorClase