DOMANDA Chiarimento sulla chiamata di un metodo Java

_Gemba_

Utente Attivo
220
32
CPU
i5 7600
Dissipatore
Stock Intel
Scheda Madre
Gigabyte H270 HD3
HDD
Western Digital Blue 1TB + SSD NVME 960 EVO 250GB
RAM
2 x 4GB Corsair Vengeance 2400 Mhz CL14
GPU
MSI RX 480 Gaming X 8GB
PSU
EVGA Supernova G2 550W
Case
Corsair Spec 03
OS
Windows 10 Pro x64
Salve ragazzi, sto studiando il manuale di Java 8 di De Sio. Oltre a fare esercizi, mi cimento a capire il codice degli esempi.
Sono arrivato al capitolo dei tipi generici, qui c'è un esempio d'uso (tuttavia non importante ai fini della domanda):
Codice:
import java.util.ArrayList;


public class Cesta<F extends Frutta> {


    private ArrayList<F> frutta;


    public Cesta() {
        frutta = new ArrayList<>();
    }


    public ArrayList<F> getFrutta() {
        return frutta;
    }


    public void aggiungiFrutta(F frutto) throws PesoException {
        final int nuovoPeso = getPeso() + frutto.getPeso();
        if (nuovoPeso > 2000) {
            throw new PesoException("Troppo peso: " + nuovoPeso + " grammi!");
        }
        frutta.add(frutto);
        System.out.println(frutto.getClass().getName() + " da " + frutto.getPeso() + " grammi aggiunta alla cesta");
    }


    public int getPeso() {
        int peso = 0;
        for (F frutto : frutta) {
            peso += frutto.getPeso();
        }
        return peso;
    }
}

Non metto tutto il codice altrimenti diventa troppo lungo. Oltre a questa classe, di importante c'è la classe astratta Frutta (da cui estendono Mela e Arancia) che ha il metodo getPeso che, qualsiasi sia il tipo di frutto, restituisce il suo peso.
Non riesco a capacitarmi di come sia possibile la chiamata a getPeso() senza specificare il nome della classe, nel metodo aggiungiFrutta. Esso magicamente si riferisce al getPeso di questa classe Cesta.
Come è possibile?
In pratica il primo getPeso è riferito a Cesta e trova il peso corrente della Cesta, mentre il frutto.getPeso si rifà al metodo della classe Frutta che appunto restituisce il peso di quello specifico frutto (parametro di aggiungiFrutta).
Spero di essermi spiegato bene, vi ringrazio!
 
Ultima modifica:

1nd33d

Utente Attivo
653
279
CPU
Intel i5 3570K @ 4,5Ghz
Dissipatore
Scythe Mugen 2
Scheda Madre
Gigabyte Z77X-UD3H
HDD
Samsung 840 PRO 256GB + Sandisk Ultra 250GB + Sandisk Plus 960GB
RAM
2x8GB Crucial Ballistix Tactical @2000Mhz CL9
GPU
XFX RX480 GTR Black Edition
Audio
Auzentech X-Fi Forte
Monitor
AOC i2369VW
PSU
Seasonic P660
Case
eh?
Periferiche
Razer Naga HEX v2
OS
Windows 10 64bit - Linux Mint 18
Molto semplicemente, se chiami il metodo getPeso() senza specificare l'oggetto di invocazione, il compilatore invoca this.getPeso(). Il metodo "aggiungiFrutto" è un metodo della classe "Cesta" per cui "this" sarà un oggetto di tipo "Cesta". Quando invece invochi frutto.getPeso() stai specificando l'oggetto di invocazione e il compilatore cerca il metodo getPeso() nell'oggetto "frutto", che è di tipo F.
 
Ultima modifica:

_Gemba_

Utente Attivo
220
32
CPU
i5 7600
Dissipatore
Stock Intel
Scheda Madre
Gigabyte H270 HD3
HDD
Western Digital Blue 1TB + SSD NVME 960 EVO 250GB
RAM
2 x 4GB Corsair Vengeance 2400 Mhz CL14
GPU
MSI RX 480 Gaming X 8GB
PSU
EVGA Supernova G2 550W
Case
Corsair Spec 03
OS
Windows 10 Pro x64
Molto semplicemente, se chiami il metodo getPeso() senza specificare l'oggetto di invocazione, il compilatore invoca this.getPeso(). Il metodo "aggiungiFrutto" è un metodo della classe "Cesta" per cui "this" sarà un oggetto di tipo "Cesta". Quando invece invochi frutto.getPeso() stai specificando l'oggetto di invocazione e il compilatore cerca il metodo getPeso() nell'oggetto "frutto", che è di tipo F.
Ti ringrazio per la risposta. In effetti avevo provato anch'io con this.getPeso() e funzionava lo stesso.
Ma il this si riferisce a un'istanza di Cesta? Perchè se provo a fare Cesta.getPeso() non funziona. Comunque grazie ancora!
 

1nd33d

Utente Attivo
653
279
CPU
Intel i5 3570K @ 4,5Ghz
Dissipatore
Scythe Mugen 2
Scheda Madre
Gigabyte Z77X-UD3H
HDD
Samsung 840 PRO 256GB + Sandisk Ultra 250GB + Sandisk Plus 960GB
RAM
2x8GB Crucial Ballistix Tactical @2000Mhz CL9
GPU
XFX RX480 GTR Black Edition
Audio
Auzentech X-Fi Forte
Monitor
AOC i2369VW
PSU
Seasonic P660
Case
eh?
Periferiche
Razer Naga HEX v2
OS
Windows 10 64bit - Linux Mint 18
Ti ringrazio per la risposta. In effetti avevo provato anch'io con this.getPeso() e funzionava lo stesso.
Ma il this si riferisce a un'istanza di Cesta? Perchè se provo a fare Cesta.getPeso() non funziona. Comunque grazie ancora!
Si, si riferisce all'istanza di Cesta in cui viene eseguito il metodo che chiama getPeso(), in questo caso si riferisce all'istanza su cui hai chiamato aggiungiFrutta().
In una delle diverse volte che mi hanno insegnato Java mi è capitato di sentire una spiegazione di questo funzionamento che si basa sull'assunzione che l'invocazione di un metodo non statico ha un parametro attuale nascosto che è l'oggetto di invocazione. In altri linguaggi, come Python, il this (in python è 'self') è invece esplicitato. Se non specifichi l'oggetto di invocazione, viene assunto che sia il this del metodo chiamante.
Esempio:
Codice:
ilmiocestino.aggiungiFrutta(mela)  = oggetto.metodo(<this = ilmiocestino>, mela)
dentro ad aggiungiFrutta, il valore di this è quindi il riferimento a ilmiocestino, se invochi getPeso() senza metodo hai questo comportamento
Codice:
getPeso() = this.getPeso() = ilmiocestino.getPeso() = ilmiocestino.getPeso(<this = ilmiocestino>)
dentro a getPeso() iteri l'array frutta, ma di quale oggetto? Ovviamente dell'oggetto "this" che è ancora "ilmiocestino".

Cesta.getPeso() non funziona perchè getPeso() non è un metodo statico e quindi può essere invocato solo su istanze di Cesta. Se fosse un metodo statico allora potresti chiamarlo in quel modo senza nemmeno istanziare un oggetto di tipo Cesta, ma potresti lavorare solo con campi statici della classe Cesta (per esempio, non potresti accedere alla variabile "frutta" perchè non è statica). Se sia il metodo getPeso() e che la variabile frutta fossero statici, allora il codice funzionerebbe ma, essendo la variabile frutta statica, sarebbe condivisa anche da tutti gli oggetti di tipo Cesta. Praticamente tutte le ceste avrebbero una sola lista di frutti condivisa.
 
  • Mi piace
Reazioni: _Gemba_

_Gemba_

Utente Attivo
220
32
CPU
i5 7600
Dissipatore
Stock Intel
Scheda Madre
Gigabyte H270 HD3
HDD
Western Digital Blue 1TB + SSD NVME 960 EVO 250GB
RAM
2 x 4GB Corsair Vengeance 2400 Mhz CL14
GPU
MSI RX 480 Gaming X 8GB
PSU
EVGA Supernova G2 550W
Case
Corsair Spec 03
OS
Windows 10 Pro x64
Grazie mille per la spiegazione, ho capito chiaramente tutto!
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!