Menu
Coddy logo textTech

Classi interne, annidate e anonime

Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 49 di 87.

Java ti permette di definire classi all'interno di altre classi. Queste classi interne aiutano a organizzare il codice raggruppando insieme funzionalità correlate e possono accedere direttamente ai membri della classe esterna.

Una classe interna annidata è definita come membro di un’altra classe. Ha accesso a tutti i campi e metodi della classe esterna, inclusi quelli privati:

class Outer {
    private String message = "Hello";
    
    class Inner {
        void display() {
            System.out.println(message);  // Può accedere al campo privato
        }
    }
}

// Utilizzo
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display();  // Stampa: Hello

Una classe interna locale è definita all'interno di un metodo. Può essere usata solo all'interno di quel metodo e può accedere alle variabili locali che sono effettivamente finali:

void process() {
    String prefix = "Result: ";
    
    class LocalHelper {
        void print(int value) {
            System.out.println(prefix + value);
        }
    }
    
    new LocalHelper().print(42);
}

Una classe interna anonima è una classe senza nome, creata e istanziata in un’unica espressione. È comunemente usata per implementare interfacce o estendere classi al volo:

Comparator<String> comp = new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return a.length() - b.length();
    }
};

Le classi interne sono particolarmente utili quando una classe è rilevante solo per un'altra classe, mantenendo il codice organizzato ed incapsulato.

challenge icon

Sfida

Facile

Creiamo un sistema di carrello della spesa che mostri tutti e tre i tipi di classi interne. Creerai uno ShoppingCart che usa una classe interna annidata per rappresentare gli articoli, una classe interna locale per calcolare gli sconti e una classe interna anonima per formattare lo scontrino finale.

Organizzerai il codice in due file:

  • ShoppingCart.java: crea la classe esterna che gestisce l'esperienza di acquisto. Il tuo ShoppingCart dovrebbe avere un campo privato customerName (String).

    All'interno di ShoppingCart, definisci una classe interna annidata chiamata Item con due campi privati: name (String) e price (double). Assegna a Item un costruttore per inizializzare entrambi i campi e un metodo getDetails() che restituisce: [name]: $[price]

    Il tuo ShoppingCart deve avere un costruttore che accetta il nome del cliente e un metodo chiamato checkout() che accetta un Item e una percentuale di sconto (double). All'interno di checkout():

    1. Crea una classe interna locale chiamata DiscountCalculator con un metodo applyDiscount(double originalPrice) che restituisce il prezzo dopo aver applicato la percentuale di sconto.
    2. Usa la classe locale per calcolare il prezzo finale.
    3. Crea una classe interna anonima che implementa l'interfaccia Formatter (che definirai) per formattare lo scontrino. La classe anonima dovrebbe sovrascrivere un metodo format() che restituisce una stringa di scontrino su più righe.

    Il metodo checkout() dovrebbe restituire la stringa dello scontrino formattata con questo formato esatto:

    --- Receipt ---
    Customer: [customerName]
    Item: [item details from getDetails()]
    Discount: [discount]%
    Final Price: $[calculated price]
  • Formatter.java: definisci una semplice interfaccia con un solo metodo: String format(). Questa interfaccia sarà implementata dalla tua classe interna anonima all'interno del metodo checkout.
  • Main.java: dai vita al tuo carrello della spesa! Riceverai tre input: nome del cliente (String), nome dell'articolo (String) e prezzo dell'articolo (double). La percentuale di sconto è fissata a 10.0.

    Crea uno ShoppingCart con il nome del cliente. Poi crea un Item usando la sintassi di riferimento alla classe esterna: cart.new Item(name, price). Chiama checkout() con l'articolo e lo sconto, quindi stampa lo scontrino restituito.

Riceverai tre input, in quest'ordine: nome del cliente, nome dell'articolo e prezzo dell'articolo.

Per esempio, se gli input sono Alice, Laptop e 1000.0, il prezzo finale dopo uno sconto del 10% sarà 900.0.

Nota come ogni tipo di classe interna abbia uno scopo diverso: la classe annidata raggruppa i dati correlati con la classe esterna, la classe locale incapsula la logica necessaria solo all'interno di un metodo e la classe anonima fornisce un'implementazione rapida e occasionale di un'interfaccia!

Provalo tu

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Leggi i dati di input
        String customerName = scanner.nextLine();
        String itemName = scanner.nextLine();
        double itemPrice = scanner.nextDouble();
        
        double discount = 10.0;
        
        // TODO: Crea un ShoppingCart con il nome del cliente
        
        // TODO: Crea un Item usando: cart.new Item(itemName, itemPrice)
        
        // TODO: Chiama checkout() con l'articolo e lo sconto, poi stampa il risultato
        
    }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Java online