Quando di scrive la definizione di un metodo o una funzione in Xojo è possibile, nello scrivere i parametri, sfruttare diverse possibilità offerte dal linguaggio questo permette di rendere veloce e semplice la creazione di metodi mantenendo il progetto semplice e gestibile.
Parametri per valore o per riferimento?
I parametri sono automaticamente passati per riferimento nel caso di oggetti (compresi gli array). Nel caso di scalari sono passati per valore.
Questo vuol dire che all’interno del metodo o della funzione richiamata, se si modifica il valore del parametro nel caso di un oggetto questo cambierà il suo valore anche nel metodo chiamante (sempre se l’oggetto non sia immutabile, in questo caso si genera un errore), mentre lo scalare sarà con il nuovo valore all’interno ma con il valore originale all’esterno.
//Funzione che modifica il valore del parametro passato: Function esempio(valore as Integer) as Integer valore=valore*2 return valore*10 End Function //Da qualche parte nel nostro codice: Dim numero as Integer=1 Dim risultato as Integer=esempio(numero) //Dopo la chiamata risultato=20 e numero=1 //Lo scalare è rimasto immutato //Esempio con oggetto poniamo di avere una classe Persona con una proprietà nome //Metodo che cambia l'oggetto Sub esempio(unaPersona as Persona) unaPersona.nome="Giovanni" End Sub //Da qualche parte nel nostro codice dim p as new Persona p.nome="Mario" esempio(p) //Ora p.nome vale "Giovanni" |
Per fare in modo di passare un elemento scalare per riferimento in modo che una modifica fatta all’interno di un metodo/funzione abbia effetto anche all’esterno devo usare ByRef (che quindi non è necessario per gli oggetti)
Function esempio2(ByRef valore as integer) as Integer valore=valore*2 return valore*10 End Function //Da qualche parte nel nostro codice: Dim numero as Integer=1 Dim risultato as Integer=esempio(numero) //Dopo la chiamata risultato=20 e numero=2 //Lo scalare è stato modificato |
Overloading
Spesso capita di aver necessità di scrivere più metodi che fanno cose simili in base al tipo di parametro ricevuto. In questo caso non è necessario scrivere, come avviene in diversi linguaggi, più metodi con nomi diversi ma è possibile scrivere metodi con lo stesso nome che verranno utilizzati in base al tipo di parametri utilizzati. Questa tecnica è chiamata overloading e Xojo permette di utilizzarla.
La possibilità deriva dal fatto che nei linguaggi che prevedono l’overloading la “firma” del metodo è data dal nome e dalla sequenza dei parametri, mentre in altri che non lo permettono, ad esempio l’Objective-C, questa è data dal nome del metodo e dai “nomi” di parametri.
Ad esempio se vogliamo definire delle avere una funzioni che eseguono la registrazione di un dato su un file (ad esempio un file di log) potremmo avere:
writeMyLog(value as integer) writeMyLog(value as double) writeMyLog(value as boolean) writeMyLog(value as string) |
Mentre in Objective-C dovremmo scrivere:
writeMyLogFromInteger:(NSInteger *) value writeMyLogFromFloat:(CGFloat)value writeMyLogFromBool:(BOOL)value writeMyLogFromString:(NSString *) value |
Tra l’altro l’IDE di Xojo raggruppa tutti metodi che hanno lo stesso nome in un gruppo rendendone semplice la gestione a livello di IDE.
Valori di default
Xojo permette di definire per ogni parametro un valore di default, permettendo quindi di non dover necessariamente scrivere tutti i parametri o più funzioni diverse in base al numero di parametri.
Ad esempio possiamo definire una funzione che calcola il prezzo con IVA di un prodotto e definire che normalmente questa è il 22%, ma dando la possibilità di indicarne un valore diverso:
function prezzoConIVA(prezzoBase as single, aliquota as single=.22) as single return prezzoBase*(1+aliquota) end function |
e possiamo avere le seguenti chiamate:
dim prezzo as single prezzo=prezzoConIva(1000) //prezzo con IVA standard prezzo=prezzoConIva(1000, .04) //prezzo con IVA al 4% prezzo=prezzoConIva(1000, 0) //prezzo con esenzione IVA |
Metodi per assegnare un valore
Talvolta capita di avere la necessità di gestire una struttura dati non pubblica (per cui non esponiamo i singoli elementi) ma vogliamo anche dare la possibilità di assegnare o leggere valori per questa struttura.
Supponiamo per esempio di avere una struttura dati provvisoria che rappresentano delle persone con delle caratteristiche. Per il momento gestiamo la struttura come dictionary di dictionary, ovvero un dictionary con chiave il nome della persona e valore un dictionary che permette di memorizzare alcune caratteristiche.
La struttura non è pubblica, perché la vogliamo gestire internamente o vogliamo in seguito modificarla senza voler cambiare il codice pubblico per accedere ai dati.
Per leggere i dati possiamo scrivere una normale funzione del tipo (ripeto è un esempio minimalista per comprendere la funzionalità)
function informazione(nome as string, info as string) as variant if persone.hasKey(nome) then dim persona as dictionary=persone.value(nome) if persona.hasKey(info) then return persona.value(info) else //Gestione dell'errore o ritorno di un valore di default indicativo else //Gestione dell'errore o ritorno di un valore di default indicativo end if end function |
Ma possiamo anche scrivere un metodo per assegnare l’informazione:
sub informazione(nome as string, info as string, assigns value as variant) dim persona as dictionary if persone.hasKey(nome) then persona=persone.value(nome) else persona=new dictionary persone.value(nome)=persona end if persona.value(info)=value end sub |
Quindi con l’utilizzo di assigns indichiamo che l’ultimo parametro è un valore che andremo ad assegnare infatti possiamo scrivere:
informazione("Mario", "eta")=25 dim eta as integer=informazione("Mario", "eta") //ottenendo il valore assegnato. |
Questo permette di pubblicare immediatamente una serie di funzionalità per gestire la struttura dati e in seguito possiamo cambiarla (con un database ad esempio) lasciando intatta la parte di codice che accede alla nostra struttura.
Numero non definito di parametri
Un’altra possibilità che si ha utilizzando Xojo è la possibilità di definire metodi che accettano un numero indefinito di parametri dello stesso tipo.
Internamente il parametro definito come paramArray viene considerato un vettore e al pari di assigns deve essere l’ultimo parametro del metodo.
Supponiamo di voler avere una funzione che calcola il prezzo in base ad una serie di sconti commerciali:
Public Function scontoCommerciale(prezzo as single, paramArray sconti as single) as single Dim sconto As Single=1 for i as integer=0 to sconti.ubound sconto=sconto*If(sconti(i)>1, 1, 1-sconti(i)) Next Return prezzo*sconto End Function //Utilizzo dim prezzoScontato as single prezzoScontato=scontoCommerciale(1000, .50) //sconto del 50% prezzoScontato=scontoCommerciale(1000, .50, .30) //sconto del 50+30 |
Questo tipo di funzionalità la utilizziamo ad esempio quando passiamo i parametri per un preparedStatement.