Ereditarietà

di il
6 risposte

Ereditarietà

Salve amici, vi contatto perché stavo provando a scrivere due semplici classi in modo da capire bene il funzionamento dell'ereditarietà .
Anzitutto ho creato la superasse "Studente", caratterizzata con i seguenti dati: Nome, Cognome, cf, Città, Indirizzo.
Poi ho creato una sottoclasse "StudenteNonLaureato" che eredita i 5 parametri dalla superclasse e in aggiunta ha i parametri Matricola e 3 valori booleani inCorso, fuoriCorso e tesista. Vi posto il codice sorgente delle due classi da me scritte.
// Superclasse Studente.java

public class Studente {
	
	private String nome;
	private String cognome;
	private String codiceFiscale;
	private String citta;
	private String indirizzo;

	// costruttore della superclasse con 5 argomenti
	public Studente(String _nome, String _cognome, String cf, String _citta, String _indirizzo)
	{
		nome = _nome;
		cognome = _cognome;
		codiceFiscale = cf;
		citta = _citta;
		indirizzo = _indirizzo;
		
		System.out.printf("\nCostruttore di Studente:\n%s\n", this);
	}
	
	// imposta il nome dello studente
	public void setNome(String _nome)
	{
		nome = _nome;
	}
	
	// restituisce il nome dello studente
	public String getNome()
	{
		return nome;
	}
	
	// imposta il cognome dello studente 
	public void setCognome(String _cognome)
	{
		cognome = _cognome;
	}
	
	// restituisce il cognome dello studente
	public String getCognome()
	{
		return cognome;
	}
	
	// imposta il codice fiscale dello studente
	public void setCodiceFiscale(String cf)
	{
		codiceFiscale = cf;
	}
	
	// restituisce il codice fiscale dello studente
	public String getCodiceFiscale()
	{
		return codiceFiscale;
	}
	
	// imposta la città dello studente
	public void setCitta(String _citta)
	{
		citta = _citta;
	}
	
	// restituisce la città dello studente
	public String getCitta()
	{
		return citta;
	}
	
	// imposta l'indirizzo dello studente
	public void setIndirizzo(String _indirizzo)
	{
		indirizzo = _indirizzo;
	}
	
	// restituisce l'indirizzo dello studente
	public String getIndirizzo()
	{
		return indirizzo;
	}
	
	// restituisce i dati dello studente in formato stringa
	public String toString()
	{
		return String.format("%s: %s %s\n\t\t\t\t%s: %s\n\t\t\t\t%s: %s\n\t\t\t\t%s: %s",
				"Dati anagrafici dello studente", getNome(), getCognome(),
				"Codice Fiscale", getCodiceFiscale(),
				"Nato/a a", getCitta(),
				"Residente in via/piazza", getIndirizzo());
	}

}

// Sottoclasse StudenteNonLaureato.java

public class StudenteNonLaureato extends Studente{

	private String matricola;
	private boolean inCorso;
	private boolean fuoriCorso;
	private boolean tesista;

	// sono stati aggiunti altri 4 argomenti al cotruttore
	public StudenteNonLaureato(String _nome, String _cognome, String cf,
			String _citta, String _indirizzo, String _matricola, boolean _inCorso, 
			boolean _fuoriCorso, boolean _tesista) {
		// costruttore della superclasse
		super(_nome, _cognome, cf, _citta, _indirizzo);
		
		matricola = _matricola;
		inCorso = _inCorso;
		fuoriCorso = _fuoriCorso;
		tesista = _tesista;
		
		System.out.printf("\nCostruttore di StudenteNonLaureato:\n%s\n", this);
	}
	
	// imposta  la matricola dello studente
	public void setMatricola(String _matricola)
	{
		matricola = _matricola;
	}
	
	// restituisce la matricola dello studente
	public String getMatricola()
	{
		return matricola;
	}
	
	// restituisce l'informazione relativa a "in corso" dello studente
	public boolean getInCorso()
	{
		return inCorso;	
	}
	
	// restituisce l'informazione relativa a "fuori corso" dello studente
	public boolean getFuoriCorso()
	{
		return fuoriCorso;	
	}
		
	// restituisce l'informazione relativa a "tesista" delo studente
	public boolean getTesista()
	{
		return tesista;
	}
	
	// restituisce la rappresentazione in formato stringa
	public String toString()
	{
		return String.format("%s: %s\n\t\t\t\t%s: %s\n\t\t\t\t%s: %s\n\t\t\t\t%s: %s", 
				super.toString(), 
				"Matricola", getMatricola(),
				"In corso", getInCorso(),
				"Fuori corso", getFuoriCorso(),
				"Tesista", getTesista());
	}

}
Il mio problema è questo: creo una classe di test, istanzio uno studente e uno studenteNonLaureato e quando eseguo l'applicazione mi mostra il seguente risultato, mostrandomi due volte lo studenteNon laureato

Costruttore di Studente:
Dati anagrafici dello studente: Gino Bacoli
Codice Fiscale: GJ89JK90JKL30K
Nato/a a: Milano
Residente in via/piazza: Genova, 1


Costruttore di Studente:
Dati anagrafici dello studente: Veronica Barra
Codice Fiscale: KHGJD89S55A894J
Nato/a a: Isernia
Residente in via/piazza: E.Montale,22: Matricola
null: In corso
false: Fuori corso
false: Tesista

Costruttore di StudenteNonLaureato:
Dati anagrafici dello studente: Veronica Barra
Codice Fiscale: KHGJD89S55A894J
Nato/a a: Isernia
Residente in via/piazza: E.Montale,22: Matricola
863000102: In corso
true: Fuori corso
false: Tesista


Per completezza vi posto anche la classe di test. Secondo voi dove commetto errore?
public class TestStudenti {

	/**
	 * TestStudenti.java
	 * Test effettuati sulla superclasse e le sottoclossi
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		// Crea lo studente (superclasse)
		Studente studente1 = new Studente("Gino", "Bacoli", "GJ89JK90JKL30K", 
				"Milano", "Genova, 1");
	
		System.out.println();
		
		// Crea lo studente non laureato (sottoclasse)
		StudenteNonLaureato studente2 = new StudenteNonLaureato("Veronica", "Barra", 
				"KHGJD89S55A894J", "Isernia", "E.Montale,22", "863000102", true, false,
				false);
		
	}

}

6 Risposte

  • Re: Ereditarietà

    MacGigi ha scritto:


    quando eseguo l'applicazione mi mostra il seguente risultato, mostrandomi due volte lo studenteNon laureato
    Perché il costruttore di StudenteNonLaureato invoca il costruttore della super classe, ovvero quello di Studente. Fai la stampa dei dati in entrambi i costruttori.


    P.S. un consiglio: non "inventarti" nomi particolari (tantomeno con l'underscore davanti) per i parametri di costruttori e metodi. La convenzione standard, tipica e riconosciuta è di avere il parametro con lo stesso identico nome della variabile di istanza. Questo crea uno "shadowing" ma è accettato e per riferirsi al campo (ove ci sia conflitto) lo si qualifica con this.
    private String nome;
    
    ...
    public void setNome(String nome) {
        this.nome = nome;
    }
  • Re: Ereditarietà

    MacGigi ha scritto:


    Costruttore di Studente:
    Dati anagrafici dello studente: Veronica Barra
    Codice Fiscale: KHGJD89S55A894J
    Nato/a a: Isernia
    Residente in via/piazza: E.Montale,22: Matricola
    null: In corso
    false: Fuori corso
    false: Tesista

    Costruttore di StudenteNonLaureato:
    Dati anagrafici dello studente: Veronica Barra
    Codice Fiscale: KHGJD89S55A894J
    Nato/a a: Isernia
    Residente in via/piazza: E.Montale,22: Matricola
    863000102: In corso
    true: Fuori corso
    false: Tesista
    Tra l'altro, nota la differenza tra i due print. Prova a ragionarci e prova tu a dirmi il perché.


    P.S. ancora una cosa: nei print in generale NON usare \n pensando che sia il "newline" generico valido per qualunque sistema. Non lo è. Nei format/printf il %n è il newline generico ed appropriato per il sistema su cui sta girando.
  • Re: Ereditarietà

    Anzitutto grazie per il consiglio sui costruttori e metodi.
    Riguardo la tua domanda, penso che avviene la seguente stampa perché mi stampa prima i dati della superclasse e poi quelli della sottoclasse appunto per via dell'ereditarietà.
  • Re: Ereditarietà

    Ok ho risolto in questo modo e adesso funziona. Ti allego la stampa dello studente e la stampa dello studenteNonLaureato
    public void printStudente()
    	{
    		System.out.printf("%s: %s %s\n\t\t\t\t%s: %s\n\t\t\t\t%s: %s\n\t\t\t\t%s: %s",
    				"Dati anagrafici dello studente", getNome(), getCognome(),
    				"Codice Fiscale", getCodiceFiscale(),
    				"Nato/a a", getCitta(),
    				"Residente in via/piazza", getIndirizzo());
    	}
    public void printStudenteNonLaureato()
    	{
    		super.printStudente();
    		System.out.printf("%s: %s\n\t\t\t\t%s: %s\n\t\t\t\t%s: %s\n\t\t\t\t%s: %s",
    				"Matricola", getMatricola(),
    				"In corso", getInCorso(),
    				"Fuori corso", getFuoriCorso(),
    				"Tesista", getTesista());
    	}
    

    E in questo modo funziona
  • Re: Ereditarietà

    MacGigi ha scritto:


    Riguardo la tua domanda, penso che avviene la seguente stampa perché mi stampa prima i dati della superclasse e poi quelli della sottoclasse appunto per via dell'ereditarietà.
    In StudenteNonLaureato invochi il costruttore di Studente con

    super(_nome, _cognome, cf, _citta, _indirizzo);

    La prima istruzione di un costruttore deve essere una invocazione di un costruttore con super(); o this(); con o senza argomenti. Se non metti nulla, il compilatore mette un super(); senza argomenti.

    Quando il costruttore di Studente viene eseguito, i campi di StudenteNonLaureato sono ancora al loro valore di default e verranno assegnati solo dopo la terminazione del costruttore di Studente.
    Nel costruttore di Studente stampi il this che fa invocare il toString(), che essendo un metodo di istanza e ridefinibile (ed è ridefinito in StudenteNonLaureato), la implementazione realmente eseguita è sempre quella nell'oggetto istanziato cioè il toString() di StudenteNonLaureato. Quando questo viene eseguito, quei campi sono ancora al loro valore di default.

    C'è una regola importante da tenere sempre a mente: mai invocare (in)direttamente da un costruttore un metodo della propria classe che è soggetto ad override in una sotto-classe.
  • Re: Ereditarietà

    Capito. grazie mille per i consigli
Devi accedere o registrarti per scrivere nel forum
6 risposte