4D v16.3

Guía de declaración

Inicio

 
4D v16.3
Guía de declaración

Guía de declaración  


 

 

Esta sección describe las principales causas de conflictos de tipos en variables, como también las maneras de evitarlos.

Los conflictos de tipos simples pueden resumirse en:

  • conflictos entre dos usos,
  • conflictos entre uso y una directiva de compilación,
  • conflictos por declaración implicita,
  • conflictos entre dos directivas de compilación.

El conflicto de tipo más simple es aquel en el que un nombre de variable está designado a dos objetos diferentes. Imagine que en una aplicación, usted escribe:

 Variable:=5

y que en otra parte, de la misma aplicación, escribe:

 Variable:=True

Esto genera un conflicto de tipo de datos. El problema puede resolverse renombrando una de las variables.

Suponga que escribe en una aplicación:

 Variable:=5

y que en otra parte, en la misma aplicación, escribe:

 C_BOOLEAN(Variable)

Como el compilador primero revisa las directivas, hará la variable de tipo Booleano, pero cuando encuentre:

 Variable:=5

detectará un conflicto de tipo de datos. Puede resolver el problema renombrando la variable o modificando la directiva de compilación.

La utilización de variables de tipos diferentes en una expresión genera inconsistencias. El compilador señala las incompatibilidades. Este es un ejemplo simple:

vBool:=True `El compilador deduce que vBoolean es de tipo Booleano
C_LONGINT(<>vInteger) `Declaración de un Entero largo por una directiva de compilación
<>vInteger:=3 `Comando compatible con la directiva de compilación
Var:= <>vInteger+vBool `Operación que contiene variables con tipos de datos incompatibles

Algunas funciones devuelven variables de un tipo muy preciso. La asignación del resultado de una de estas variables a una variable ya declarada de forma diferente provocará un conflicto de tipos si no tiene cuidado.
Por ejemplo, en una aplicación interpretada, puede escribir:

 IdentNo:=Request("Número de identificación") `IdentNo es de tipo Texto
 If(Ok=1)
    IdentNo:=Num(IdentNo) `IdentNo es de tipo Real
    QUERY([Contactos]Id=IdentNo)
 End if

En este ejemplo, usted genera un conflicto de tipos en la tercera línea. La solución consiste en controlar el comportamiento de la variable. En algunos casos, deberá crear una variable intermedia que utilice un nombre diferente. En otros casos, como este, puede estructurar su método de una forma diferente:

 IdentNo:=Num(Request("Número de identificación")) `IdentNo es de tipo Real
 If(Ok=1)
    QUERY([Contactos]Id=IdentNo)
 End if

Declarar la misma variable por dos directivas de compilación diferentes constituye una redeclaración. Si escribe en la misma base:

 C_BOOLEAN(Variable)
 C_TEXT(Variable)

el compilador detecta el conflicto y reporta un error en el archivo de error. Generalmente, puede resolver el problema renombrando una de las variables.

Los conflictos de tipo para las variables locales son idénticos a los conflictos de tipo para las variables proceso o interproceso. La única diferencia es que debe haber consistencia sólo en un método específico.
Para las variables proceso e interproceso, los conflictos ocurren a nivel general de la base. Para las variables locales, los conflictos ocurren al nivel del método. Por ejemplo, no puede escribir en el mismo método:

 $Temp:="Flores"

y luego

 $Temp:=5

Sin embargo, puede escribir:

 $Temp:="Flores"

en método M1 y:

 $Temp:=5

en método M2, porque el alcance de las variables locales es el mismo método y no la base completa.

Los conflictos sobre un array nunca están relacionados con el tamaño del array. En modo compilado como en modo interpretado, los arrays son administrados dinámicamente. El tamaño de un array puede variar a través de los métodos, y no tiene que declarar un tamaño máximo para un array.
Por lo tanto, puede dimensionar un array en cero, añadir o eliminar elementos o borrar el contenido.

Debe seguir las siguientes pautas cuando escribe una base destinada a ser compilada:

  • No cambiar los tipos de elementos del array,
  • No cambiar el número de dimensiones de un array,
  • Para un array Alfa, no cambiar la longitud de las cadenas de caracteres.

Si declara un array como un array Entero, debe permanecer como un array Entero en toda la base. Por ejemplo, nunca podrá contener elementos de tipo Booleano.
Si escribe:

 ARRAY INTEGER(MiArray;5)
 ARRAY BOOLEAN(MiArray;5)

el compilador no puede identificar el tipo de MiArray.
Simplemente renombre uno de los arrays.

En una base interpretada, puede cambiar el número de dimensiones de un array. Cuando el compilador establece la tabla de símbolos, se manejan de diferente forma los array de una dimensión que los bidimensionales.
En consecuencia, no puede declarar un array de una dimensión como bidimensional, o viceversa.
Por lo tanto, no puede tener en la misma base:

 ARRAY INTEGER(MiArray1;10)
 ARRAY INTEGER(MiArray1;10;10)

Sin embargo, puede escribir en la misma aplicación:

 ARRAY INTEGER(MiArray1;10)
 ARRAY INTEGER(MiArray2;10;10)

El número de dimensiones en un array no puede cambiarse en una base. Sin embargo, puede cambiar el tamaño de un array. Puede redimensionar un array de un array bidimensional y escribir:

 ARRAY BOOLEAN(MiArray;5)
 ARRAY BOOLEAN(MiArray;10)

Nota: un array bidimensional, es de hecho, un conjunto de varios arrays de una dimensión. Para mayor información, consulte la sección .

Durante la utilización de comandos como COPY ARRAY, LIST TO ARRAY, ARRAY TO LIST, SELECTION TO ARRAY, SELECTION RANGE TO ARRAY, ARRAY TO SELECTION, o DISTINCT VALUES, puede cambiar, voluntariamente o no, los tipos de elementos, el número de dimensiones, o en una array alfa, la longitud de la cadena. Usted se encontrará entonces en una de las tres situaciones anteriormente mencionadas.

El compilador genera un mensaje de error; la corrección necesaria es generalmente bastante obvia. Los ejemplos de declaración implícita de arrays están en la sección .

Si quiere compilar una base que utiliza arrays locales (arrays visibles únicamente por los métodos que los crearon), debe declararlos explícitamente en 4D antes de utilizarlos.
La declaración explícita de un array significa la utilización de un comando de tipo ARRAY REAL, ARRAY INTEGER, etc.
Por ejemplo, si un método genera un array local de enteros que contiene 10 elementos, usted debe tener la línea siguiente en su método:

 ARRAY INTEGER($MiArray;10)

Las variables creadas en un formulario (como botones, list boxes desplegables, y así sucesivamente) siempre son variables proceso o interproceso.
En una base interpretada, el tipo de estas variables no es importante. Sin embargo, en aplicaciones compiladas, podría tener importancia. No obstante, las reglas son bastante claras:
• Puede declarar variables de formulario utilizando directivas de compilación, o
• El compilador atribuye un tipo por defecto que puede definirse en las Preferencias de compilación (ver el Manual de Diseño).

Las siguientes variables de formulario son consideradas por defecto como Reales:

Casilla de selección
Casillas de selección 3D
Botón
Botón inverso
Botón invisible
Botón 3D
Botón imagen
Rejilla de botones
Botón de opción
Botón de opción 3D
Botón imagen de opción
Menú imagen
Menú desplegable jerárquico
Lista jerárquica
Regla
Dial
Termómetro
List box (tipo selección).

Nota: las variables de formulario Regla, Dial y Termómetro siempre son declaradas como Reales, incluso si elige Entero largo como el tipo de botón por defecto en las Preferencias.

Para estas variables, el único conflicto de tipo que puede surgir sería si el nombre de una variable fuera idéntico al de otra ubicada en otra parte de la base. En este caso, renombre la segunda variable.

Un área de plug-in siempre es un Entero largo. Nunca podrá haber un conflicto de tipo.
Para un área de plug-in, el único conflicto de tipo que podría surgir es que el nombre de una variable fuera idéntico al de otra ubicada en otra parte de la base. En este caso, renombre la segunda variable.

Las áreas 4D Write Pro son siempre variables de tipo de Objeto. No puede haber ningún conflicto de escritura, a menos que el mismo nombre de variable se utilice en otra parte de la aplicación.

Estas variables son de los siguientes tipos:
Variable no editable,
Variable editable,
Menú/Lista desplegable,
Área de desplazamiento,
Combo box,
Menú Pop-up,
Pestaña,
Área Web,
Columna de list bost (tipo array).

Estas variables están divididas en dos categorías:

  • variables simples (variables editables y no editables),
  • variables ubicadas en arrays (listas desplegables , menús/listas desplegables, áreas de desplazamiento, menús pop-up, combo boxes y pestañas)
  • variables simples
    Por defecto, estas variables son de tipo texto. Cuando se utilizan en métodos o en métodos de objeto, se les atribuye el tipo seleccionado por usted. No hay ningún riesgo de conflicto diferente del resultante de asignar el mismo nombre a otra variable.
  • Variables de visualización
    Algunas variables se utilizan para visualizar los arrays en los formularios. Si los valores por defecto han sido introducidos en el editor de formularios, usted debe declarar explícitamente las variables correspondientes utilizando los comandos de declaración de arrays ([#cmd id="223"/], ARRAY TEXT, etc.).

Cada list box añade varias variables en los formularios. El tipo por defecto de estas variables depende del tipo de list box:

List box tipo arrayList box tipo selección
List boxArray booleanoNúmero (no se utiliza)
Columna de list boxArray textoDigitación dinámica
EncabezadoNúmericoNúmerico
PieDigitación dinámicaDigitación dinámica
Array de control de líneasArray booleano (Array Entero largo aceptado)-
EstilosArray entero largoEntero largo
Colores de fuenteArray entero largoEntero largo
Colores de fondoArray entero largoEntero largo
Asegúrese de identificar y digitar estas variables y arrays correctamente con el fin de evitar conflictos durante la compilación.

Cuando utiliza punteros en su base, toma ventaja de una herramienta poderosa y versátil de 4D. El compilador conserva integralmente los beneficios de los punteros.
Un puntero puede apuntar a variables de tipos de datos diferentes. Asignar diferentes tipos a una variables no crea conflicto. Tenga cuidado de no cambiar el tipo de una variable a la cual un puntero hace referencia.
Este es un ejemplo de este problema:

 Variable:=5.3
 Puntero:=->Variable
 Puntero->:=6.4
 Puntero->:=False

En este caso, su puntero desreferenciado es una variable Real. Al asignarle a esta variable un valor Booleano, se crea un conflicto de tipos.

Si necesita utilizar punteros con diferentes propósitos en el mismo método, asegúrese de que sus punteros estén definidos:

 Variable:=5.3
 Puntero:=->Variable
 Puntero->:=6.4
 Bool:=True
 Puntero:=->Bool
 Puntero->:=False

Un puntero siempre está definido con relación al objeto al cual se refiere. Por esta razón el compilador no puede detectar conflictos de tipos generados por punteros. En caso de un conflicto, no recibirá un mensaje de error mientras esté en la fase de declaración o de compilación.
Esto no significa que el compilador no tenga manera de detectar conflictos relacionados con punteros. El compilador puede verificar su uso de punteros cuando marca la opción Control de ejecución en las Preferencias de compilación (ver Manual de Diseño).

Durante la compilación, el compilador analiza las definiciones de los comandos de los plug-ins utilizados en la base, es decir el número y tipo de parámetros de estos comandos. No hay peligro de confusión a nivel de declaración si sus llamadas son consistentes con la declaración del método.

Asegúrese de que sus plug-ins estén instalados en la carpeta PlugIns, en una de las ubicaciones autorizadas por 4D: junto al archivo de estructura o junto a la aplicación ejecutable (Windows) / en el paquete de software (Mac OS). Por razones de compatibilidad, aún es posible utilizar la carpeta Win4DX o Mac4DX junto al archivo de estructura. Para mayor información, consulte la Guía de instalación de 4D.

El compilador no duplica estos archivos, pero los analiza para determinar la declaración adecuada de sus rutinas.
Si sus plug-ins están ubicados en otra parte, el compilador le pedirá ubicarlos durante la declaración, vía una ventana de abrir archivos.

Ciertos plug-ins, por ejemplo 4D Write, utilizan comandos que llaman implícitamente a comandos 4D.

Tomemos el ejemplo de 4D Write. La sintaxis del comando WR ON EVENT es:
WR ON EVENT(area;evento;eventoMetodo)

El último parámetro es el nombre del método que usted ha creado en 4D. Este método será llamado por 4D Write cada vez que el evento sea recibido y automáticamente recibe los parámetro siguientes:

ParámetrosTipoDescripción
$0Entero largoRetorno de función
$1Entero largoÁrea 4D Write
$2Entero largoTecla Mayús.
$3Entero largoTecla Alt (Windows); Tecla Opción (Mac OS)
$4Entero largoTecla Ctrl (Windows), Tecla Comando (Mac OS)
$5Entero largoTipo de evento
$6 Entero largoValor que depende del parámetro evento

Para que el compilador tenga en cuenta estos parámetros, debe asegurarse de que hayan sido declarados, bien sea por la directiva de compilación, o por su uso en el método, suficientemente explícito para poder deducir claramente el tipo.

4D puede utilizarse para crear y trabajar con componentes. Un componente es un conjunto de objetos 4D representando una o varias funcionalidades agrupadas en un archivo de estructura (llamado base principal), que puede instalarse en diferentes bases (llamadas bases huésped).

Una base huésped ejecutada en modo interpretado puede utilizar indiferentemente componentes interpretados o compilados. Es posible instalar los componentes interpretados y compilados en la misma base huésped. Por el contrario, una base huésped ejecutada en modo compilado no puede utilizar componentes interpretados. En este caso, sólo pueden utilizarse componentes compilados.

Una base huésped interpretada que contiene componentes interpretados puede ser compilada y no llama a los métodos del componente interpretado. Si este no es el caso, aparece una caja de diálogo de alerta cuando la compilación no es posible.

Se puede producir un conflicto de nombre cuando un método de proyecto del componente tiene el mismo nombre que un método de proyecto de la base huésped. En este caso, cuando el código se ejecuta en el contexto de la base huésped, se llama al método de la base huésped. Este principio permite "ocultar" un método del componente con un método personalizado (por ejemplo para obtener una funcionalidad diferente). Cuando el código se ejecuta en el contexto del componente, se llama al método del componente. Este enmascaramiento es señalado como una advertencia durante la compilación de la base huésped.

Si dos componentes comparten métodos con el mismo nombre, se genera un error en el momento de la compilación de la base host.

Para mayor información sobre componentes, consulte el Manual de Diseño.

La manipulación de las variables locales sigue todas las reglas que ya han sido enunciadas. Como las otras variables, sus tipos de datos no pueden alterarse durante la ejecución del método. En esta sección, examinamos dos instancias que pueden conducir a conflictos de tipos:

  • Cuando necesita una redeclaración. El uso de punteros ayuda a evitar los conflictos de tipos.
  • Cuando necesita direccionar parámetros por indirección.

Una variable no puede ser redeclarada. Sin embargo, es posible utilizar un puntero para referirse a variables de diferentes tipos de datos.
Como ejemplo, considere una función que devuelve el tamaño en memoria de un array de una dimensión. El resultado es un Real, excepto en dos casos; para arrays de tipo texto y de tipo imagen, el tamaño en memoria depende de valores que no pueden expresarse numéricamente (ver la sección Arrays y memoria).

En el caso de arrays Texto y arrays Imagen, el resultado se devuelve como una cadena de caracteres. Esta función necesita un parámetro: un puntero al array cuyo tamaño de memoria queremos conocer.

Hay dos métodos para efectuar esta operación:

  • Trabajar con variables locales sin preocuparese por su tipo; en tal caso, el método corre sólo en modo interpretado.
  • Utilizar punteros y continuar en modo interpretado o compilado.
Función MemSize, en modo interpretado únicamente (Ejemplo para Macintosh)
 $Tamaño:=Size of array($1->)
 $Tipo:=Type($1->)
 Case of
    :($Tipo=Real array)
       $0:=8+($Size*10) ` $0 es un Real
    :($Tipo=Integer array)
       $0:=8+($Tamaño*2)
    :($Tipo=LongInt array)
       $0:=8+($Tamaño*4)
    :($Tipo=Date array)
       $0:=8+($Tamaño*6)
    :($Tipo=Text array)
       $0:=String(8+($Tamaño*4))+("+Suma de las longitudes de los textos") ` $0 es un Texto
    :($Tipo=Picture array)
       $0:=String(8+($Tamaño*4))+("+Suma de los tamaños de las imágenes") ` $0 es un Texto
    :($Tipo=Pointer array)
       $0:=8+($Tamaño*16)
    :($Tipo=Boolean array)
       $0:=8+($Tamaño/8)
 End case

En el método anterior, el tipo de $0 cambia de acuerdo al valor de $1; por lo tanto, no es compatible con el compilador.

  • La función MemSize en modo interpretado y compilado (Ejemplo para Macintosh)
    Acá el método está escrito utilizando punteros:
 $Tamaño:=Size of array($1->)
 $Tipo:=Type($1->)
 VarNum:=0
 Case of
    :($Tipo=Real array)
       VarNum:=8+($Tamaño*10) ` VarNum es un Real
    :($Tipo=Integer array)
       VarNum:=8+($Tamaño*2)
    :($Tipo=LongInt array)
       VarNum:=8+($Tamaño*4)
    :($Tipo=Date array)
       VarNum:=8+($Tamaño*6)
    :($Tipo=Text array)
       VarText:=String(8+($Tamaño*4))+("+Suma de longitudes de texto")
    :($Tipo=Picture array)
       VarText:=String(8+($Tamaño*4))+("+Suma de tamaños de imágenes")
    :($Tipo=Pointer array)
       VarNum:=8+($Tamaño*16)
    :($Tipo=Boolean array)
       VarNum:=8+($Tamaño/8)
 End case
 If(VarNum#0)
    $0:=->VarNum
 Else
    $0:=->VarText
 End if

Estas son las principales diferencias entre las dos funciones:
• En el primer caso, el resultado de la función es la variable que se esperaba,
• En el segundo caso, el resultado de la función es un puntero a esta variable. Usted simplemente desreferencia su resultado.

El compilador administra el poder y la versatilidad de indirección sobre los parámetros. En modo interpretado, 4D le da toda toda la libertad con los números y los tipos de parámetros. Usted mantiene esta libertad en modo compilado, siempre y cuando no introduzca conflictos de tipos y que no utilice más parámetros de los pasados en el método llamado.
Para evitar posibles conflictos, los parámetros direccionados por indirección deben ser del mismo tipo.
Esta indirección es mejor manejada si usted respeta la siguiente convención: si sólo algunos parámetros son direccionados por indirección, deben pasarse después de los otros.
En el método, una dirección por indirección tiene el formato: ${$i}, donde $i es una variable numérica. ${$i} es llamado parámetro genérico.

Como ejemplo, considere una función que añade valores y devuelve la suma con el formato que se pasa como un parámetro. Cada vez que se llama este método, el número de valores a añadir puede variar. Debemos pasar los valores como parámetros al método y el formato en forma de una cadena de caracteres. El número de valores puede variar de llamado en llamado.
Esta función se llama de la forma siguiente:

 Resultado:=MiSuma("##0.00";125,2;33,5;24)

En este caso, el método llamado, obtendrá la cadena “182.70”, la cual es la suma de los números, con el formato especificado. Los parámetros de funciones deben pasarse en el orden correcto: primero el formato y luego los valores.

Esta es la función MiSuma:

 $Sum:=0
 For($i;2;Count parameters)
    $Sum:=$Sum+${$i}
 End for
 $0:=String($Sum;$1)

Esta función puede llamarse de varias formas:

 Resultado:=MySum("##0.00";125,2;33,5;24)
 Resultado:=MySum("000";1;18;4;23;17)

Al igual que con las otras variables locales, no es necesario declarar parámetros genéricos por directivas de compilación. Si es necesario (en casos de ambigüedad o por optimización), se utiliza la siguiente sintaxis:

 C_LONGINT(${4})

Este comando significa que todos los parámetros a partir del cuarto (incluido) estarán direccionados por indirección y serán de tipo Entero largo. $1, $2 y $3 pueden ser de cualquier tipo. Sin embargo, si utiliza $2 por indirección, el tipo utilizado será de tipo genérico. Será de tipo Entero largo, incluso si para usted era, por ejemplo, de tipo Real.

Nota: el compilador utiliza este comando en la fase de declaración. El número en la declaración tiene que ser una constante y no una variable.

Algunas variables y constantes de 4D tiene un tipo y una identidad asignada por el compilador. Por lo tanto, no puede crear una nueva variable, método, función o comando de plug-in comando utilizando cualquiera de los nombres de esta variables o constantes. Puede probar sus valores y utilizarlos como lo hace en modo interpretado.

Esta es una lista completa de las Variables sistema de 4D con sus tipos.

VariableTipo
OKEntero largo
DocumentTexto
FldDelimitEntero largo
RecDelimitEntero largo
ErrorEntero largo
Error methodTexto
Error lineEntero largo
Error formulaTexto<br/>
MouseDownEntero largo
KeyCodeEntero largo
ModifiersEntero largo
MouseXEntero largo
MouseYEntero largo
MouseProcEntero largo

Cuando crea una columna calculada en un informe, 4D crea automáticamente una variable C1 para la primera, C2 para la segunda, C3... y así sucesivamente. Esto se hace de manera transparente.
Si utiliza estas variables en métodos, recuerde que al igual que las otras variables, C1, C2, ... Cn no pueden ser redeclaradas.

La lista de constantes predefinidas en 4D se encuentra utilizando el Lista de temas de constantes. Igualmente puede ver las constantes en Explorador, en modo Diseño.



Ver también 

Consejos de optimización
Detalles de sintaxis
Mensajes de error
Utilización de directivas de compilación
Variables sistema

 
PROPIEDADES 

Producto: 4D
Tema: Compilador

 
HISTORIA 

Modificado: 4D v15 R4

 
ARTICLE USAGE

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)