> For the complete documentation index, see [llms.txt](https://checksound.gitbook.io/corsojava/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://checksound.gitbook.io/corsojava/nested-classes.md).

# Nested Classes

### Static nested classes

```java
public class WireFrameModel {

   . . . // other members of the WireFrameModel class
   
   static public class Line {
         // Represents a line from the point (x1,y1,z1)
         // to the point (x2,y2,z2) in 3-dimensional space.
      double x1, y1, z1;
      double x2, y2, z2;
   } // end class Line
   
   . . . // other members of the WireFrameModel class
   
} // end WireFrameModel
```

Il nome completo della **nested class** è `WireFrameModel.Line`. Questo nome può essere utilizzato ad esempio per dichiarare le variabili. All'interno di WireFramaModel un oggetto di tipo Line, sarebbe dichiarato con `new Line()`. All'esetno della classe contenitore con `new WireFrameModel.Line()`.&#x20;

Una **static nested class**, ha accesso completo ai membri statici della classe contenitore, anche se sono membri privati.

### Inner class

Una nested class non static, è chiamata una **inner class**. Una Inner class, non è in pratica molto differente da una nested class, ma una non-static nested class è associata con un oggetto piuttosto che con la classe al cui interno è definita.

I membri non statici di una classe specificano cosa verrà contenuto negli oggetti che sono creati dalla classe. Lo stesso è vero per le inner class. Cioè ogni oggetto che appartiene alla classe contenitore ha la sua copia della nested class. Questa classe ha accesso a tutti i membri e metodi d'istanza dell'oggetto anche se sono dichiarati `private`. Le due copie dell'inner class in due oggetti differenti differiscono perché le variabili d'istanza e i metodi d'istanza a cui si riferiscono sono in oggetti differenti. In effetti, la regola per decidere se una nested class, devono essere static o non-static è semplice: Se la nested class ha bisogno di accedere ai membri o metodi d'istanza della classe contenitore, creaimo la nested class, non-static. Altrimenti facciamola static.

```java
public class PokerGame {  // Represents a game of poker.
    
    class Player {  // Represents one of the players in this game.
       .
       .
       .
    } // end class Player
    
    private Deck deck;      // A deck of cards for playing the game.
    private int pot;        // The amount of money that has been bet.
    
    .
    .
    .

} // end class PokerGame
```

Se *game* è una variabile di tipo `PokerGame`, allora, concettualmente, *game* contiene la propria copia della classe `Player`. In un metodo d'instanza di un oggetto di tipo *PokerGame*, un nuovo oggetto di tipo `Player`, verrà creato con istruzione "*new Player()*", così come ogni altra classe. (Un oggetto invece Player, che volesse essere creato dall'esterno della classe PockerGame, utilizzo più raro, dovrebbe essere creato tramite l'istruzione "*game.new Player()*"). L'oggetto di tipo `Player` avrebbe accesso alle variabili d'istanza *deck* e *pot* dell'oggetto di tipo `PokerGame`. Ogni oggetto di tipo `PokerGame` ha il proprio *deck*, *pot* e *Players*. I Player di quel particolare poker game, partita di poker, utilizzano il mazzo (deck) e puntata (pot) per quella particolare partita; giocatori di un altro poker game, partita, avranno un altro mazzo, deck, e puntata, pot. Questo è l'effetto di avere la classe `Player` non-static. Questo è il modo naturale per i giocatori di comportarsi. Un oggetto di tipo `Player` rappresenta un giocatore in una particolare partita di poker. Se Player fosse stata una classe indipendente o una classe statica, d'altro lato, essa avrebbe rappresentato l'idea generale di giocatore di poker, indipendentemente dalla particolare partita di poker.

### Anonymous Inner classes

In alcuni casi, vi potresete trovare a scrivere un' inner class e a utilizzare quella classe in usa sol punto del vostro codice. Ha senso allora creare una classe? Può darsi, ma potreste anche creare un **anomymous inner class**. Un' anomymous inner class, è creata con una con una variazione dell'operatore new, che ha  la forma:

```java
new  <superclass-or-interface> ( <parameter-list> ) {
                   <methods-and-variables>
              }
```

Questo costruttore definisce una nuova classe senza assegnargli un nome. Questa forma dell'operatore **new** è creare "un nuovo oggetto appartenente a una classe che è la stessa come *\<superclass-or-interface>* ma con questi *\<methods-and-variables>* aggiunti. Il risultato è ottenere un oggetto unico customizzato, giusto nel punto del programma in cui è necessario. Da notare che è possibile basare una classe anonima su un'interfaccia, piuttosto che una classe. In questo caso, una classe anonima, deve implementare un'interfaccia definendo tutti i metodi che sono dichiarati nell'interfaccia. Se un'interfaccia è utilizzata come base, la *\<parameter-list>* deve essere vuota. Altrimenti, può contenere i parametri del costruttore della *\<superclass>*.

Supponiamo di avere un'interfaccia `Drawable` così definita:

```java
public interface Drawable {
    public void draw(GraphicsContext g);
}
```

Se vogliamo utilizzare un oggetto di tipo Drawable di colore rosso che sia un rettangolo, invece di creare una nuova classe che implementi Drawable e poi instanziala per creare l'oggetto, possimo invece usare una classe anonima per creare l'oggetto direttamente.

```java
Drawable redSquare = new Drawable() {
       void draw(Graphics g) {
          g.setColor(Color.RED);
          g.fillRect(10,10,100,100);
       }
   };
```

La variabile *redSquare* riferisce a un oggetto che implementa `Drawable` e che disegna un rettangolo rosso quando il metodo `draw()` è invocato.

Una classe anonima è spesso utilizzata come parametri attuali. Per esempio considera questa funzione:

```java
void drawTwice( Graphics g1, Graphics g2, Drawable figure ) {
    figure.draw(g1);
    figure.draw(g2);
}
```

Quando chiamiamo questo metodo, il terzo parametro può essere creato utilizzano una classe anonima. Per esempio:

```java
drawTwice( firstG, secondG, new Drawable() {
          void draw(Graphics g) {
             g.drawOval(10,10,100,100);
          }
     } );
```

### Local classes

Una classe può essere definita pure all'interno di un metodo. Queste classi cono chiamate **local classes**, classi locali. Una local class può essere solo utilizzata all'interno del metodo in cui è definita. Tuttavia un oggetto che è definito da una local class può essere utilizzato all'esterno del metodo. Può essere ritornato come valore di una subroutine, o può essere passato come parametro di un altro metodo. Questo è possibile, perché un oggetto appartenente a qualche classe B può essere assegnato a una variabile di tipo A, se B è sottoclasse di A o, se la classe B implementa l'interfaccia A. Ad esempio se un metodo accetta come parametro un oggetto di tipo `Drawable` (interfaccia definita negli esempi sopra), allora un oggetto che implementa `Drawable` può essere passato come parametro a quel metodo. E quell'oggetto può essere definito da una local class.

La definizione di una local class può utilizzare le variabili locali del metodo all'interno del quale è definita. Può utilizzare anche parametri di quel metodo. Tuttavia c'è una restrizione nell'utilizzo di queste variabili locali e parametri nella local class: Le variabili locali o i parametri devono essere dichiarati final o, se non esplicitamente dichiarati final, devono esser "effettivamente final". Un parametro è "effettivamente final" se il suo valore non è cambiato all'interno della subroutine (inclusa ogni local class che riferisce il parametro). Una variabile locale è "effettivamente final" se il suo valore non è mai cambiato dopo che viene inizializzata. Nota che non c'è una simile restrizione sulle variabili globali che sono usate nella definizione di una local class.
