D4rkAng3l
16-05-2009, 17:21
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:
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()
}
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):
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
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:
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()
}
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):
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