Visualizzazione dei risultati da 1 a 2 su 2
  1. #1

    [JAVA] Esempio di classe Abstract...ma così non è una porcata?!?!

    Ciao,
    stavo vedendo un esempio di classe Abstract sul mio libro...ma sinceramente mi pare un po' una porcata come viene usata in questo caso...mi dite se oggettivamente sono cose da evitare o se invece non ho capito bene io?

    Praticamente ho una classe astratta IntSet che mi fornisce una rappresentazione parziale di un insieme di interi e l'unica variabile di istanza è la variabile protected dimensione che indica la dimensione di tale insieme di interi.

    Poi estendo tale classe abstract mediante la sottoclasse SortedIntSet che rappresenta un insieme di interi ordinati e che usa come variabile di istanza una OrderedIntList (una classe che mi rappresenta liste di interi ordinate).
    In tale sottoclasse viene fornita la rappresentazione vera e propria del tipo di dati (che nella classe astratta non veniva fornita perchè poi magari potrei avere altre estensioni di IntSet che la implementano in altro modo...tipo ad esempio un'altra sottoclasse ConstantIntSet che rappresenta insiemi di interi di dimensione costante).

    La variabile di istanza dimensione della superclasse è stata definita protected così quando ad esempio aggiungo con il metodo insert() o rimuovo con delete() un elemnto ad OrderedIntList posso accedere alla variabile protected dimensione ed aggiornarla.
    Ma francamente mi pare un po' una porcata dichiarare tale variabile protected per 2 motivi:

    1) Se cambio l'implementazione della superclasse devo cambiare l'implementazione delle varie sottoclassi.
    2) Motivi di sicurezza perchè è visibile in tutto il package e qualsiasi metodo definito nel package potrebbe andare a modificarla.

    Che mi dite in proposito? C'ho ragione io o mi sfugge qualcosa?

    Il codice d'esempio del libro (parzialmente implementato) è il seguente:

    codice:
    public abstract class IntSet{
    	
    	protected int dimensione;			// La dimensione
    	
    	// COSTRUTTORE
    	public IntSet(){
    		dimensione = 0;
    	}
    	
    	// METODI ABSTRACT
    	public abstract void insert(int x);		// Inserisce l'elemento x nell'insieme di interi
    	public abstract void remove(int x);		// Rimuove l'elemento x dall'insieme di interi
    	public abstract Iterator elements();	// Per enumerare gli elementi dell'insieme di interi
    	
    	
    	// METODI IMPLEMENTATI
    	public boolean isIn(int x){
    		Iterator g = elements();
    		Integer z = new Integer(x);
    		
    		while(g.hasNext())
    			if(g.next().equals(z)) return true;
    		return false;
    	}
    	
    	public int size(){
    		return dimensione;
    	}
    	
    	// IMPLEMENTAZIONE DEI METODI subset() e toString()
    }
    codice:
    public class SortedIntSet extends Inset{
    	
    	private OrderedIntList els;
    	
    	public SortedIntSet(){			// COSTRUTTORE
    		els = new OrderedIntList();
    	}
    	
    	public int max() throws EmptyException{
    		if(dimensione == 0) throw new EmptyException("SortedIntSet.max");
    		return els.greates();
    	}
    	
    	public Iterator elements(){
    		return els.elements();
    	}
    	
    	public boolean subset((SortdIntSet) s){
    		try{
    			return subset((SortedIntSet) s);
    		}catch(ClassCastException e){return super.subset(s);}
    	}
    	
    	public boolean subset(SortedIntSet s){
    		.....
    		.....
    		.....
    	}
    	
    	// Implementazione di insert e remove va quì
    }
    Poi ho qualche domanda teorica:

    1) Estendendo IntSet la variabile protected dimensione viene ereditata in SortedIntSet...se si...perchè allora devo dichiararla protected per potervi accedere dalla classe figlia? Se era dichiarata private e viene ereditata perchè non ci si accede automaticamente?

    2) Il costruttore della classe abstract IntSet non viene mai invocato dagli utenti ma da quello che ho letto sul libro i costruttori delle classi abstract vengono invocati dai costruttori delle classi che le estendono per inizializzare la parte comune di rappresentazione, giusto?
    Allora quì (nel costruttore di SortedIntSet):

    codice:
    public SortedIntSet(){			// COSTRUTTORE
    		els = new OrderedIntList();
    	}
    dove cavolo viene invocato il costruttore della classe padre IntSet? Lo fà in automatico senza dover specificarlo? potevo anche metterci dentro super()?

    3) Avrei potuto non usare la classe padre abstract (IntSet) ed al posto di questa usare un'interface IntSet senza NESSUNA RAPPRESENTAZIONE (la variabile dimensione) ed implementare vari sottotipi di IntSet tra cui ad esempio il SortedIntSet visto prima ed un ConstantIntSet ognuno con una sua propria rappresentazione e l'implementazione di tutti i metodi abstract definiti dentro l'interface IntSet, avrebbe avuto più senso o no?

    4) [DOMANDA FORSE DELIRANTE] Se proprio avessi voluto usare la classe abstract come ha fatto lui nell'esempio del codice, a questo punto non sarebbe stato meglio dichiarare private la variabile di istanza dimensione (nella classe abstract) e poi prevedere in tale classe un metodo abstract che mi faceva accedere a tale variabile (così tale metodo era visibile anche nelle classi figlie)...cambiava qualcosa o no?

    Grazie
    Andrea

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: [JAVA] Esempio di classe Abstract...ma così non è una porcata?!?!

    Originariamente inviato da AndreaNobili
    Ma francamente mi pare un po' una porcata dichiarare tale variabile protected
    Quel 'dimensione' marcato protected pare anche a me una porcheria ... ma per un motivo molto semplice: il calcolo/determinazione della dimensione dovrebbe dipendere dalla implementazione concreta della collezione.

    Poi quello che dici sulla visibilità del campo protected .. ok è anche vero.

    Originariamente inviato da AndreaNobili
    1) Estendendo IntSet la variabile protected dimensione viene ereditata in SortedIntSet...se si...perchè allora devo dichiararla protected per potervi accedere dalla classe figlia? Se era dichiarata private e viene ereditata perchè non ci si accede automaticamente?
    I membri "private" non vengono ereditati.

    Originariamente inviato da AndreaNobili
    2) Il costruttore della classe abstract IntSet non viene mai invocato dagli utenti ma da quello che ho letto sul libro i costruttori delle classi abstract vengono invocati dai costruttori delle classi che le estendono per inizializzare la parte comune di rappresentazione, giusto?
    Alcune regole sui costruttori: la prima istruzione di un costruttore deve tassativamente essere una invocazione super() oppure this() (con o senza argomenti ... dipende) per invocare un altro costruttore (nella classe "sopra" o nella stessa classe). Se il programmatore non mette esplicitamente uno dei due, il compilatore mette per default un super() (senza argomenti!).

    Originariamente inviato da AndreaNobili
    3) Avrei potuto non usare la classe padre abstract (IntSet) ed al posto di questa usare un'interface IntSet senza NESSUNA RAPPRESENTAZIONE (la variabile dimensione)
    Le interfacce non possono avere "variabili" .... solo al massimo delle costanti.

    Originariamente inviato da AndreaNobili
    ed implementare vari sottotipi di IntSet tra cui ad esempio il SortedIntSet visto prima ed un ConstantIntSet ognuno con una sua propria rappresentazione e l'implementazione di tutti i metodi abstract definiti dentro l'interface IntSet, avrebbe avuto più senso o no?
    Certamente. Partire da una interfaccia sarebbe ancora meglio e più flessibile. Ed è quello che è stato fatto nel "collection framework" di Java. Basta che guardi la gerarchia delle classi in java.util.

    Nel tuo caso definisci una interfaccia IntSet, poi una classe astratta AbstractIntSet (che implementa IntSet) per implementare solo quelle operazioni che hanno senso a quel livello di astrazione (pensa al metodo toString() o ad un ipotetico metodo addAll() che è fatto in termini di utilizzo di un add() (che sarebbe poi implementato concretamente in una sottoclasse). Altri metodi potresti non farne nulla (non dovresti nemmeno dichiararli ... perché già la interfaccia indica che sono abstract!). Se però vuoi potresti implementarli (es. insert()) facendo lanciare UnsupportedOperationException. Una implementazione concreta che sia "read-only" quindi sarebbe più semplice (e con meno codice) da implementare.
    E poi le sottoclassi "concrete".

    Originariamente inviato da AndreaNobili
    4) [DOMANDA FORSE DELIRANTE] Se proprio avessi voluto usare la classe abstract come ha fatto lui nell'esempio del codice, a questo punto non sarebbe stato meglio dichiarare private la variabile di istanza dimensione (nella classe abstract) e poi prevedere in tale classe un metodo abstract che mi faceva accedere a tale variabile (così tale metodo era visibile anche nelle classi figlie)...cambiava qualcosa o no?
    No, non potevi. Se la variabile 'dimensione' è private, l'ho detto prima, non è ereditata. Quindi non accessibile nella sottoclasse.
    Avresti dovuto implementare dei metodi getter/setter protected (il setter non di certo public!) che accedono al campo private. Ma secondo me sarebbe stato pessimo e brutto.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.