Guía de declaración

4D - Documentation   Français   English   German   Español   4D v11 SQL, Comandos por temas   4D v11 SQL, Lista alfabética de comandos   4D v11 SQL, Constantes por temas   Regresar   Anterior   Siguiente

versión 11 (Modificado)


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

Conflictos en variables simples


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.

Conflictos entre dos usos

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.

Conflicto entre el uso y una directiva de compilación

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_INTEGER(<>vEntero)   `Declaración de un Entero por una directiva de compilación
   <>vEntero:=3   `Comando compatible con la directiva de compilación
   Var:= <>vEntero+vBool   `Operación que contiene variables con tipos de datos incompatibles

Conflicto por declaración implícita

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

Conflicto entre dos directivas de compilación

Declarar dos veces 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.

Recuerde que un conflicto de tipos puede surgir relacionado con el uso de C_STRING si modifica la longitud máxima de la cadena. Si escribe:

   C_STRING(4;MiCadena)
   MiCadena:="Hola"
   C_STRING(6;MiCadena)
   MiCadena:="Flores"

el compilador identifica un conflicto porque la declaración de variables de tipo Alfa, debe ofrecer una ubicación de tamaño adecuado.

La solución es utilizar una directiva de compilación que de una longitud máxima, ya que por defecto, el compilador aceptará una longitud inferior. Puede escribir:

   C_STRING(6;Cadena)
   String:="Flores"
   String:="Hola"

Nota: Si ha escrito dos veces C_STRING(7;Cadena), es decir:

   C_STRING(6;Cadena)
   Cadena:="Flores"
   C_STRING(6;Cadena)
   Cadena:="Hola"

el compilador aceptará las directivas de todas formas; la segunda directiva es simplemente redundante.

Nota sobre variables locales

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.

Conflictos en arrays


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.

Cambio de tipos de los elementos de un Array

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.

Cambio del número de dimensiones de un array

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 Arrays bidimensionales.

Caso de arrays de cadenas fijas

Los arrays de cadenas fijas siguen las mismas reglas que los array alfa, por las mismas razones.

Si escribe:

   ARRAY STRING(5;MiArray;10)
   ARRAY STRING(10;MiArray;10)

el compilador detecta un conflicto de longitud. La solución es simple: declare la longitud máxima de la cadena. El compilador maneja automáticamente cadenas de longitudes inferiores.

Declaración implícita

Durante la utilización de comandos como COPY ARRAY, LIST TO ARRAY, ARRAYTO LIST, SELECTION TO ARRAY, SELECTION RANGE TO ARRAY, ARRAYTO 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 Detalles de sintaxis.

Arrays locales

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)

Declaración de variables creadas en formularios


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).

Variables consideradas por defecto como de tipo Real

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.

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.

Variable gráfica

Un área gráfica es automáticamente el tipo gráfico (Entero largo). Esta variables nunca crean un conflicto de tipo. Para una variable gráfica, el único conflicto de tipo posible que puede surgir sería 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.

Variable de área de plug-in

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.

Variables consideradas por defecto como de Texto

Estas variables son de los siguientes tipos:

Variable no editable,

Variable editable,

Lista desplegable,

Menú/Lista desplegable,

Área de desplazamiento,

Combo box,

Menú Pop-up,

Pestaña.

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 ubicadas en arrays

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 (ARRAY STRING, ARRAY TEXT...).

Punteros


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).

Comandos de plug-ins


Generalidades

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.

Comandos de plug-in que reciben parámetros implícitos

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.

Componentes 4D


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.

Manipulación de variables locales $0…$N y paso de parámetros


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.

Utilización de punteros para evitar redeclaraciones.

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.

Indirecciones sobre los parámetros

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_INTEGER(${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. $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, incluso si para usted era 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.

Variables reservadas y constantes


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.

Variables sistema

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

VariableTipo
OKEntero largo
DocumentAlfa (255)
FldDelimitEntero largo
RecDelimitEntero largo
ErrorEntero largo
MouseDownEntero largo
KeyCodeEntero largo
ModifiersEntero largo
MouseXEntero largo
MouseYEntero largo
MouseProcEntero largo

Variables de informes rápidos

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.

Constantes predefinidas 4D

La lista de constantes predefinidas en 4D puede consultarse en este manual, igualmente puede visualizar 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.


4D - Documentation   Français   English   German   Español   4D v11 SQL, Comandos por temas   4D v11 SQL, Lista alfabética de comandos   4D v11 SQL, Constantes por temas   Regresar   Anterior   Siguiente