W3docs

Metodi di Classe Java

Aggiungi metodi di istanza a una classe Java per dare comportamento agli oggetti e operare sui loro campi.

I metodi di una classe sono ciò che conferisce comportamento ai suoi oggetti. I campi definiscono cosa un oggetto è; i metodi descrivono cosa può fare. Fino a ora i metodi che hai scritto erano static — utilità che appartengono alla classe stessa. Questo capitolo riguarda i metodi di istanza, che appartengono a ciascun oggetto e operano sui suoi campi.

Il termine "metodi di classe" in Java è un po' ambiguo. La maggior parte degli autori lo usa per indicare metodi definiti all'interno di una classe — il che include entrambi i tipi. Alcuni lo usano in senso stretto per indicare i metodi static (perché questi appartengono letteralmente alla classe). Tratteremo qui i metodi di istanza, mentre i metodi static hanno un capitolo dedicato in Java static.

Un metodo di istanza

Aggiungi un metodo al corpo della classe, senza static, e diventa parte di ogni istanza:

public class Circle {
  double radius;

  double area() {
    return Math.PI * radius * radius;
  }
}

Ora ogni Circle che crei può rispondere ad area():

Circle c = new Circle();
c.radius = 5;
System.out.println(c.area());   // 78.539...

Il corpo legge radius senza qualificarlo — Java risolve il nome semplice come this.radius, il campo dell'oggetto su cui è stato chiamato il metodo.

this — il ricevitore

Ogni metodo di istanza ha un parametro invisibile chiamato this, che fa riferimento all'oggetto su cui è stato chiamato il metodo:

Circle a = new Circle();   a.radius = 2;
Circle b = new Circle();   b.radius = 5;

a.area();    // inside area(), this == a, so this.radius == 2
b.area();    // inside area(), this == b, so this.radius == 5

Lo stesso metodo compilato viene eseguito in entrambi i casi; ciò che cambia è a quale oggetto fa riferimento this. Il capitolo sulla parola chiave this spiega quando è necessario scrivere esplicitamente this. e quando può essere omesso.

Metodi che modificano lo stato

Un metodo può anche scrivere sui campi. Tali metodi sono spesso chiamati mutatori:

public class Counter {
  int count;

  void increment() {
    count++;            // mutates this.count
  }
  void reset() {
    count = 0;
  }
  int get() {
    return count;
  }
}

Counter c = new Counter();
c.increment(); c.increment(); c.increment();
System.out.println(c.get());   // 3

La mutazione tramite metodi è il modo in cui gli oggetti evolvono nel tempo senza che il codice esterno acceda direttamente ai loro campi. I metodi che si limitano a leggere un campo e restituirne il valore sono l'immagine speculare — vengono solitamente chiamati accessor o getter (int get() nell'esempio è uno di questi). Instradare letture e scritture attraverso i metodi, invece di esporre i campi, è l'idea centrale dell'incapsulamento: l'oggetto rimane responsabile dei propri dati.

Chiamare altri metodi dall'interno

I metodi di istanza possono chiamare altri metodi sullo stesso oggetto, semplicemente per nome:

public class Rectangle {
  double width, height;

  double area()      { return width * height; }
  double perimeter() { return 2 * (width + height); }

  String describe() {
    return "area=" + area() + ", perimeter=" + perimeter();
  }
}

Il compilatore trasforma area() e perimeter() all'interno di describe in this.area() e this.perimeter(). Chiamano i metodi sul rettangolo su cui è stato chiamato describe.

Static vs istanza — quale usare

La regola generale: il metodo dipende dallo stato per-oggetto?

  • Se sì, è un metodo di istanza (senza static).
  • Se no, è static.
public class Math2 {
  public static int squared(int n) {       // pure calculation — static
    return n * n;
  }
}

public class Counter {
  int count;
  public void increment() {                // reads/writes this.count — instance
    count++;
  }
}

Un segnale comune è un metodo di istanza che ignora completamente this — quello è un metodo static travestito. Il capitolo su Java static approfondisce i compromessi.

Chiamare un metodo di istanza richiede un'istanza

Poiché i metodi di istanza leggono this, non puoi chiamarne uno senza un oggetto:

Counter.increment();      // ERROR — increment is not static
new Counter().increment(); // fine — increment is called on a fresh Counter (which is then thrown away)

Counter c = new Counter();
c.increment();             // fine — increment is called on c

Questo è l'errore di compilazione più comune che incontrano i principianti: un metodo non-static referenziato da un contesto static (tipicamente da main, che è esso stesso static).

Attenzione

Se il compilatore segnala non-static method increment() cannot be referenced from a static context, quasi certamente hai chiamato un metodo di istanza senza un oggetto — ad esempio Counter.increment() invece di c.increment(). Crea prima un'istanza, poi chiama il metodo su di essa.

Overloading e overriding

I metodi di istanza supportano entrambi:

  • Overloading: più metodi con lo stesso nome ma elenchi di parametri diversi nella stessa classe (trattato in method overloading).
  • Overriding: una sottoclasse che sostituisce la versione ereditata di un metodo (trattato in method overriding).

Hai già visto l'overloading nella Parte 5. L'overriding è uno dei grandi vantaggi dell'ereditarietà e verrà trattato a breve.

I corpi dei metodi sono blocchi

Il corpo di un metodo è semplicemente un blocco di codice ordinario — le variabili che dichiari sono locali alla chiamata, il flusso di controllo funziona come altrove, e puoi restituire il risultato in anticipo. Niente del fatto che "questo è in una classe" cambia come si legge il corpo stesso. L'unica capacità aggiuntiva è che gli identificatori semplici possono ora fare riferimento ai campi dell'oggetto e agli altri metodi.

Un esempio pratico

Questo esempio raccoglie accessor (area, perimeter), un mutatore (scale) e un metodo che chiama altri metodi (describe) in un'unica classe. Rectangle è dichiarata static class solo per far stare l'intera demo in un singolo file — quella parola chiave si applica alla classe annidata, non ai suoi metodi di istanza, che vengono comunque eseguiti su un rettangolo specifico. Nota che scalare r lascia s invariato: ogni oggetto mantiene il proprio stato.

java— editable, runs on the server

Cosa viene dopo

Finora hai creato oggetti scrivendo new Dog(), poi compilando i campi riga per riga. Questo approccio è verboso e soggetto a errori — ed è facile dimenticarsi qualcosa. La soluzione è un costruttore, un metodo speciale che viene eseguito quando l'oggetto viene creato. Continua con il capitolo sui costruttori.

Pratica

Pratica
Qual è la differenza tra un metodo static e un metodo di istanza?
Qual è la differenza tra un metodo static e un metodo di istanza?
Was this page helpful?