Metodologie di Programmazione a.a. 2010-2011
Prova scritta - 27 giugno 2011
Avvertenze     Le soluzioni devono essere scritte in modo chiaro e ordinato; il codice deve essere indentato per facilitarne la lettura. Si possono consultare libri e appunti ma non è permesso usare computer. Il voto (in trentesimi) sarà determinato dalla somma dei punteggi ottenuti nei vari esercizi.
Chi fa solamente la Seconda Parte: i punti degli esercizi sono da intendersi raddoppiati.
Chi fa l'intero scritto: per raggiungere la sufficienza deve ottenere almeno 8 punti sull'esercizio SSS e almeno 10 punti sulla Seconda Parte.


[SSS]   Definire una gerarchia di classi per gestire i dati dei dipendenti e dei progetti di una Società di Sviluppo Software.
  1. (max 13 punti)  Definire prima di tutto una classe Data (tre campi interi, giorno, mese ed anno) e una classe Progetto per i dati di un progetto (software): il codice (una stringa) e la data di consegna (di tipo Data). La classe Progetto deve ridefinire il metodo equals di Object (due progetti sono uguali se hanno lo stesso codice), inoltre il costruttore deve lanciare NullPointerException se il codice o la data sono null. Gli oggetti di entrambe le classi devono essere immutabili.
         Definire la classe base Dipendente per gestire i dati comuni dei dipendenti: il nome e cognome (una sola stringa), un importo in euro (un float) che rappresenta lo stipendio di base. Definire un metodo per impostare lo stipendio di base. Definire un metodo float stipendio() che ritorna lo stipendio e che sarà ridefinito dalle sottoclassi. Lo stipendio è inizialmente uguale allo stipendio di base. Il costruttore della classe Dipendente deve prendere in input solamente il nome e cognome. Lo stipendio base è inizializzato a 0.
         Definire una sottoclasse Programmatore che mantiene il progetto (di tipo Progetto) a cui il programmatore è assegnato e definisce metodi per leggere e impostare il progetto. Inizialmente è null e può essere impostato a null. La classe ridefinisce il metodo stipendio che ritorna il valore ritornato dalla superclasse maggiorato del 10% se il programmatore ha un progetto assegnato.
         Definire una sottoclasse Supervisore che mantiene l'elenco dei progetti di cui il supervisore è responsabile e definisce un metodo per aggiungere un progetto (solo se non è null e non è già presente), un metodo per rimuovere un progetto dall'elenco e un metodo Progetto[] resp(Data d) che ritorna in un array i progetti che hanno la data di consegna uguale o antecedente alla data d (se non ci sono, ritorna l'array vuoto). Lo stipendio è determinato dalla somma dello stipendio della superclasse più il 10% dello stesso per ogni progetto.
  2. (max 5 punti)  Aggiungere alla classe Dipendente un metodo statico che preso in input un array di Dipendente e una data d ritorna in un nuovo array tutti i programmatori e i supervisori impegnati in progetti con data di consegna antecedente o uguale a d. Si tenga presente che potrebbero esserci anche altre sottoclassi (oltre a Programmatore e Supervisore) di Dipendente.
SECONDA PARTE
[Geo] (max 13 punti)   Una entità geografica è una qualsiasi entità della geografia fisica (montagna, fiume, lago, ecc.) o politica (città, regione, stato, ecc.). Un tipo rappresenta una entità geografica se implementa l'interfaccia:
public interface Geo {
        //Ritorna true se questa entità è disgiunta dall'entità g
    boolean disjoint(Geo g);  //Se g è null, lancia NullPointerException
        //Ritorna true se questa entità è interamente contenuta in g
    boolean contained(Geo g); //Se g è null, lancia NullPointerException
        //Ritorna la categoria di questa entità
    String getCategory();
}
Le relazioni tra due entità x e y possono essere le seguenti: x e y sono disgiunte (x.disjoint(y) == true); x è interamente contenuta in y (x.contained(y) == true); y è interamente contenuta in x (y.contained(x) == true); x e y si contengono parzialmente (x.isDisjoint(y) == false, x.contained(y) == false e y.contained(x) == false). Se x e y appartengono alla stessa categoria (ad esempio, sono entità politiche come stati, regioni, comuni, ecc.) allora è garantito che o sono disgiunte o x contiene interamente y o y contiene interamente x. Definire una classe generica GeoSet per gestire insiemi di entità geografiche parametrizzata rispetto al tipo degli oggetti che rappresentano entità geografiche (cioè, implementano l'interfaccia Geo). La classe deve implementare i seguenti metodi (il costruttore crea un insieme vuoto e può essere quello di default): Inoltre, la classe deve implementare l'interfaccia Iterable per iterare sulle entità dell'insieme.

[Errori] (max 4 punti)   Il seguente codice Java contiene uno o più errori. Trovare gli errori, spiegarli e dire per ognuno se si verifica in compilazione o in esecuzione.
 1 import java.util.*;
 2 
 3 public class Test {
 4     public static <T> void copy(T[] a, List<T> list) {
 5         int n = (a.length < list.size() ? a.length : list.size());
 6         for (int i = 0 ; i < n ; i++)
 7             a[i] = list.get(i);
 8     }
 9     public static void main(String[] args) {
10         Integer[] intA = new Integer[8];
11         List<Number> nL = new ArrayList<Number>();
12         nL.add(0.87);
13         copy(intA, nL);
14         Object[] objA = new Object[5];
15         copy(objA, nL); 
16         nL.set(0, 17);
17         copy(intA, nL);
18         for (Number n : nL)
19             if (n.doubleValue() >= 5)
20                 nL.remove(n);
21     }
22 }

[Merge] (max 5 punti)   Definire un metodo statico generico merge che prende in input due liste ordinate (rispetto all'interfaccia Comparable) e ritorna in una nuova lista la fusione ordinata delle due liste. Ovviamente, i tipi degli elementi delle due liste di input devono essere confrontabili tramite l'interfaccia Comparable. L'intestazione del metodo deve permettere la massima flessibilità d'uso senza sacrificare il controllo statico dei tipi. Ad esempio, se Point è un tipo che implementa Comparable<Point> e LPoint e CPoint sono due sottotipi di Point, allora il metodo merge deve accettare in input una lista di LPoint e una lista di CPoint e ritornare una lista compatibile con una lista di Point.