Metodologie di Programmazione a.a. 2010-2011

Prova intermedia - 3 maggio 2011
Avvertenze:


[AEKI]   Definire una piccola gerarchia di classi per gestire il catalogo di una azienda che vende mobili (componibili) e combinazioni di mobili, secondo le indicazioni seguenti.
  1. (max 13 punti)
    • Definire una classe base Articolo che gestisce i dati comuni: il codice (una stringa), non modificabile, e la dimensione (larghezza, altezza e profondità in cm) rappresentata tramite una classe nidificata statica Misura le cui istanze sono immutabili. La classe Misura ridefinisce toString() di Object. Il costruttore di Articolo ha due argomenti: il codice e la dimensione. La classe Articolo ha dei metodi per leggere il codice e la dimensione. Ha un metodo float getPrezzo() che sarà ridefinito dalle sottoclassi e ritorna 0. Inoltre, ridefinisce il metodo equals() di Object: due oggetti Articolo sono uguali se hanno lo stesso codice.
    • Definire una sottoclasse Mobile per gestire i dati di un mobile: la categoria (una stringa, ad es. "Libreria", "Vetrina", ecc.) non modificabile, il prezzo (un float) e la gamma dei colori (un elenco di stringhe). Il costruttore prende in input anche la categoria e il prezzo. La classe Mobile ha un metodo per leggere la categoria, un metodo per impostare il prezzo e ridefinisce getPrezzo(). Ha un metodo boolean addColore(String c) che aggiunge il colore c solo se non è già presente (se lo aggiunge ritorna true, altrimenti false), se c è null lancia NullPointerException. Ridefinisce il metodo toString() ed ha un metodo che ritorna la gamma dei colori, in un array creato ex novo.
    • Definire una sottoclasse Comb di Articolo per gestire i dati di una combinazione di mobili: la percentuale di sconto (un intero compreso tra 0 e 100) e l'elenco dei mobili (di tipo Mobile) componenti. Il costruttore non prende in input altri dati oltre quelli della superclasse. La classe ha un metodo per impostare lo sconto; se l'intero in input non è compreso tra 0 e 100, lancia IllegalArgumentException. Ridefinisce getPrezzo() così che ritorni la somma dei prezzi dei mobili componenti scontata dello sconto. Ha un metodo void addMobile(Mobile m) che aggiunge un mobile componente (una combinazione può avere due o più componenti uguali) e se m è null, lancia NullPointerException. Ridefinisce toString() ed ha un metodo int contains(Mobile m) che ritorna quante volte il mobile m è nella combinazione.
    Ecco un esempio di cosa devono ritornare i metodi toString() di Mobile e Comb (nell'esempio, una vetrina di codice 123.400, una libreria di codice 123.407 e una combinazione di codice 208.609 composta da 2 mobili di codice 123.400 e un mobile di codice 123.407):
    "Vetrina 123.400 L: 40cm, H: 170cm, P: 60cm
    Colori: Bianco Beige Marrone
    Prezzo: 120.0"
    
    "Libreria 123.407 L: 60cm, H: 120cm, P: 60cm
    Colori: Marrone
    Prezzo: 90.0"
    
    "Combinazione 208.609 L: 140cm, H: 170cm, P: 60cm 
    2 Vetrina 123.400 L: 40cm, H: 170cm, P: 60cm
    1 Libreria 123.407 L: 60cm, H: 120cm, P: 60cm
    Prezzo: 297.0"
    
    Si osservi che nel caso di una combinazione, se è composta da due o più componenti uguali, i dati di questi vanno accorpati e va riportata la loro quantità. La combinazione ha uno sconto del 10%;
  2. (max 5 punti)  Aggiungere alla classe Articolo un metodo statico Comb[] trova(Articolo[] art, Mobile m, float max) che ritorna in un array le combinazioni nell'array art che hanno come componente il mobile m e il cui prezzo non supera max.

[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.
public class Esame {
    public static void main(String[] args) {
        String[] sA = new String[10];
        String[][] sM = new String[5][];
        sM[0] = sA;
        int n = sA[0].length();
        System.out.println(sM.toString());
        Object[] oA = new int[6][6];
        n = oA[0][0];
        oA[0] = new long[5];
        sM[0][0] = "prova";
        System.out.println(sA[0].length());
        Object o = new String[] {"A", "B"};
        System.out.print(o.length());
        ((int[])oA[1])[2] = 13;
    }
}

[GeoMap]   Si vuole definire una classe GeoMap per rappresentare mappe geografiche (semplificate). Una mappa geografica è una matrice rettangolare M i cui elementi sono entità geografiche. Una entità geografica è univocamente determinata da un codice (un numero intero positivo), ha un tipo (una stringa che può assumere i valori "LAKE", "RIVER", "CITY", ecc.) e un nome (una stringa, ad esempio "Roma", "Garda", ecc.). Se M[i][j] contiene, ad esempio, il riferimento ad una entità {1002, "CITY", "Roma"} significa che l'entità geografica "Roma" occupa la posizione (i, j). Una stessa entità geografica può occupare più posizioni.
  1. (max 6 punti)  Definire la classe GeoMap con una classe nidificata statica Entity che rappresenta entità geografiche. La classe Entity ridefinisce equals di Object e le sue istanze sono immutabili. Il costruttore di GeoMap ha due parametri interi nr e nc e costruisce una mappa di dimensione nr×nc i cui elementi sono inizializzati a null. Definire un metodo void set(int r, int c, Entity g) che inserisce l'entità g nella posizione (r, c) della mappa e se (r, c) non è una posizione della mappa, lancia IllegalArgumentException. GeoMap ha un metodo void print(int r, int c, int n) che stampa a video un quadrato di n×n caratteri relativo alla sottomappa che inizia nella posizione (r, c) ed ha n righe e n colonne. Per ogni posizione della sottomappa, se c'è una entità stampa il carattere iniziale del nome, altrimenti stampa il carattere '.' (si veda l'esempio più avanti).

  2. (max 6 punti)  Aggiungere alla classe GeoMap un metodo public int count(String t) che ritorna il numero di entità distinte di tipo t presenti nella mappa (si veda l'esempio più avanti).

  3. (max 6 punti)  Aggiungere un altro costruttore che prende come argomento il pathname di un file e costruisce una mappa con le entità geografiche specificate nel file. Il file ha il seguente formato. La prima linea contiene due interi nr e nc separati da uno spazio che specificano le dimensioni della mappa. le linee successive hanno il formato: C T N r c. Dove C T N sono, nell'ordine, il codice, il tipo e il nome di una entità geografica e r c specificano una posizione occupata dall'entità. Tutte le posizioni non specificate sono inizializzate a null. Per semplicità, si può assumere che il tipo e il nome non contengano spazi. Un esempio di file è il seguente:
    100 200
    1002 CITY Roma 50 15
    1012 RIVER Tevere 48 13
    1012 RIVER Tevere 49 14
    1002 CITY Roma 51 15
    1002 CITY Roma 50 16
    1050 LAKE Albano 47 18
    1050 LAKE Albano 46 18
    1002 CITY Roma 51 16
    1060 LAKE Nemi 46 15
    
Se map è la mappa creata tramite il file d'esempio, l'invocazione map.print(46, 12, 7) stampa:
...N..A
......A
.T.....
..T....
...RR..
...RR..
.......
le invocazioni map.count("LAKE") e map.count("CITY") ritornano, rispettivamente, 2 e 1.