BlackTDN Search

quarta-feira, 21 de janeiro de 2009

Protheus :: Programação Básica em Advpl “Combo XXXV”

Passando Arrays por Referência:

Verificamos que as variáveis do tipo Array são realmente passadas por valor. Mas podemos, também, passá-las por referência. Para que isso aconteça, temos que preceder o parâmetro real com o símbolo @. Dessa forma, poderemos mudar os elementos do array como antes, e a rotina continuará recebendo uma referência aos elementos do array. Mas, neste caso, a diferença é que, agora, podemos mudar aquilo a que o array se refere, uma vez que a própria variável array foi passada por referência. Podemos ilustrar isso da seguinte forma:

Local aNomes := { “P.A.Cabral” , “Santos Dumont” }

U_Test( @aNomes )

Alert( aNomes[1] ) // “Einstein”

User Function Test( aFormal )

Alert( aFormal[1] ) // P.A.Cabral

aFormal := { “Einstein” , “Leibiniz” }

Return( NIL )

Se quisermos que a rotina chamada nunca altere o valor do array original, podemos forçar que ela sempre receba uma cópia do array ao invés do próprio array. Isso pode ser feito utilizando a função aClone() da seguinte forma:

Local aNomes := { “P.A.Cabral” , “Santos Dumont” }

U_Test( aClone( aNomes ) )

Alert( aNomes[1] ) // “P.A.Cabral”

User Function Test( aFormal )

Alert( aFormal[1] ) // P.A.Cabral

aFormal[1] := “Einstein”

Alert( aFormal[1] ) //“Einstein”

Return( NIL )

A função aClone() para uma cópia do Array criando uma nova referência. Dessa forma, garantimos, na função chamadora a integridade do array mas, na função chamada podemos alterar o conteúdo da maneira que quisermos.

Para exemplificar melhor a passagem por referência, tomemos como exemplo o seguinte fragmento de código que referência uma variável do tipo numérica.

Local nVar := 1
Local cVar

U_Test( @nVar )
cVar := Str( nVar )
Alert( cVar ) //Aqui nVar terá o valor 3

User Funcion Test( nFormal )
nFormal := 3
Return( NIL )

Passamos nVar por referência para a função U_Test(); portanto, no retorno, nVar foi alterada. Um aspecto importante a observar é que, dentro da função U_Test(), não sabemos se nFormal foi passado por referência ou por valor. Apenas fizemos a atribuição. Este processo é diferente em linguagens como C, que não suportam envio por referência. Na linguagem C, se quisermos permitir que uma rotina altere um parâmetro, precisaremos passar o endereço do parâmetro. Conseqüentemente, a rotina receptora receberá um ponteiro para a verdadeira variável e a modificará por vias indiretas. Neste caso a rotina receptora precisa saber como o parâmetro foi passado ( o que não acontece em Advpl ).

Em Advpl ocorre uma via indireta “implícita” quando fazemos uma atribuição a um parâmetro formal que a rotina chamadora passa por referência. Isso poderá ser visualizado se imaginarmos que a codificação em Advpl recebesse um ponteiro para um parâmetro real e, toda vez que mudássemos um parâmetro passado por referência, estaríamos alterando o parâmetro real. O compilador ou o sistema, na execução, estarão implementando a via indireta.

Mas como isso se aplica aos arrays passados por referência? Já vimos que os arrays são implementados como ponteiros; portanto, ao passar um array por referência, na verdade, estamos passando um ponteiro para um ponteiro. O Advpl manipula a via indireta quando acessamos os elementos, mas, como recebemos uma referência à variável do array, podemos mudar aquilo para o qual o array aponta, além do seu conteúdo.

Nenhum comentário:

Postar um comentário