|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
[generico]Costruttori con molti parametri
Ciao a tutti
![]() La mia più che altro è una curiosità.. Vi capita mai di avere a che fare con costruttori che abbiano molti parametri ? per es.: Codice:
public DatiAnagrafici(cognome, nome, dataDiNascita, comuneDiNascita, provincia, blablabla con molti campi ? Grazie ![]() RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek ![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Se stiamo parlando di semplificare un metodo (costruttore o altro) e in particolare di ridurre la sua lista dei parametri, penso la cosa vada vista caso per caso.
Ad esempio, eaminando quello che hai postato, mi vengono in mente due scenari diversi e due possibilità: 1) la classe DatiAnagrafici è un "value object" che mappa la tabella di un db relazionale: in questo caso non mi pare si possa fare molto, visto che si e' costretti a rispettare la struttura della tabella che giustifica l'esistenza della classe stessa. 2) la classe DatiAnagrafici non è un value object e quindi posso rifattorizzarla come mi pare. In questo caso vale la pena di osservare che potrei dividere i parametri in due gruppi: uno relativo al concetto di "Persona" (cognome, nome, dataNascita) e l'altro relativo al concetto di "Indirizzo" o "Luogo" cha a dir si voglia (comune, provincia, ecc...). In questo caso potrei vedere il costruttore di DatiAnagrafici così: Codice:
DatiAnagrafici(Persona p, Indirizzo luogoDiNascita) {...} Codice:
class Persona { private String nome; private String cognome; private final Indirizzo luogoDiNascita; private final Data dataDiNascita; private Indirizzo residenza; ... public Persona(String nome, String cognome, Data dNascita, Indirizzo iNascita) {...} ... public void getLuogoDiNascita(Indirizzo ind) {luogoDiNascita=ind;} public void setResidenza(Indirizzo res) {residenza=res;} ... } Se più in generale ti interessanto le tecniche di refactoring del codice qui trovi un buon punto di partenza.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Dipende anche dal linguaggio. Esempio:
Codice:
>>> class c: ... def __init__(self, *Args, **Keys): ... self.Arguments = Args ... self.Keywords = Keys ... def __str__(self): ... return 'Mi hai passato gli argomenti %s e le keyword %s' % (self.Arguments, self.Keywords) ... >>> a = c(1, 2, 3, a = 'Qui', b = 'Quo', c = 'Qua') >>> print a Mi hai passato gli argomenti (1, 2, 3) e le keyword {'a': 'Qui', 'c': 'Qua', 'b': 'Quo'}
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Apr 2008
Città: Varese
Messaggi: 406
|
Nooooo che brutta sintassi cdimauro
![]() ![]() ![]() ![]() prrrr ![]() PS. ottimo esempio! Grande il pitone! ![]()
__________________
IT Developer at Hardware Upgrade S.r.l. self.love(this.me()); |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Equivalente tradotto in Java;
Codice:
public class Prova { Integer[] args; Map<String,String> keys; public Prova(Integer[] args, Map<String,String> keys) { this.args = args; this.keys = keys; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Mi hai passato gli argomenti"); for (Integer i : args) { sb.append(" ").append(i).append(" "); } sb.append("e le keyword"); for (Map.Entry<String,String> keyword : keys.entrySet()) { sb.append(" ") .append(keyword.getKey()).append(" = ").append(keyword.getValue()) .append(" "); } return sb.toString(); } public static void main(String... argv) { Integer[] args = {1,2,3}; Map keys = new HashMap<String,String>(); keys.put("a", "Qui"); keys.put("b", "Quo"); keys.put("c", "Qua"); Prova a = new Prova(args, keys); System.out.println(a); } } // output: // Mi hai passato gli argomenti 1 2 3 e le keyword b = Quo c = Qua a = Qui Immagino in C# sia lo stesso, e in genere ovunque uno possa passare come argomento ad un metodo un tipo-collezione, per così dire.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 06-11-2009 alle 10:29. |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Ciao a tutti !
![]() allora, in ordine : @Banryu79: Anche io avevo pensato a semplificare il costruttore più o meno nel modo da te indicato ma, se è vero che semplifico il costruttore, vado poi a fare le stesse cose all'interno del metodo, per esempio: Codice:
void AggiungiNominativo(Persona p) { //necessariamente dovrò creare o qui o altrove //un oggetto Persona e: p.Cognome = valore; p.Nome = valore; etc.. } come correttamente sottolineato da te, li per forza di cosa bisogna semplicemente rappresentare la tabella e amen. @cdimauro In effetti ho visto che sia in java che in c# esiste una tecnica particolare per passare molti parametri (indicata però solo nei casi in cui non se ne conosca a monte il numero) Codice:
//Java public double getQualcheEuro(double... euri); //C# public double GetQualcheEuro(params[] double); //o anche ma non è CLS; dalla documentazione ufficiale [assembly: CLSCompliant(true)] namespace UsageLibrary { public class UseParams { // This method violates the rule. [CLSCompliant(false)] public void VariableArguments(__arglist) { ArgIterator argumentIterator = new ArgIterator(__arglist); for(int i = 0; i < argumentIterator.GetRemainingCount(); i++) { Console.WriteLine( __refvalue(argumentIterator.GetNextArg(), string)); } } // This method satisfies the rule. public void VariableArguments(params string[] wordList) { for(int i = 0; i < wordList.Length; i++) { Console.WriteLine(wordList[i]); } } } }
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek ![]() |
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Le soluzioni Java e C# possono sembrare simili, ma sono molto diverse: state semplicemente utilizzando classi di tipo lista o mappa/dizionario per cercare di mascherare il passaggio di una quantità variabile di parametri.
Anche in Python esistono da tempo le liste e le mappe/dizionari, per cui si poteva applicare la stessa soluzione. Ma qui stiamo parlando di parametri in quantità variabile, cioè una funzione/metodo cambia la sua arietà dinamicamente in base al chiamante. Può sembrare sottile, ma col seguente esempio si capisce perché la differenza è, invece, notevole: Codice:
>>> class c: ... def __init__(self, a, b, c, x = 1, y = 2, z = 3, *Args, **Keys): ... Args = (a, b, c) + Args ... Keys.update({'x' : x, 'y' : y, 'z' : z}) ... self.Arguments = Args ... self.Keywords = Keys ... def __str__(self): ... return 'Mi hai passato gli argomenti %s e le keyword %s' % (self.Arguments, self.Keywords) ... >>> a = c(1, 2, 3, 4, 5, Emi = 'Qui', Eli = 'Quo', Evy = 'Qua') >>> print a Mi hai passato gli argomenti (1, 2, 3) e le keyword {'Evy': 'Qua', 'Eli': 'Quo', 'y': 5, 'x': 4, 'z': 3, 'Emi': 'Qui'} >>> a = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, Emi = 'Qui', Eli = 'Quo', Evy = 'Qua') >>> print a Mi hai passato gli argomenti (1, 2, 3, 7, 8, 9, 10) e le keyword {'Evy': 'Qua', 'Eli': 'Quo', 'y': 5, 'x': 4, 'z': 6, 'Emi': 'Qui'}
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Certamente. Con arietà intanto definiamo il numero di argomenti accettati (o che si aspetta) una determinata funzione (o metodo).
Nel caso in oggetto, abbiamo un costruttore (quindi una funzione) della classe c che accetta almeno 6 parametri, di cui i primi 3 fissi / obbligatori, e i seguenti 3 opzionali. Inoltre può accettare un qualunque altro numero di parametri, siano essi con o senza nome, i quali, se presenti, vengono inseriti nella tupla (è una lista non modificabile) Args oppure nel dizionario (mappa) Keys rispettivamente. Tutti i parametri definiti si possono referenziare col nome. Esempio: Codice:
>>> a = c(a = 0, b = -1, c = -2) >>> print a Mi hai passato gli argomenti (0, -1, -2) e le keyword {'y': 2, 'x': 1, 'z': 3} - se ci sono parametri obbligatori, questi devono essere necessariamente presenti (e lo si può fare senza specificare il nome, visto che sono sempre i primi, oppure col nome, come ho mostrato poco sopra); - se sono presenti altri parametri senza che venga specificato il loro nome, questi vengono assegnati agli eventuali parametri con valore di default (x, y e z, nello specifico caso); - se sono presenti ulteriori parametri senza nome, vengono tutti inseriti in *Args (il nome ovviamente si può cambiare); - se sono presenti parametri con nome che non coincidono coi parametri con valori predefiniti, questi vengono tutti inseriti in **Keys (anche qui si può cambiare il nome). Le istruzioni: Codice:
Args = (a, b, c) + Args Keys.update({'x' : x, 'y' : y, 'z' : z}) Se ci sono dubbi, fammi/temi sapere.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Apr 2008
Città: Varese
Messaggi: 406
|
cdimauro docet!
__________________
IT Developer at Hardware Upgrade S.r.l. self.love(this.me()); |
![]() |
![]() |
![]() |
#12 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Ok, mi ero "perso" a causa dei parametri con valore di default, che in Java non ci sono (e la mia memoria storica del C++ ormai è stata relegata chissà dove...), mea culpa. Ora ho capito, grazie alla tua spiegazione, ma la cosa (probabilmente perchè non ne sono abituato) mi pare un poco error-prone.
Più che altro, mi domando in quali situazioni/scenari possa tornare molto comoda questa funzionalità?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
![]() |
![]() |
![]() |
#13 |
Senior Member
Iscritto dal: Feb 2003
Città: Stockholm (SE)
Messaggi: 1343
|
Data questa classe:
Codice:
public class Person { public string FirstName { get; set; } public string LastName { get; set; } public string City { get; set; } public DateTime DateOfBirth { get; set; } public Person.Sex Sex { get; set; } public enum Sex { Male = 0, Female = 1 } } Codice:
Person p = new Person { FirstName = "Salvatore", LastName = "Esposito", City = "Napoli", DateOfBirth = new DateTime( 1970, 12, 1), Sex = Person.Sex.Male }; |
![]() |
![]() |
![]() |
#14 | |||
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Quote:
Quote:
![]() Quote:
![]() x michele.broggi: esagerato! ![]()
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|||
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Apr 2008
Città: Varese
Messaggi: 406
|
Sono serio cdimauro, tu sei da curare!
Ciò che hai scritto è sensazionale per gli occhi di un programmatore ![]() ![]()
__________________
IT Developer at Hardware Upgrade S.r.l. self.love(this.me()); |
![]() |
![]() |
![]() |
#16 | |
Member
Iscritto dal: Nov 2009
Messaggi: 56
|
Quote:
mi scusa in anticipo per la mia ignoranza, ma con params in c# non ottieni il risultato di cambiare dinamicamente il numero di parametri passati? ma forse non mi è ancora molto chiaro il significato di questa discussione ![]() ![]() edit capisco che sia comodo con i parametri con valore di default, ma se in un linguaggio non ci sono è chiaro che sia diverso, e il metodo piu' elegante sarà diverso. Ma forse non ho afferrato la domanda iniziale.
__________________
Un elemento come me quando si fissa fa sempre un gran casino, ma solo nel 45 ciò è stato negativo . Little Boy era mio nonno Ultima modifica di U235 : 06-11-2009 alle 21:25. Motivo: spiegazioni |
|
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Per fugare un pò ogni dubbio:
Usare in C# i params, equivale a non sapere quanti parametri possano essere passati in anticipo, ma, per la mia domanda iniziale, non era questo il caso che mi incuriosiva. La mia domanda era rivolta invece quando in presenza di un numero elevato e fisso di parametri, ci fosse un modo migliore per non passarli tutti nel costruttore o in un metodo. Giustamente Banryu79 ha fatto una degna osservazione sull'ambito: 1) devi rappresentare tabelle di un db ? <= ciccia ![]() 2) devi rappresentare altro ? <= probabilmente il design è sbagliato a monte e c'è bisogno di refactor. Però... per la (1) forse forse con un ORM si potrebbe ottenere un design migliore . Questo, ovviamente, non toglie nulla a quanto mostrato da cdimauro con python, anche perchè il titolo è appunto [generico] e non mi riferivo in particolare ad un linguaggio ![]() chissà che un domani non riesca a farci qualcosina pure io col pitone oltre a mangiarmene di crudi per colazione ![]()
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek ![]() |
![]() |
![]() |
![]() |
#18 | ||||
Member
Iscritto dal: Nov 2009
Messaggi: 56
|
Quote:
Quote:
![]() secondo me dipende dai linguaggi, da come devi utilizzarli ecc. Quote:
![]() ![]() Quote:
![]() ![]()
__________________
Un elemento come me quando si fissa fa sempre un gran casino, ma solo nel 45 ciò è stato negativo . Little Boy era mio nonno |
||||
![]() |
![]() |
![]() |
#19 | |||
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Eh, no: adesso non ci siamo proprio.
Quote:
Quote:
Quote:
![]() Comunque male non ti farà di sicuro lavorare con Python. ![]()
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|||
![]() |
![]() |
![]() |
#20 | |
Senior Member
Iscritto dal: Feb 2003
Città: Stockholm (SE)
Messaggi: 1343
|
Quote:
![]() Codice:
private DateTime _DateOfBirth; public DateTime DateOfBirth { get { return _DateOfBirth; } set { if (value > DateTime.Today) throw new OMGException("OMG!"); _DateOfBirth = value; } } |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 03:05.