Aiuto per un costruttore

di il
11 risposte

Aiuto per un costruttore

Salve ragazzi mi servirebbe aiuto per la creazione del costruttore di una classe.
Classe: Angolo
Attributi: gradi, primi, secondi (tutti di tipo intero ovviamente)
vorrei creare un costruttore che mi controlli se i tre parametri possono essere accettati, mi spiego meglio.. i gradi devono essere compresi tra 0 e 360 , i primi tra 0 e 60 e anche i secondi tra 0 e 60 .. come mi conviene procedere .. con dei semplici controlli if? grazie in anticipo!

11 Risposte

  • Re: Aiuto per un costruttore

    gaab ha scritto:


    .. come mi conviene procedere .. con dei semplici controlli if?
    Sì, bastano degli if con condizioni che usano gli operatori relazionali ( < > ). Se c'è almeno un valore inappropriato puoi far lanciare IllegalArgumentException che è fatta apposta per questo (e magari con un message descrittivo del singolo problema, es. "i gradi non devono essere inferiori a 0")


    P.S. sarò arruginito io ma ... il 60 è compreso o escluso?
  • Re: Aiuto per un costruttore

    0 compreso 60 escluso, sia per i primi che per i secondi..
    ora provo a farlo e in caso scrivo il codice quando finisco.. Grazie mille.
  • Re: Aiuto per un costruttore

    Salve gaab, se implementata bene la tua classe Angolo rassomiglierà molto a java.time.LocalTime , quindi ti consiglio di aggiungere qualche costruttore in più (ad esempio solo gradi e primi).
    Poi passando al costruttore ad esempio 35°77'63" sta a te la scelta se non accettarlo o trasformarlo in 36°18'3".
    Qualche annetto fa ho creato una classe simile in C# (Degree).

    andbin ha scritto:


    P.S. sarò arruginito io ma ... il 60 è compreso o escluso?
    andbin, non posso credere che sei caduto sul modulo 60! Era proprio una buccia di banana.
  • Re: Aiuto per un costruttore

    @raph1328
    Mi puoi spiegare il senso del tuo post?
    Cosa c'entra la classe LocalTime con la classe Angolo?
  • Re: Aiuto per un costruttore

    Salve xneo, forse mi hai frainteso, NON intendevo "Angolo extends LocalTime" o robaccia simile. Ma facevo notare che la classe Angolo potrebbe avere membri ad esempio:
    aggiungiGradi|Primi|Secondi(); sottraiGradi|Primi|Secondi(); isMinore(); isMaggiore(); aggiungi(int,int,int); sottrai(int,int,int); MIN; MAX
    così come li ha più o meno LocalTime:
    plusHours|Minutes|Seconds|Nanos(), minusHours|Minutes|Seconds|Nanos(), isBefore(), isAfter(), plus(), minus(), MIN, MAX
    e nient'altro.

    Trascuriamo i vari overloads di LocalTime.of(), non non credi sia la soluzione ideale avere più costruttori che chiamano quello con più parametri (sempre purché gradi|primi|secondi siano private e non ci siano i rispettivi setter).
    Gia che ci stiamo un "implements Comparable<Angolo>" non farebbe male.
    Se ci vuoi anche la ciliegina sulla torta c'aggiungo prodotto|divisione(Angolo, int) . (Il prodotto tra
    Angoli sarà una cavolata, ma tra Angolo e scalare non lo è.)
    Anzi è un peccato che in Java non si possa sovrascrivere gli operatori, in questo caso farlo per: +, -, >, <, ==, >=, <=, != ci stava bene!
    Che ne pensi?
  • Re: Aiuto per un costruttore

    non credi sia la soluzione ideale avere più costruttori che chiamano quello con più parametri
    No non è la soluzione ideale.
    Questi tipi di costruttori vengono definiti "costruttori telescopici" ed è sconsigliato farne uso.
    Se da un lato evitano il dover riscrivere porzioni di codice già scritto, dall'altra introducono problemi di leggibilità del codice e anche problemi di usabilità soprattutto se i parametri sono tutti dello stesso tipo.
  • Re: Aiuto per un costruttore

    @xneo Non metto in dubbio ciò che dici, ma in questo caso specifico dove ci si aspettino parametri ordinati in un certo modo non vi saranno equivoci su quali siano i costruttori in base alla precisione della misurazione scelta
    
    Angolo(){}//ce lo metto se si vuole subito un'istanza 0°0'0"
    Angolo(int gradi){}
    Angolo(int gradi, int primi){}
    Angolo(int gradi, int primi, int secondi){}
    
    Il nome dei parametri sarà d'aiuto per l'utente finale e volendo il JavaDoc pure.
    Ma ovviamente non potranno coesistere altre combinazioni di costruttori tipo questi
    
    Angolo(int secondi){}
    Angolo(int secondi, int primi){}
    Angolo(int gradi, int secondi){}
    
    Qui nel forum sappiamo che nella signature conta il tipo e non il nome del parametro.

    Anche nella restituzione in gruppo degli attributi ci si aspetta lo stesso ordine, ovvero un int[]{gradi, primi, secondi} o una string nel formato ggg°pp'ss".

    Se lo vuoi sapere la mia classe Degree ha costruttori telescopici sia così che con l'ultimo parametro di tipo double; non lancia eccezioni perché accetta e restituisce sempre un valore.

    Altro caso.
    Se avessimo avuto una classe Prova con attributi: alpha, uno, primo tutti di tipo String i costruttori telescopici sono la soluzione peggiore, concordando col tuo discorso, perché quale ordine di 3 parametri scegliere? La signature è la stessa Prova(String,String,String).
    Lo stesso è crearne uno con 2 parametri: Quale escludere? Quale ordine scegliere?
    Anche a 1 parametro: Quale mettere?

    Se non sei d’accordo sul discorso fammi un esempio.

    PS. Una curiosità: Ti rendi conto che dibattiamo animosamente mentre gaab potrebbe crearsi una semplice classe senza tanti fronzoli ignorando il mio intervento fin dall'inizio?
  • Re: Aiuto per un costruttore

    Questo è un caso semplice con pochi parametri.
    Il mio discorso vale in generale e devi sempre considerare il fatto che il codice evolve.

    Magari quando inizi a scrivere una classe hai 2,3 costruttori telescopici al massimo, poi ti accorgi che ti serve un altro costruttore con un altro parametro in più, poi un altro costruttore con due parametri in più, ecc.

    Se i parametri sono tutti dello stesso tipo, quando sono "troppi" quando vai ad istanziare l'oggetto potresti confonderti con l'ordine; inoltre di solito quell'oggetto dovrà essere utilizzato da una persona diversa da te e sebbene ci sia una documentazione (javadoc per java) il rischio di confondere la posizione dei parametri è molto alta.

    Se vuoi un esempio, eccolo qui:
    public class NutritionFacts {
        private final int servingSize; // (mL) required
        private final int servings; // (per container) required
        private final int calories ; // optional
        private final int fat ; // (g) optional
        private final int sodium; // (mg) optional
        private final int carbohydrate; // (g) optional
    
        public NutritionFacts( int servingSize, int servings) {
            this(servingSize, servings, 0);
        }
        public NutritionFacts( int servingSize, int servings, int calories ) {
            this(servingSize, servings, calories , 0);
        }
        public NutritionFacts( int servingSize, int servings, int calories , int fat ) {
            this(servingSize, servings, calories , fat , 0);
        }
        public NutritionFacts( int servingSize, int servings, int calories , int fat , int sodium) {
            this(servingSize, servings, calories , fat , sodium, 0);
        }
        public NutritionFacts( int servingSize, int servings, int calories , int fat , int sodium, int carbohydrate) {
            this.servingSize = servingSize; this.servings = servings; this. calories = calories ;
            this. fat = fat ; this.sodium = sodium; this.carbohydrate = carbohydrate;
        }
    }
    Si nota subito che occorre estrema attenzione per istanziare un oggetto NutritionFacts con tutti i parametri.
    Inoltre supponiamo che ho intenzione di non specificare la quantità di grassi, ma la quantità di sodio e carboidrati in questo caso devo comunque usare il costruttore con il massimo numero di parametri e fornire il valore 0 per i grassi.
  • Re: Aiuto per un costruttore

    Ti rispondo con le citazioni:

    xneo ha scritto:


    Il mio discorso vale in generale
    Per questo continuiamo a discutere: tu parli in generale, mentre io no.

    raph1328 ha scritto:


    non non credi sia la soluzione ideale avere più costruttori che chiamano quello con più parametri
    Era sottinteso "in questo caso specifico", in questa frase ci trovi la parola "sempre" o "per ogni classe"?

    raph1328 ha scritto:


    @xneo Non metto in dubbio ciò che dici
    Concordo con te se parli in generale, gia te l'ho detto!

    xneo ha scritto:


    devi sempre considerare il fatto che il codice evolve.
    E chi dice di no, ma la classe Angolo - qui sottoposta ad esame - non si evolverà con altri attributi, al massimo avrà metodi in più.
    Per inserirne un altro con una certa logica occorre un ordine di grandezza maggiore o minore ai soliti 3. Ragionando per assurdo:
    superiore all'angolo giro rimane solo che contarli, ma a che può servire ai fini d'un calcolo con le funzioni trigonometriche sessagesimali create in un'altra classe ad-hoc?
    Il secondo di grado è già abbastanza piccolo di per sé che non conviene usare una quantità 1/60 o 1/100 più piccola. Ad esempio un arco di 1" che ha tangente di 1 cm dovrebbe avere un raggio di 1/tan(1") = 206264,81 ovvero poco più di 2 km (è lo stesso rapporto tra 1 parsec ed 1 unità astronomica). Anche i militari hanno smesso da un bel po' di puntare i cannoni girando la manovella oppure fare rilevamenti topografici con 2 punti ravvicinati tra loro e lontani 2 km vuol dire stare messi proprio male!


    Per quanto riguarda la tua classe NutritionFacts visto che si tratta solo d'assegnare valori senza calcoli avrei fatto
    public NutritionFacts( int servingSize, int servings) {
            this.servingSize = servingSize; this.servings = servings;
    }
    public NutritionFacts( int servingSize, int servings, int calories) {
            this(servingSize, servings); 
            this.calories = calories;
    }
    //...
    
    per dar più importanza al 1° costruttore senza fargli fare la cascata di chiamate, ma inserendo gli altri costruttori il problema di confusione resta!
    Mentre per gaab va bene perché
    
    Angolo(int gradi, int primi){
       this(gradi,primi,0);// altrimenti perché ricopiare i calcoli qui?
    }
    Angolo(int gradi, int primi, int secondi){
        // calcoli + assegnamento
    }

    xneo ha scritto:


    Se i parametri sono tutti dello stesso tipo, quando sono "troppi" quando vai ad istanziare l'oggetto potresti confonderti con l'ordine
    Se hai "troppi" attributi soprattutto se opzionali mica andrai a creare un costruttore con tutti quei parametri?

    xneo ha scritto:


    Inoltre supponiamo che ho intenzione di non specificare la quantità di grassi, ma la quantità di sodio e carboidrati in questo caso devo comunque usare il costruttore con il massimo numero di parametri e fornire il valore 0 per i grassi.
    Se l'hai impostato così ... allora trucca pure che non t'ingrassi.

    Su mettiamo un break in questo loop! Incomincio io!
  • Re: Aiuto per un costruttore

    Salve ragazzi scusate il ritardo, ma ho avuto qualche problema con la conneseione. Questo è ciò che ho pensato
    public void aggiungiSecondi(int n){
    int p; 
    secondi =secondi +n;
    p=secondi/60;
    secondi=secondi %60;
    aggiungiPrimi(p);
    } 
    Così anche per i metodi aggiungiprimi(),richiamando aggiungiGradi(), aggiungiGradi() che alla fine non richiama altri metodi facendo solo le sue operazioni, mentre per quanto riguarda il costruttore l'ho fatto proprio semplice.
    public Angolo(int gradi, int primi, int secondi){
    this.gradi=gradi;
    this.primi=primi
    this.secondi=secondi;
    }
    Il discorso delle eccezioni non l'ho ancora capito benissimo
  • Re: Aiuto per un costruttore

    @gaab aggiungiSecondi() più o meno va bene, ma prima di metterci ancora mano concentrati sull’obbiettivo: la tua domanda che sta ad inizio pagina ed i suggerimenti di andbin.
    Le mie proposte vengono dopo.
    [quote=gaab]Il discorso delle eccezioni non l'ho ancora capito benissimo [/quote]
    Purtroppo te le devi rivedere, altrimenti supponiamo che utilizzi in modo spropositato la tua classe:
        public static void main(String[] args){
            Angolo alfa = new Angolo(452,88,34);
            Angolo beta = new Angolo(47,Integer.MAX_VALUE,-6);
            Angolo gamma = new Angolo(Integer.MIN_VALUE,97,-3473);
            System.out.println(alfa.getGradi()+"°"+alfa.getPrimi()+"'"+alfa.getSecondi()+"\""); // suppongo ci siano i getters
            //452°88'34"
            System.out.println(beta.getGradi()+"°"+beta.getPrimi()+"'"+beta.getSecondi()+"\"");
            //47°2147483647'-6"
            System.out.println(gamma.getGradi()+"°"+gamma.getPrimi()+"'"+gamma.getSecondi()+"\"");
            //-2147483648°97'-3473"
            Angolo delta = new Angolo(217,36,44); 
            delta.aggiungiSecondi(Integer.MIN_VALUE);
            delta.aggiungiSecondi(Integer.MAX_VALUE);
        }
    Come faccio a sapere quali valori posso usare?
    [quote=gaab] i gradi devono essere compresi tra 0 e 360 , i primi tra 0 e 60 e anche i secondi tra 0 e 60 [/quote]
    Fino ad ora è falso!

    Una volta risolto potrai controllare i risultati imprevisti di aggiungiSecondi e sistemarla. Occhio all’intero che superi Integer.MAX_VALUE o sia inferiore a Integer.MIN_VALUE .
Devi accedere o registrarti per scrivere nel forum
11 risposte