4D v16.3Métodos de proyecto |
|||||||||||||||||||||||
|
4D v16.3
Métodos de proyecto
|
Tipo de parámetro | Cómo se pasa | Comentario |
Campo, variable o expresión de un tipo escalar (número, texto, fecha...) | por valor | Se puede pasar por referencia a través de un puntero, ver abajo |
Campo, variable o expresión de tipo Objeto | por referencia | Ver ejemplo a continuación |
Variable o expresión de tipo Colección | por referencia | |
Variable o expresión de tipo Puntero | por referencia | Ver Pasar punteros a métodos |
Array | No se puede pasar directamente como parámetro | Se puede pasar por referencia a través de un puntero, ver Arrays y punteros |
Table | No se puede pasar directamente como parámetro | Se puede pasar por referencia a través de un puntero, ver Punteros |
Cuando se utilizan campos, variables y expresiones de tipo escalar como parámetros de método, sólo se pasan copias de valores.
Como $1, $2... son variables locales, están disponibles sólo dentro de la subrutina y son borradas al final de la subrutina. Por esta razón, una subrutina no puede cambiar el valor real de los campos o variables pasadas como parámetros al nivel del método llamante. Por ejemplo:
` He aquí parte del método MI MÉTODO
` ...
HACER ALGO([Personas]Apellido) ` Supongamos que [Personas]Apellido es igual a "pérez"
ALERT(([Personas]Apellido)
` Este es el código del método HACER ALGO
$1:=Uppercase($1)
ALERT($1)
La caja de diálogo de alerta mostrada por HACER ALGO contendrá “PÉREZ” y la caja de diálogo mostrada por MI METODO contendrá “pérez”. El método ha modificado localmente el valor del parámetro $1, pero esto no afecta el valor del campo [Personas]Apellido pasado como parámetro por el método MI METODO.
Hay dos maneras de hacer que el método HACER ALGO cambie el valor del campo:1. En lugar de pasar el campo al método, pasar un apuntador, escriba:
` He aquí parte del método MI METODO
` ...
HACER ALGO(->[Personas]Apellido) ` Digamos que [Personas]Apellido es igual a "pérez"
ALERT([Personas]Apellido)
` Este es el código del método HACER ALGO
$1->:=Uppercase($1->)
ALERT($1->)
Aquí el parámetro no es el campo, sino un puntero al campo. Por lo tanto, dentro del método HACER ALGO, $1 ya no es el valor del campo sino un puntero hacia el campo. El objeto referenciado por $1 ($1-> en el código anterior) es el campo real. Por consiguiente, la modificación del objeto referenciado va más allá del alcance de la subrutina, y el campo real es afectado. En este ejemplo, ambas cajas de alerta mostrarán “PÉREZ”.
Para mayor información sobre Punteros, consulte la sección Punteros.
2. En lugar de tener al método HACER ALGO “haciendo algo”, puede reescribir el método de manera que devuelva un valor. De esta forma usted escribiría:
` He aquí parte del código del método MI METODO
` ...
[Personas]Apellido:=HACER ALGO([Personas]Apellido) ` Supongamos que [Personas]Apellido es igual a "pérez"
ALERT([Personas]Apellido)
` Here the code of the method <span class="rte4d_met">HACER ALGO</span>
$0:=Uppercase($1)
ALERT($0)
Esta segunda técnica de que una subrutina devuelva un valor se llama “utilizar una función.” Este punto se describe en los párrafos siguientes.
Cuando se utilizan variables, expresiones o campos de tipo objeto o colección como parámetros de método, se pasan referencias a los valores fuente reales. En este caso, $1, $2... no contienen valores sino referencias. La modificación del valor de los parámetros $1, $2... dentro de la subrutina se propagará donde quiera que se utilice el objeto o la colección fuente. Este es el mismo principio que para los punteros, excepto que los parámetros $1, $2... no necesitan ser desreferenciados en la subrutina.
Por ejemplo:
//El método CreatePerson crea un objeto y lo envía como un parámetro
C_OBJECT($person)
$person:=New object("Name";"Smith";"Age";40)
ChangeAge($person)
ALERT(String(OB get($person;"Age")))
//El método ChangeAge añade 10 al atributo Age del objeto recibido
C_OBJECT($1)
OB SET($1;"Age";OB Get($1;"Age")+10)
ALERT(String(OB get($1;"Age")))
Si ejecuta el método CreatePerson,
ambos cuadros de alerta dirán "50" ya que la misma referencia es manejada por ambos métodos.
4D Server: cuando los parámetros se pasan entre métodos que no se ejecutan en la misma máquina (utilizando por ejemplo la opción Ejecutar en servidor, ver Propiedades de los métodos proyecto), las referencias no se pueden utilizar. En estos casos, se envían copias de los parámetros de objeto y colección en lugar de referencias.
Los métodos pueden devolver valores. Un método que devuelve un valor se llama función.
Los comandos de 4D o de los plug-ins que devuelven un valor también se llaman funciones.
Por ejemplo, la siguiente línea es una instrucción que utiliza la función integrada, Length, para devolver la longitud de una cadena. La instrucción coloca el valor devuelto por Length en una variable llamada
MiLongitud:=Length("¿'Cómo llegué acá?")
Toda subrutina puede devolver un valor. El valor a devolver se coloca en la variable local $0.
Por ejemplo, la siguiente función, llamada Mayusculas4, devuelve una cadena con los primeros cuatro caracteres de la cadena pasados a mayúsculas:
$0:=Uppercase(Substring($1;1;4))+Substring($1;5)
El siguiente es un ejemplo que utiliza la función Mayusculas4 :
NuevaFrase:=Mayusculas4("Esto está bien.")
En este ejemplo, la variable NuevaFrase toma el valor “ESTO está bien.”
El resultado de la función, $0, es una variable local dentro de la subrutina. Puede ser utilizada como tal dentro de la subrutina. Por ejemplo, en el ejemplo anterior el método HACER ALGO, $0 primero fue asignado al valor $1, luego fue utilizado como parámetro del comando ALERT. Dentro de la subrutina, puede utilizar $0 de la misma forma que utilizaría otra variable local. 4D devuelve el valor de $0 (el valor actual cuando la subrutina termina) al método llamado.
Los métodos de proyecto pueden llamarse entre sí. Por ejemplo:
Esto se llama recursividad. El lenguaje de 4D soporta totalmente la recursividad.
Este es un ejemplo. Supongamos que tiene una tabla [Amigos y familiares] compuesta del siguiente conjunto de campos:
- [Amigos y familiares]Nombre
- [Amigos y familiares]NinosNombre
Para este ejemplo, asumimos que los valores en los campos son únicos (no hay dos personas con el mismo nombre). A partir de un nombre, usted quiere construir una frase “Un amigo mio, Juan el hijo de Pedro hijo de Ana hija de Roberto hijo de Eleonor, ¡hace esto para vivir!”:
1. Puede construir la frase de esta forma:
$vsNombre:=Request("Introduzca el nombre:";"Juan")
If(OK=1)
QUERY([Amigos y familiares];[Amigos y familiares]Nombre=$vsNombre)
If(Records in selection([Amigos y familiares])>0)
$vtTodalahistoria:="Un amigo mio, "+$vsNombre
Repeat
QUERY([Amigos y familiares];[Amigos y familiares]NinosNombre=$vsNombre)
$vlQueryResult:=Records in selection([Amigos y familiares])
If($vlQueryResult>0)
$vtTodalahistoria:=$vtTodalahistoria+" el hijo de "+[Amigos y familiares]Nombre
$vsNombre:=[Amigos y familiares]Nombre
End if
Until($vlQueryResult=0)
$vtTodalahistoria:=$vtTodalahistoria+", ¡hace esto para vivir!"
ALERT($vtTodalahistoria)
End if
End if
2. También la puede construir de esta forma:
$vsNombre:=Request("Introduzca el nombre:";"Juan")
If(OK=1)
QUERY([Amigos y familiares];[Amigos y familiares]Nombre=$vsNombre)
If(Records in selection([Amigos y familiares])>0)
ALERT("Un amigo mio, "+Genealogia de($vsName)+", ¡hace esto para vivir!")
End if
End if
con la función recursiva Genealogia de listada aquí:
` Método de proyecto Genealogia de
` Genealogia de ( Cadena ) -> Texto
` Genealogia de ( Nombre ) -> Parte de la frase
$0:=$1
QUERY([Amigos y familiares];[Amigos y familiares]NinosNombre=$1)
If(Records in selection([Amigos y familiares])>0)
$0:=$0+" hijo de "+Genealogia de([Amigos y familiares]Nombre)
End if
Observe que el método Genealogia de se llama a sí mismo.
La primera forma es un algoritmo iterativo. La segunda es un algoritmo recursivo.
Cuando implemente código para casos como el del ejemplo anterior, es importante tener en cuenta que usted siempre puede escribir métodos utilizando iteración y recursividad. Generalmente, la recursividad ofrece código más conciso, fácil de leer y de mantener, pero su uso no es obligatorio.
Algunos usos típicos de recursividad en 4D son:
Importante: las llamadas recursivas deben terminar en algún momento. En el ejemplo, el método Genealogia de deja de llamarse a sí mismo cuando la búsqueda no devuelve registros. Sin esta condición, el método se llamaría a sí mismo indefinidamente; finalmente, 4D devolvería un error “Pila llena” porque no habría espacio para “apilar” las llamadas (así como los parámetros y las variables locales utilizadas en el método).
Producto: 4D
Tema: Presentación del lenguaje
Manual de lenguaje 4D ( 4D v16)
Manual de lenguaje 4D ( 4D v16.1)
Manual de lenguaje 4D ( 4D v16.2)
Manual de lenguaje 4D ( 4D v16.3)