Skip to content

Impariamo Xojo: Metodi e parametri

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
Questo può essere utile ad esempio quando vogliamo passare uno scalare ad un evento che definiamo e lasciare la possibilità di modificarlo o lasciarlo immutato se l’evento non viene implementato.

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.