A = A – 1
Loop
Un bucle o ciclo en programación es una sentencia que se realiza repetidas veces.
Un bucle se utiliza para hacer una acción repetida sin tener que repetir varias veces el mismo código, lo que ahorra tiempo, deja el código más claro y facilita su modificación en el futuro.
El bucle y los condicionales representan la base de la programación estructurada. Es una evolución del código ensamblador, donde la única posibilidad de iterar un código era establecer una sentencia jump (que en los lenguajes de programación fue sustituida por el "ir a" o GOTO).
Los tres bucles más utilizados en programación son el mientras, el para y el bucle repetir.
Ejemplo en código C de sentencias repetidas:
int var=0;
//código que puede ser sustituido por un bucle
var = var + 2; //var igual a 2 (puede ser sustituído por var+=2)
var = var + 2; //var igual a 4
var = var + 2; //var igual a 6
var = var + 2; //var igual a 8
var = var + 2; //var igual a 10
// fin de código que puede ser sustituido por un bucle
printf("el resultado es %i", var );
Ejemplo con un bucle:
int var=0;
//Código para el bucle
int i;
// este es el Bucle for
for(i=0;i<10;i+=2)
{
var += 2;
}
printf("el resultado es %i", var);
Algunos lenguajes de programación tienen sentencias que permiten "escapar" de los bucles sin llegar a la condición de fin, como el romper o el devolver.
Ejemplo escapando de un bucle en Visual Basic 1:
Dim h&, var&
var = 0
'Codigo del Bucle
do
var = var + 2
if var = 10 then 'Codigo para salir del bucle
goto escape
end if
loop
escape:
print "El resultado es " & var
Ejemplo escapando de un bucle en Visual Basic 2:
Dim h&, var&
var = 0
'Codigo del Bucle
do
var = var + 2
if var = 10 then 'Codigo para salir del bucle
exit do
end if
loop
print "El resultado es " & var
- Bucle
El bucle for o ciclo for es una estructura de control en la que se puede indicar el número máximo de iteraciones. Está disponible en casi todos los lenguajes de programación imperativos.
- Elementos del bucle
- Variable de control: prácticamente un mandato impuesto por el uso habitual es utilizar la letra i como variable de control, o bien sus sucesoras en caso de bucles anidados. El uso de esta letra críptica quizás a primera vista es sin embargo una excelente forma de aportar agilidad de lectura al código por su uso tan extensivo. Como raras veces los bucles anidados superan las tres dimensiones (por una sencilla cuestión de explosión exponencial), las letras i, j y k suelen ser las únicas relacionadas con este uso. En C se define en el primer parámetro de la instrucción junto con la inicialización (opcional).
- Bucle for
- Inicialización de la variable de control: en pseudolenguaje se pide explicitarlo (es la sección := ValorInicial), sin embargo, otros lenguajes más permisivos como C no lo requieren de forma obligatoria. De todos modos, la práctica de utilizar variables de control que no se inicializan en el bucle no es recomendada para la legibilidad del código. En C se define en el primer parámetro del bucle junto con la variable de control.
- Condición de control: en pseudolenguaje se ve representado por el valor final que puede tomar la variable de control (la sección A ValorFinal). En C es el segundo parámetro y puede ser cualquier condición (ni siquiera es obligación que esté la variable de control, aunque una vez más, esto no se considera una buena práctica).
- Incremento: en pseudolenguaje se toma por defecto el valor 1, aunque puede explicitarse por medio de la sentencia PASO = ValorPaso cualquier número entero (léase bien entero, o sea que técnicamente podemos decrementar). En C es el último parámetro.
- Cuerpo: es lo que se hará en cada iteración, pueden ser una o más instrucciones. En pseudolenguaje pesa la restricción de no poder alterar el valor de la variable de control; esto no es requerido en C, pero no se considera una buena práctica.
- Usos
- Su uso principal se orienta a los arreglos, pudiendo modificar, agregar, eliminar o consultar datos que se encuentren según el índice. Por esto último, una condición mínima del arreglo es que debe ser ordenado, por que si se intenta leer un dato inexistente, esto genera un error de programación.
- Teorema de Dijkstra
Un famoso teorema, demostrado por Edsger Dijkstra en los años sesenta, demuestra que todo programa puede escribirse utilizando únicamente las tres instrucciones de control siguientes:
- El bloque secuencial de instrucciones, instrucciones ejecutadas sucesivamente.
- La instrucción condicional alternativa, de la forma "IF condición THEN instrucción-1 ELSE instrucción-2".
- Si la condición se cumple, se ejecutará "instrucción-1".
- En caso contrario, se ejecuta "instrucción-2".
- Abreviadamente, esta instrucción se suele llamar IF-THEN-ELSE.
- El bucle condicional "WHILE condición DO instrucción", que ejecuta la instrucción repetidamente mientras la condición se cumpla.
- En su lugar, se puede utilizar también la forma "UNTIL condición DO instrucción", que ejecuta la instrucción hasta que la condición se cumpla. Los dos bucles se diferencian entre sí porque en la forma WHILE la condición se comprueba al principio, por lo que es posible que la instrucción no se ejecute ni una sola vez.
- En cambio, en la forma UNTIL la condición se comprueba al final del bucle, por lo que la instrucción se ejecuta siempre al menos una vez.
Los programas que utilizan sólo estas tres instrucciones de control básicas o sus variantes (como los bucles FOR o la instrucción condicional CASE), pero no la instrucción GOTO, se llaman estructurados.
La "programación estructurada" (llamada también "programación sin GOTO") se convirtió durante los años setenta en la forma de programar más extendida.
A pesar de todo, la mayoría de los lenguajes conservan la instrucción GOTO y las etiquetas de las instrucciones, para utilizarla en casos muy especiales, aunque normalmente se desaconseja su uso. Entre los lenguajes de alto nivel, Pascal, C y Ada pueden considerarse especializados en programación estructurada, y aunque todos ellos permiten utilizar la instrucción GOTO, se desaconseja su uso. En otros lenguajes, tal como Léxico, se ha suprimido esa instrucción por considerársele una fuente de errores cuando se carece de experiencia en la lógica de programación.
6.- Subprogramas, paso de parámetros, implementación y abstracción de datos
Subprogramas
Definición, declaración y uso
Un subprograma es un procedimiento (procedure) o una función (function). La diferencia entre un procedimiento y una función es que el primero sólo indica la ejecución de una secuencia de instrucciones, en función de unos parámetros, mientras que la segunda representa un valor que se genera como resultado de su ejecución. Se pueden usar funciones para sobrecargar los operadores del lenguaje, otorgándoles nuevos significados.
Definición de un subprograma.
La definición de un subprograma consta de tres elementos: (1) cabecera, donde se fija su clase y nombre, se describen sus parámetros formales y, si es una función, se especifica el tipo de su resultado, terminando todo ello con la palabra "is", expresando que a continuación se desarrolla el subprograma, (2) declaraciones locales, de cualquier elemento declarable (tipos, variables, constantes, …), incluyendo la definición anidada de otros subprogramas y (3) el bloque de sentencias ejecutables del subprograma delimitado por las palabras reservadas "begin" y "end" (esta última suele ir acompañada del nombre del subprograma). Si el subprograma es una función, entre las sentencias ejecutables debe incluirse al menos una sentencia de retorno ("return") con una expresión que indique el valor a devolver a quien la llamó; si la ejecución de una función alcanza el final sin encontrar una sentencia de retorno, se produce una excepción "Program_Error", dado que la sentencia de retorno se utiliza en las funciones para especificar el valor a devolver. En los procedimientos puede omitirse la sentencia de retorno cuando el único punto de retorno se encuentra al final, como en el siguiente ejemplo.
procedure Intercambia(A,B: in out Integer) is C: integer; begin C := A; A := B; B := C; end Intercambia; function Media(A,B: Float) return Float is begin return (A + B) / 2.0; end Media;
Las declaraciones locales están sujetas a las reglas de ámbito generales de Ada.
Un subprograma puede constituir por sí mismo una unidad de librería o estar anidado dentro de una unidad mayor. Si un subprograma está anidado en una unidad mayor, la definición del subprograma debe escribirse en una sección de declaraciones de esa unidad.
procedure Principal is … procedure Intercambia(A,B: in out Integer) is … begin … end Intercambia; … begin … end Principal;
En un mismo ámbito se pueden tener varios subprogramas con el mismo nombre, siempre que se diferencien en los parámetros o en el tipo del resultado (si son funciones). Esto se conoce como sobrecarga de subprogramas. La sobrecarga de operadores es una clase de sobrecarga de subprogramas.
… procedure Intercambia(A,B: in out Integer) is … begin … end Intercambia; … procedure Intercambia(A,B: in out Float) is … begin … end Intercambia; …
Declaración de un subprograma.
En determinadas circunstancias (p.e. cuando un subprograma se proporciona para ser usado desde un paquete, cuando se define un subprograma genérico o cuando hay referencias mutuas entre subprogramas) se precisa escribir una declaración de un subprograma separada de su definición. La declaración de un subprograma es como su cabecera, pero terminada en ";" en vez de con la palabra "is", para expresar que lo que se está dando es una vista de un subprograma cuya definición se haya en otro lugar.
procedure Intercambia(A,B: in out Integer); function Media(A,B: Float) return Float;
Definición separada (separate).La definición de un subprograma que está anidado en otra unidad puede extraerse de la misma para compilarse por separado, dejándolo indicado en la unidad matriz mediante una declaración con cláusula "separate". A efectos de reglas de ámbito es como si la definición del subprograma estuviera donde está dicha declaración. El subprograma separado debe indicar quién es su unidad matriz.
procedure Ejemplo_Matriz is … — Indicación de que Intercambia se desarrollará aparte procedure Intercambia(A,B: in out Integer) is separate; … begin … end Ejemplo_Matriz;
— Lo siguiente posiblemente irá en un fichero diferente separate(Ejemplo_Matriz) procedure Intercambia(A,B: in out Integer) is … begin … end Intercambia; …
Llamada a un subprograma.
La llamada a un procedimiento constituye una sentencia, mientras que la llamada a una función sólo puede hacerse como parte de una expresión:
Intercambia(X,Y); Z := Media(L,M); if Media(L,M) > 5.0 then … return Media(L,M);
Parámetros.
Listas de parámetros formales.
El número, tipo y clase de los parámetros formales se declara en una lista de parámetros formales que se pone justo después del nombre del subprograma en la especificación del mismo. La lista de parámetros formales se delimita por paréntesis y se compone de una o varias sublistas de parámetros de la misma clase y tipo separadas por punto y coma (";"). Cada sublista est
Las palabras parámetro y argumento, aunque de significado similar, tiene distintas connotaciones semánticas: Se denominan parámetros los tipos declarados en el prototipo (que deben corresponder con los declarados en la definición). Cuando se realiza una llamada a la función, los "valores" pasados se denominan argumentos. A veces se utilizan también las expresiones argumentos formales, para los parámetros y argumentos actuales para los valores pasados.
Parámetros (en prototipo o definición) argumentos formales
Valores pasados (en tiempo de ejecución) argumentos actuales
La sintaxis utilizada para la declaración de la lista de parámetros formales es similar a la utilizada en la declaración de cualquier identificador. A continuación se exponen varios ejemplos:
int func(void) {…} // sin parámetros inf func() {…} // ídem. int func(T1 t1, T2 t2, T3 t3=1) {…} // tres parámetros simples, // uno con argumento por defecto int func(T1* ptr1, T2& tref) {…} // los argumentos son un puntero y // una referencia. int func(register int i) {…} // Petición de uso de registro para // argumento (entero) int func(char* str,…) {…} /* Una cadena y cierto número de otros argumentos, o un número fijo de argumentos de tipos variables */
Los argumentos son siempre objetos. Sus tipos pueden ser: escalares; estructuras; uniones, o enumeraciones; clases definidas por el usuario; punteros o referencias a estructuras y uniones, o punteros a funciones, a clases o a matrices. El tipo void está permitido como único parámetro formal. Significa que la función no recibe ningún argumento.
Nota: recuerde que cuando coloquialmente se dice que se pasa una matriz como argumento de una función, en realidad se está pasando un puntero a su primer elemento. Recuerde también que las funciones no pueden ser utilizadas como argumentos, pero sí pueden serlo los punteros-a-función, lo que a la postre, viene a ser equivalente.
Es un error realizar una declaración en la lista de parámetros
int func (int x, class C{…} c) { … } // Error!!
Todos los parámetros de una función tienen ámbito del bloque de la propia función y la misma duración automática que la función.
El único especificador de almacenamiento que se permite es register. En la declaración de parámetros también pueden utilizarse los modificadores volatile y const. Este último se utiliza cuando se pasan argumentos por referencia y queremos garantizar que la función no modificará el valor recibido. Ejemplo:
int dimension(X x1, const X& x2) // x2 NO se puede modificar!!
- Sinopsis
C++ permite tener valores por defecto para los parámetros. Esto supone que, si no se pasa el parámetro correspondiente, se asume un valor predefinido. La forma de indicarlo es declararlo en el prototipo de la función, como se muestra en el ejemplo (ambas expresiones son equivalentes).
float mod (float x, float y = 0); float mod (float, float = 0);
Más tarde no es necesario, ni posible, indicarlo de nuevo en la definición. Por ejemplo:
float mod (float, float = 0); // prototipo … float mod (float x, float y = 0) { return x + y; } // Error!! float mod (float x, float y) { return x + y; } // definición Ok
Si declaración y definición están en una sola sentencia entonces si es necesario indicar los valores por defecto. Ejemplo, en la sentencia:
float mod (float x, float y = 0) { return pow(x*x + y*y, 0.5); }
La ausencia de un segundo argumento en la invocación hace que se adopte para él un valor 0 (podría haber sido cualquier otro valor). En este contexto, la función mod aceptaría estas dos llamadas como correctas y de resultados equivalentes:
m1 = mod (2.0 , 0); m2 = mod (2.0);
Un argumento por defecto no puede ser repetido o cambiado en una siguiente declaración dentro del mismo ámbito. Por ejemplo:
void func (int x = 5); … void func (int x = 5); // Error: repetición de argumento por defecto { // nuevo ámbito void func (x = 7); // L.4 Correcto: esta función oculta a la anterior } // el ámbito anterior vuelve a ser visible void func (x = 7); // Error: cambiar argumento por defecto
Nota: a pesar de que la expresión de la línea 4 es correcta, tenga en cuenta que las declaraciones en ámbitos anidados que ocultan declaraciones del mismo nombre en ámbitos externos, suele ser fuente de errores y confusiones.
Es muy de tener en cuenta esta regla en la definición de clases, ya que en ellas es frecuente que la declaración de métodos se realice en un punto (el cuerpo de la clase), y la definición se realice "off-
line" (fuera del cuerpo de la clase). En caso que el método tenga argumentos por defecto recuerde no repetirlos más tarde en la definición.
La gramática de C++ exige que los parámetros con valores por defecto deben ser los últimos en la lista de parámetros, y que si en una ocasión falta algún argumento, los que le siguen también deben faltar (adoptar también los valores por defecto).
Nota: como puede verse, C++ no admite la posibilidad de otros lenguajes de saltarse parámetros por defecto incluyendo una coma sin ningún valor en la posición correspondiente, por ejemplo:
int somefunc (int, int = 1, char, long); // Incorrecto!! …. x = somefunc ( 33, , 'c', 3.14); // Error! No aceptable en C++ x = somefunc (int, char*, char* = 0);
Observe que en este último caso, el espacio de separación entre char* y = es importante, ya que *= es un operador de asignación. Así pues:
x = somefunc (int, char*, char*= 0); // Error!
Los argumentos por defecto de métodos (funciones-miembro de clases) no pueden ser otros miembros a no ser que sean estáticos. Ejemplo:
class C {
int v1;
void foo(char, int = v1); // Error!!
};
class B {
static int v1;
void foo(char, int = v1); // Ok.
}
Un posible diseño de la clase C podría ser:
class C {
int v1;
void foo(char, int = -1); // Ok
};
más tarde, en la definición del método hacer:
void C::foo(char a, int x) {
if (x == -1) x = v1;
…
}
Los argumentos por defecto no pueden ser otros argumentos:
x = somefunc (int x, int y = x); // Error!
Los argumentos pasados por referencia solo pueden adoptar valores por defecto estáticos, globales o de un subespacio cualificado. Ejemplo:
namespace ALPHA { long n = 20.10L; } long n = 10.10L; void f1 (long& lg = ALPHA::n); // Ok.
void f2 (long& lg = n); // Ok. void f3 (long lg = 10.2L); // Ok. void f4 (long& lg = 10.2L ); // Error!!
- Argumentos por defecto
Existen dos formas de pasar argumentos a las funciones: por valor y por referencia. El primero es utilizado por defecto con la declaración usual de parámetros. En el paso "por valor", se crean copias de los argumentos pasados a la función, los cuales, junto a las variables locales (incluyendo el posible valor devuelto), y la dirección de vuelta a la rutina que efectúa la invocación, son pasados a la pila en la secuencia de llamada. Más tarde, cuando termina su ejecución definitivamente, es decir, cuando el control vuelve a la función que la invocó, toda esta información es sacada de la pila mediante la secuencia de retorno (y se pierde). Estos procesos suponen un consumo de tiempo y espacio (memoria), a veces considerable.
- Argumentos: por valor y por referencia
Hemos visto que el paso de parámetros por valor significa que existen copias de los argumentos formales (estas copias son variables locales de la función llamada), y que una función no puede alterar ninguna variable de la función que la invocó.
La única excepción es el caso de las matrices. Cuando se utiliza una matriz como argumento en la llamada a una función, el valor pasado es un puntero a la dirección de memoria del principio de la matriz.
Cuando los argumentos pasan por valor pero no hay concordancia entre el tipo de los argumentos actuales y los argumentos formales utilizados en la declaración de la función, entonces se produce un modelado de tipo antes de la asignación. Supongamos el ejemplo:
void func(int x) { // definición de func. Acepta un entero
x = x * 2;
}
float f = 3.14;
func(f); // f es promovido a int antes de asignación a 'x'
// x == 6
Lo que sucede en estos casos es que la copia local f en func(x) es modificada para hacerla coincidir con el tipo esperado por la función, mientras que el valor original (f) permanece inalterado.
- Paso por valor
En C clásico, cuando se desea que la función llamada pueda alterar el valor de variables de la función que la invoca, o ahorrar el espacio que supone la copia local de los argumentos (que pueden ser estructuras de datos muy grandes), la solución consistía en utilizar punteros a las variables respectivas como argumentos para la función (en vez de pasar las variables en sí mismas). A su vez, la función llamada debía declarar el parámetro como puntero, y acceder a la variable indirectamente a través de él. En otras palabras: cuando en C se desea que un valor X pase a una función F y que esta pueda alterar el valor de X en la función que la invocó, el argumento utilizado es &X (la dirección de X). De esta forma, aunque F recibe una copia de &X, puede alterar el valor original a través de esta dirección. Esta técnica puede tener sus ventajas. Por ejemplo, si X es una estructura muy grande, pero puede tener efectos colaterales peligrosísimos y ser una fuente de errores difíciles de detectar.
- Pasar un puntero
Por supuesto, C++ permite utilizar la técnica del C clásico descrita arriba, pero también utilizar el paso de argumentos por referencia (en realidad es una variante semántica del proceso anteriormente descrito). Para ello se utiliza el declarador de referencia &.
Las referencias presentan las ventajas de los punteros, en el sentido que permiten modificar los valores de los objetos pasados como argumento, y de que permiten ahorrar espacio si hay que pasar objetos muy grandes, pero no presentan los peligros potenciales de aquellos. En caso necesario las referencias pueden declararse constantes, indicando así que la función invocada no modificará estos valores. En estos casos, la utilización de referencias obedece casi exclusivamente a razones de eficacia en el mecanismo de llamada.
Nota: en ocasiones el paso por referencia tiene una justificación de tipo físico. Es el caso en que los objetos utilizados como argumento representan dispositivos físicos. Por ejemplo, ficheros externos o dispositivos de comunicación. En estas circunstancias, el objeto no puede ser copiado alegremente por el mecanismo de invocación de funciones (que utilizaría el constructor-copia de la clase) si se utilizaran pasos por valor, y es necesario recurrir al paso por referencia.
Otro uso muy común de las referencias es cuando la función debería devolver distintos valores. Por ejemplo, supongamos que nos interesa que una función foo, devuelva cuatro valores: dos int posX y posY; una cadena de caracteres char* nombre, y un float altura. Como una función no puede devolver más de un valor (al menos, no de forma directa), recurrimos a construir una estructura con los valores adecuados. Esta estructura será pasada a la función por referencia, de forma que sus miembros podrán ser modificados desde el cuerpo de la función. Una vez realizada la invocación, puede considerarse que la mencionada estructura contiene los valores "devueltos" [], aunque en realidad la función no devuelva nada (en el ejemplo que sigue devuelve void).
El esquema de funcionamiento sería el siguiente:
struct ST { int posX; int posY; char* nombre; float altura; };
void foo (ST& st) { … st.posX = value1; st.posY = value2; st.nombre = value3; st.altura = value4; } int main () { // ========= … ST st; foo(st);
cout << "Las coordenadas son: x = " << st.posX << "; y = " << st.posY << endl;
cout << "es el punto << st.nombre << " de altitud << st.altura << " metros" << endl; … }
- Paso por referencia
A continuación se muestran tres implementaciones de una misma función; cada una con una forma distinta para paso del argumento.
Implementación-1: Sistema clásico, paso "por valor"
int pru1(int n) { // n entero; pasa "por valor"
return 3 * n;
}
…
int x, i = 4;
x = pru1(i); // ahora: x = 12, i = 4
int& ry = i;
x = pru (ry); // ahora: x = 12, i = 4
Observe que la última sentencia no es un paso por referencia, sino por valor (a pesar de que el argumento actual sea una referencia).
Implementación-2: Sistema clásico, paso de "punteros por valor" (seudo-referencia)
void pru2(int* np) { // np puntero-a-entero; pasa "por valor" *np = (*np) * 3;
} . . . int x = 4; pru2(&x); // ahora x = 12
Observe que en este caso, pasar el valor &x (dirección de x) como argumento, es equivalente a pasar un puntero a dicha variable (que es lo exigido en la definición de pru2). Es decir, la última línea se puede sustituir por las siguientes:
int* ptr = &x // define puntero-a-x pru2(ptr); // pasa el puntero como argumento
Implementación-3: Sistema C++, paso "por referencia"
void pru3(int& n) { // n tipo "referencia-a-int"; pasa "por referencia" n = 3 * n; } . . . int x = 4; pru3(x); // ahora x = 12
Atención a la sintaxis: aquí la invocación a pru3 tiene la forma: pru3(x), no pru3(&x) como en el caso anterior. Es decir, la notificación de que el argumento pasa por referencia hay que hacerla en la definición de la función, y no es necesario indicarlo en el momento de la invocación.
En este último caso, la declaración int& n como parámetro de la función pru3, establece que este n sea declarado como "referencia-a-entero", de forma que cuando se pasa el argumento x, la función crea un valor n que es una especie de alias o espejo de x, de forma que la expresión n = 3*n tiene el mismo efecto que x = 3*x.
Ya hemos visto que cuando, en la declaración de una referencia, el iniciador es una constante, o un objeto de tipo diferente que el referenciado, se crea un objeto temporal para el que la referencia actúa como un alias. Esta creación de objetos temporales es lo que permite la conversión de tipos referencia-a-tipoX cuando se utilizan como parámetros de funciones y no hay concordancia entre el valor recibido y el esperado (suponiendo que exista posibilidad de conversión). Este sería el mecanismo utilizado en el siguiente caso:
void pru(int& n) { // n tipo "referencia-a-int" (pasa "por referencia") n = 3 * n; } . . . float f = 4.1; pru(f); // ahora f = 12
- Comparativa
- Ejemplo
- Parámetros y argumentos
En el programa que sigue se muestra un caso de paso por referencia y acceso a subespacios.
#include <iostream.h>
namespace ALPHA { class CAlpha { int x; public: int getx(void) { return x; } void putx(int i) { x = i; } }; CAlpha CA1; // instancia de CAlpha (en ALPHA) } int func (ALPHA::CAlpha& ca, int i); /* prototipo: ca es la referencia a un objeto de la clase CAlpha en ALPHA */
int main (void) { // ======================== int x = 0; cout << "x = " << x << endl; ALPHA::CA1.putx(10); // invocación al método putx de CA1 x = func(ALPHA::CA1, 3); cout << "x = " << x << endl; }
int func (ALPHA::CAlpha& ca, int i) { // definición return (i + ca.getx()); }
Salida:
x = 0 x = 13
Conceptos de implementación
Esta sección trata sobre las consideraciones principales a la hora de implementar las aplicaciones de C++.
Los proyectos de Visual C++ utilizan normalmente la instalación de Windows Installer tradicional para la implementación. Para preparar una implementación con Windows Installer, se ha de empaquetar la aplicación en un archivo setup.exe y distribuir este archivo junto con un paquete del instalador (.msi). A continuación, los usuarios ejecutarán setup.exe para instalar la aplicación.
La aplicación se empaqueta agregando un proyecto de instalación a la solución; una vez generado, crea los archivos del paquete del instalador y de configuración que se distribuyen a los usuarios. Para obtener más información.
- Implementación de Windows Installer en C++
Cuando una aplicación de C/C++ se genera utilizando una funcionalidad proporcionada por las bibliotecas de Visual C++, se hace dependiente en presencia de dichas bibliotecas en tiempo de ejecución. Para que la aplicación se ejecute, se debe vincular, estática o dinámicamente, a las bibliotecas de Visual C++ necesarias. Si una aplicación se vincula dinámicamente a una biblioteca de Visual C++, cuando se ejecute, esa biblioteca debe estar presente para que se pueda cargar. Por otro lado, si la aplicación se vincula estáticamente a una biblioteca de Visual C++, no es necesario que el archivo DLL correspondiente esté presente en el equipo del usuario. Sin embargo, la vinculación estática tiene algunos efectos negativos, como el aumento del tamaño de los archivos de la aplicación y la posibilidad de que el mantenimiento sea más difícil.
Las bibliotecas de Visual C++ se empaquetan como archivos DLL y todas las bibliotecas necesarias para las aplicaciones de C/C++ las instala Visual Studio en el equipo del desarrollador. Sin embargo, al implementar la aplicación para sus usuarios, no es factible en muchos casos pedirles que instalen Visual Studio para ejecutar la aplicación. Es importante redistribuir solamente las partes de Visual C++ que necesita la aplicación para ejecutarse correctamente.
Abstracción
Abstracción consiste en aislar un elemento de su contexto o del resto de los elementos que lo acompañan. En programación, el término se refiere al énfasis en el "¿qué hace?" más que en el "¿cómo lo hace?" (Característica de caja negra). El común denominador en la evolución de los lenguajes de programación, desde los clásicos o imperativos hasta los orientados a objetos, ha sido el nivel de abstracción del que cada uno de ellos hace uso.
Los lenguajes de programación son las herramientas mediante las cuales los diseñadores de lenguajes pueden implementar los modelos abstractos. La abstracción ofrecida por los lenguajes de programación se puede dividir en dos categorías: abstracción de datos (pertenecientes a los datos) y abstracción de control (perteneciente a las estructuras de control).
Los diferentes paradigmas de programación han aumentado su nivel de abstracción, comenzando desde los lenguajes máquina, lo más próximo al ordenador y más lejano a la comprensión humana; pasando por los lenguajes de comandos, los imperativos, la orientación a objetos (OO), la Programación Orientada a Aspectos (POA); u otros paradigmas como la Programación Declarativa, etc…
La abstracción encarada desde el punto de vista de la programación orientada a objetos expresa las características esenciales de un objeto, las cuales distinguen al objeto de los demás. Además de distinguir entre los objetos provee límites conceptuales. Entonces se puede decir que la encapsulación separa las características esenciales de las no esenciales dentro de un objeto. Si un objeto tiene más características de las necesarias los mismos resultarán difíciles de usar, modificar, construir y comprender.
La misma genera una ilusión de simplicidad dado a que minimiza la cantidad de características que definen a un objeto.
Durante años, los programadores se han dedicado a construir aplicaciones muy parecidas que resolvían una y otra vez los mismos problemas. Para conseguir que los esfuerzos de los programadores puedan ser utilizados por otras personas se creó la POO. Que es una serie de normas de realizar las cosas de manera que otras personas puedan utilizarlas y adelantar su trabajo, de manera que consigamos que el código se pueda reutilizar.
La POO no es difícil, pero es una manera especial de pensar, a veces subjetiva de quien la programa, de manera que la forma de hacer las cosas puede ser diferente según el programador. Aunque podamos hacer los programas de formas distintas, no todas ellas son correctas, lo difícil no es programar orientado a objetos sino programar bien. Programar bien es importante porque así nos podemos aprovechar de todas las ventajas de la POO
Pensar en términos de objetos es muy parecido a cómo lo haríamos en la vida real. Por ejemplo vamos a pensar en un coche para tratar de modelizarlo en un esquema de POO. Diríamos que el coche es el elemento principal que tiene una serie de características, como podrían ser el color, el modelo o la marca. Además tiene una serie de funcionalidades asociadas, como pueden ser ponerse en marcha, parar o aparcar.
Pues en un esquema POO el coche sería el objeto, las propiedades serían las características como el color o el modelo y los métodos serían las funcionalidades asociadas como ponerse en marcha o parar.
Por poner otro ejemplo vamos a ver cómo modelizaríamos en un esquema POO una fracción, es decir, esa estructura matemática que tiene un numerador y un denominador que divide al numerador, por ejemplo 3/2.
La fracción será el objeto y tendrá dos propiedades, el numerador y el denominador. Luego podría tener varios métodos como simplificarse, sumarse con otra fracción o número, restarse con otra fracción, etc.
Estos objetos se podrán utilizar en los programas, por ejemplo en un programa de matemáticas harás uso de objetos fracción y en un programa que gestione un taller de coches utilizarás objetos coche. Los programas Orientados a objetos utilizan muchos objetos para realizar las acciones que se desean realizar y ellos mismos también son objetos. Es decir, el taller de coches será un objeto que utilizará objetos coche, herramienta, mecánico, recambios, etc.
7. Manejo de excepciones y concurrencia
El Manejo de excepciones es una estructura de control de los lenguajes de programación diseñada para manejar condiciones anormales que pueden ser tratadas por el mismo programa que se desarrolla.
Por ejemplo, un programa puede admitir cierto número de errores en el formato de los datos y continuar su proceso para producir el mejor resultado posible en lugar de producir una salida aparatosa llena de mensajes de error probablemente incomprensibles para el usuario. Muchas veces la acción asociada a una excepción es simplemente producir un mensaje informativo y terminar, otras veces, es sólo indicación de la necesidad de un cambio en la estrategia de resolución del problema.
Algunos lenguajes de programación, por ejemplo Lisp, Ada, C++, C#, Delphi, Objective C, Java, PHP , Python ,Eiffel y Ocaml incluyen soporte para el manejo de excepciones. En esos lenguajes, al producirse una excepción se desciende en la pila de ejecución hasta encontrar un manejador para la excepción, el cual toma el control en ese momento.
Ejemplo de manejo de excepción en Java:
import java.io.IOException;
// …
public static void main(String[] args) {
try {
// Se ejecuta algo que puede producir una excepción
} catch (IOException e) {
// manejo de una excepción de entrada/salida
} catch (Exception e) {
// manejo de una excepción cualquiera
} finally {
// código a ejecutar haya o no excepción
}
}
Ejemplo de manejo de excepción en Delphi:
procedure TForm1.Button1Click(Sender : TObject);
begin
try
try
a := b / c;
finally
// Este código siempre se ejecuta, independientemente de si ocurre o no una excepción.
end;
except
on e:EZeroDivide do
// Manejo de la excepción División por cero.
on e:Exception do
// Manejo de una excepción "genérica".
end;
end;
Concurrencia:
(concurrency). En computación, la concurrencia es la propiedad de los sistemas que permiten que múltiples procesos sean ejecutados al mismo tiempo, y que potencialmente puedan interactuar entre sí.
Los procesos concurrentes pueden ser ejecutados realmente de forma simultánea, sólo cuando cada uno es ejecutado en diferentes procesadores. En cambio, la concurrencia es simulada si sólo existe un procesador encargado de ejecutar los procesos concurrentes, simulando la concurrencia, ocupándose de forma alternada en uno y otro proceso a pequeñísimos intervalos de tiempo. De esta manera simula que se están ejecutando a la vez.
Debido a que los procesos concurrentes en un sistema pueden interactuar entre otros también en ejecución, el número de caminos de ejecución puede ser extremadamente grande, resultando en un comportamiento sumamente complejo. Las dificultades asociadas a la concurrencia han sido pensadas para el desarrollo de lenguajes de programación y conceptos que permitan hacer la concurrencia más manejable.
8. Lenguajes imperativos
En ciencias de la computación se llama lenguajes imperativos a aquellos en los cuales se le ordena a la computadora cómo realizar una tarea siguiendo una serie de pasos o instrucciones, por ejemplo:
Paso 1, solicitar número.
Paso 2, multiplicar número por dos.
Paso 3, imprimir resultado de la operación.
Paso 4, etc,
Algunos ejemplos de lenguajes imperativos son: BASIC, C, C++, Java, Clipper, Dbase, C# y Perl.
- Paradigma imperativo
- Ejemplo
- Dependencias de la biblioteca
Los lenguajes de programación que cumplen el paradigma imperativo se caracterizan por tener un estado implícito que es modificado mediante instrucciones o comandos del lenguaje. Como resultado, estos lenguajes tienen una noción de secuenciación de los comandos para permitir un control preciso y determinista del estado.
- Definición de procedimientos
- Definición de tipos de datos
- Chequeo de tipos en tiempo de compilación
- Cambio de estado de variables
- Pasos de ejecución de un proceso
A.- Funciones
En el ámbito de la programación, una función es un tipo subalgoritmo, es el término para describir una secuencia de órdenes que hacen una tarea específica de una aplicación más grande.
Las declaraciones de funciones generalmente son especificadas por:
- Un nombre único en el ámbito.- Nombre de la función con el que se identifica y se distingue de otras. No podrá haber otra función ni procedimiento con ese nombre (salvo sobrecarga o polimorfismo en programación orientada a objetos).
- Un tipo de dato de retorno.- Tipo de dato del valor que la función devolverá al terminar su ejecución.
- Una lista de parámetros.- Especificación del conjunto de argumentos (pueden ser cero, uno o más) que la función debe recibir para realizar su tarea.
- El código u órdenes de procesamiento.- Conjunto de órdenes y sentencias que debe ejecutar la función.
La diferencia entre funciones y los procedimientos (otro tipo de subalgotitmos) radica en que estos últimos no devuelven un resultado.
Las funciones en programación generalmente son las que realizan los cálculos para retornar el valor correspondiente a una función matemática más o menos compleja.
Ej: La siguiente función en C es la analogía al cálculo del promedio matemático. El nombre "Promedio", retorna un valor decimal correspondiente a la suma de 2 valores enteros de entrada (A,B):
float Promedio(int A, int B){
float r;
r=(A+B)/2.0;
return r;
}
Así una llamada a Promedio(3,5) retornará el valor real (float) 4.0.
B.- Declaraciones
Una declaración es una construcción del lenguaje que asocia un nombre con una entidad. Ada distingue cuidadosamente entre declaraciones (que introducen nuevos identificadores) y sentencias (que utilizan dichos identificadores). Hay dos clases de declaraciones:
- Implícitas: que ocurren como consecuencia de la semántica de otra construcción.
- Explícitas: aparecen en el texto del programa y pueden ser:
- Declaraciones de tipo, subtipos, variables y constantes (objetos), excepciones, especificaciones de subprogramas o paquetes, cláusulas de representación o cláusulas use.
- Los cuerpos de los subprogramas, paquetes y tareas.
En ocasiones es necesario utilizar declaraciones de subprogramas, por ejemplo, si se va a utilizar la recursividad entre dos procedimientos:
procedure P; — Declaración de P, necesaria para utilizara en Q.
procedure Q is — Cuerpo de Q.
begin
P;
— …
end Q;
procedure P is — Repite especificación para declarar el cuerpo.
begin
Q;
— …
end P;
También puede resultar útil declarar las especificaciones de los subprogramas en el comienzo del programa a modo de índice, sobre todo si hay muchos cuerpos.
- Declaraciones de subprogramas
- Vista de una entidad
Todas las declaraciones contienen una definición de vista de una entidad. Una vista consiste en:
- Un identificador de la identidad.
- Características específicas de la vista que afectan al uso de la entidad a través de dicha vista.
En la mayoría de los casos, una declaración contiene la definición de la vista y de la entidad misma, pero una declaración de renombrado, sin embargo, no define una entidad nueva, sino que define una nueva vista de una entidad.
- Parte declarativa
Una secuencia de declaraciones constituye una parte declarativa. Las siguientes construcciones de Ada tienen asociada una parte declarativa:
- Bloque.
- Cuerpo de un subprograma.
- Cuerpo de un paquete.
- Cuerpo de una tarea.
- Cuerpo de una entrada a un objeto protegido.
Por ejemplo, en un procedimiento, la parte declarativa comprendería las sentencias entre procedure y begin. El cuerpo de un procedimiento puede contener en su parte declarativa el cuerpo de otro procedimiento. Por tanto, los procedimientos pueden ser declarados sin límite de niveles de anidamiento sucesivos.
En ocasiones, las declaraciones requieren una segunda parte (se dice que requieren una terminación). La declaración y su terminación deben tener el mismo nombre y deben ocurrir en la misma región declarativa. Por ejemplo, un paquete necesita un cuerpo (que sería la terminación) si en su parte declarativa contiene alguna declaración que requiere una terminación que no se encuentre en dicha declaración.
- Región declarativa de una declaración
Hay que distinguir entre región declarativa de una declaración y parte declarativa. En el supuesto de una declaración de una variable (por ejemplo I: Integer := 0;) se extiende por una región de texto que abarca sólo una línea, sin embargo, otras declaraciones más complejas como procedimientos y paquetes constituyen muchas más líneas de texto. En Ada, existen las siguientes construcciones que tienen asociada una región declarativa:
- Cualquier declaración que no sea terminación de otra.
- Bloque
- Bucle
- Construcción accept.
- Manejador de excepción.
La región declarativa de cada una de estas construcciones comprende:
- El texto de la construcción misma.
- Texto adicional, determinado de esta manera:
- Si una declaración está incluida en la región, también lo está su terminación.
- Si una unidad de biblioteca está incluida en la región, también lo están sus unidades hijas.
- Si está incluido el requerimiento de compilación separada, también lo está su subunidad correspondiente.
Así, se pueden extraer las siguientes conclusiones:
- La especificación de un paquete y su cuerpo forman parte de la misma región declarativa porque el cuerpo es la terminación de la especificación, por lo que no se puede declarar la misma variable en la especificación y en el cuerpo.
- Ya que la declaración y el cuerpo de un paquete pueden estar en compilaciones distintas, la región declarativa de una declaración de paquete puede abarcar porciones de texto en varias unidades de compilación distintas.
- Todas las unidades de biblioteca son hijas de Standard, luego toda unidad de biblioteca pertenece a su región declarativa.
C.- Orientación a objetos
La Programación Orientada a Objetos (POO u OOP según sus siglas en inglés) es un paradigma de programación que usa objetos y sus interacciones para diseñar aplicaciones y programas de computadora. Está basado en varias técnicas, incluyendo herencia, modularidad, polimorfismo, y encapsulamiento. Su uso se popularizó a principios de la década de 1990. Actualmente son muchos los lenguajes de programación que soportan la orientación a objetos.
- Los objetos son entidades que combinan estado, comportamiento e identidad:
- El estado está compuesto de datos, serán uno o varios atributos a los que se habrán asignado unos valores concretos (datos).
- El comportamiento está definido por los procedimientos o métodos con que puede operar dicho objeto, es decir, qué operaciones se pueden realizar con él.
- La identidad es una propiedad de un objeto que lo diferencia del resto, dicho con otras palabras, es su identificador (concepto análogo al de identificador de una variable o una constante).
La programación orientada a objetos expresa un programa como un conjunto de estos objetos, que colaboran entre ellos para realizar tareas. Esto permite hacer los programas y módulos más fáciles de escribir, mantener y reutilizar.
De esta forma, un objeto contiene toda la información que permite definirlo e identificarlo frente a otros objetos pertenecientes a otras clases e incluso frente a objetos de una misma clase, al poder tener valores bien diferenciados en sus atributos. A su vez, los objetos disponen de mecanismos de interacción llamados métodos que favorecen la comunicación entre ellos. Esta comunicación favorece a su vez el cambio de estado en los propios objetos. Esta característica lleva a tratarlos como unidades indivisibles, en las que no se separan ni deben separarse el estado y el comportamiento.
Los métodos (comportamiento) y atributos (estado) están estrechamente relacionados por la propiedad de conjunto. Esta propiedad destaca que una clase requiere de métodos para poder tratar los atributos con los que cuenta. El programador debe pensar indistintamente en ambos conceptos, sin separar ni darle mayor importancia a ninguno de ellos, hacerlo podría producir el hábito erróneo de crear clases contenedoras de información por un lado y clases con métodos que manejen a las primeras por el otro. De esta manera se estaría realizando una programación estructurada camuflada en un lenguaje de programación orientado a objetos.
Esto difiere de la programación estructurada tradicional, en la que los datos y los procedimientos están separados y sin relación, ya que lo único que se busca es el procesamiento de unos datos de entrada para obtener otros de salida. La programación estructurada anima al programador a pensar sobre todo en términos de procedimientos o funciones, y en segundo lugar en las estructuras de datos que esos procedimientos manejan. En la programación estructurada sólo se escriben funciones que procesan datos. Los programadores que emplean éste nuevo paradigma, en cambio, primero definen objetos para luego enviarles mensajes solicitándoles que realicen sus métodos por sí mismos.
Los conceptos de la programación orientada a objetos tienen origen en Simula 67, un lenguaje diseñado para hacer simulaciones, creado por Ole-Johan Dahl y Kristen Nygaard del Centro de Cómputo Noruego en Oslo. Al parecer, en este centro, trabajaban en simulaciones de naves, y fueron confundidos por la explosión combinatoria de cómo las diversas cualidades de diversas naves podían afectar unas a las otras. La idea ocurrió para agrupar los diversos tipos de naves en diversas clases de objetos, siendo responsable cada clase de objetos de definir sus propios datos y comportamiento. Fueron refinados más tarde en Smalltalk, que fue desarrollado en Simula en Xerox PARC (y cuya primera versión fue escrita sobre Basic) pero diseñado para ser un sistema completamente dinámico en el cual los objetos se podrían crear y modificar "en marcha" en lugar de tener un sistema basado en programas estáticos.
La programación orientada a objetos tomó posición como el estilo de programación dominante a mediados de los años ochenta, en gran parte debido a la influencia de C++, una extensión del lenguaje de programación C. Su dominación fue consolidada gracias al auge de las Interfaces gráficas de usuario, para las cuales la programación orientada a objetos está particularmente bien adaptada. En este caso, se habla también de programación dirigida por eventos.
Las características de orientación a objetos fueron agregadas a muchos lenguajes existentes durante ese tiempo, incluyendo Ada, BASIC, Lisp, Pascal, entre otros. La adición de estas características a los lenguajes que no fueron diseñados inicialmente para ellas condujo a menudo a problemas de compatibilidad y a la capacidad de mantenimiento del código. Los lenguajes orientados a objetos "puros", por otra parte, carecían de las características de las cuales muchos programadores habían venido a depender. Para saltar este obstáculo, se hicieron muchas tentativas para crear nuevos lenguajes basados en métodos orientados a objetos, pero permitiendo algunas características imperativas de maneras "seguras". El Eiffel de Bertrand Meyer fue un temprano y moderadamente acertado lenguaje con esos objetivos pero ahora ha sido esencialmente reemplazado por Java, en gran parte debido a la aparición de Internet, y a la implementación de la máquina virtual de Java en la mayoría de navegadores. PHP en su versión 5 se ha ido modificando y soporta una orientación completa a objetos, cumpliendo todas las características propias de la orientación a objetos.
La programación orientada a objetos es una nueva forma de programar que trata de encontrar una solución a estos problemas. Introduce nuevos conceptos, que superan y amplían conceptos antiguos ya conocidos. Entre ellos destacan los siguientes:
- Objeto: entidad provista de un conjunto de propiedades o atributos (datos) y de comportamiento o funcionalidad (métodos). Corresponden a los objetos reales del mundo que nos rodea, o a objetos internos del sistema (del programa). Es una instancia a una clase.—
- Clase: definiciones de las propiedades y comportamiento de un tipo de objeto concreto. La instanciación es la lectura de estas definiciones y la creación de un objeto a partir de ellas.
- Método: algoritmo asociado a un objeto (o a una clase de objetos), cuya ejecución se desencadena tras la recepción de un "mensaje". Desde el punto de vista del comportamiento, es lo que el objeto puede hacer. Un método puede producir un cambio en las propiedades del objeto, o la generación de un "evento" con un nuevo mensaje para otro objeto del sistema.
- Evento: un suceso en el sistema (tal como una interacción del usuario con la máquina, o un mensaje enviado por un objeto). El sistema maneja el evento enviando el mensaje adecuado al objeto pertinente. También se puede definir como evento, a la reacción que puede desencadenar un objeto, es decir la acción que genera.
- Mensaje: una comunicación dirigida a un objeto, que le ordena que ejecute uno de sus métodos con ciertos parámetros asociados al evento que lo generó.
- Propiedad o atributo: contenedor de un tipo de datos asociados a un objeto (o a una clase de objetos), que hace los datos visibles desde fuera del objeto y esto se define como sus características predeterminadas, y cuyo valor puede ser alterado por la ejecución de algún método.
- Estado interno: es una propiedad invisible de los objetos, que puede ser únicamente accedida y alterada por un método del objeto, y que se utiliza para indicar distintas situaciones posibles para el objeto (o clase de objetos).
- Componentes de un objeto:atributos, identidad, relaciones y métodos.
- Representación de un objeto: un objeto se representa por medio de una tabla o entidad que esté compuesta por sus atributos y funciones correspondientes.
En comparación con un lenguaje imperativo, una "variable", no es más que un contenedor interno del atributo del objeto o de un estado interno, así como la "función" es un procedimiento interno del método del objeto.
- Características de la POO
Hay un cierto desacuerdo sobre exactamente qué características de un método de programación o lenguaje le definen como "orientado a objetos", pero hay un consenso general en que las características siguientes son las más importantes (para más información, seguir los enlaces respectivos):
- Abstracción: Cada objeto en el sistema sirve como modelo de un "agente" abstracto que puede realizar trabajo, informar y cambiar su estado, y "comunicarse" con otros objetos en el sistema sin revelar cómo se implementan estas características. Los procesos, las funciones o los métodos pueden también ser abstraídos y cuando lo están, una variedad de técnicas son requeridas para ampliar una abstracción.
- Encapsulamiento: Significa reunir a todos los elementos que pueden considerarse pertenecientes a una misma entidad, al mismo nivel de abstracción. Esto permite aumentar la cohesión de los componentes del sistema. Algunos autores confunden este concepto con el principio de ocultación, principalmente porque se suelen emplear conjuntamente.
- Principio de ocultación: Cada objeto está aislado del exterior, es un módulo natural, y cada tipo de objeto expone una interfaz a otros objetos que específica cómo pueden interactuar con los objetos de la clase. El aislamiento protege a las propiedades de un objeto contra su modificación por quien no tenga derecho a acceder a ellas, solamente los propios métodos internos del objeto pueden acceder a su estado. Esto asegura que otros objetos no pueden cambiar el estado interno de un objeto de maneras inesperadas, eliminando efectos secundarios e interacciones inesperadas. Algunos lenguajes relajan esto, permitiendo un acceso directo a los datos internos del objeto de una manera controlada y limitando el grado de abstracción. La aplicación entera se reduce a un agregado o rompecabezas de objetos.
- Polimorfismo: comportamientos diferentes, asociados a objetos distintos, pueden compartir el mismo nombre, al llamarlos por ese nombre se utilizará el comportamiento correspondiente al objeto que se esté usando. O dicho de otro modo, las referencias y las colecciones de objetos pueden contener objetos de diferentes tipos, y la invocación de un comportamiento en una referencia producirá el comportamiento correcto para el tipo real del objeto referenciado. Cuando esto ocurre en "tiempo de ejecución", esta última característica se llama asignación tardía o asignación dinámica. Algunos lenguajes proporcionan medios más estáticos (en "tiempo de compilación") de polimorfismo, tales como las plantillas y la sobrecarga de operadores de C++.
- Herencia: las clases no están aisladas, sino que se relacionan entre sí, formando una jerarquía de clasificación. Los objetos heredan las propiedades y el comportamiento de todas las clases a las que pertenecen. La herencia organiza y facilita el polimorfismo y el encapsulamiento permitiendo a los objetos ser definidos y creados como tipos especializados de objetos preexistentes. Estos pueden compartir (y extender) su comportamiento sin tener que reimplementar su comportamiento. Esto suele hacerse habitualmente agrupando los objetos en clases y estas en árboles o enrejados que reflejan un comportamiento común. Cuando un objeto hereda de más de una clase se dice que hay herencia múltiple; esta característica no está soportada por algunos lenguajes (como Java).
- Lenguajes orientados a objetos
Entre los lenguajes orientados a objetos destacan los siguientes:
- ActionScript
- ActionScript 2
- ActionScript 3
- Ada
- C++
- C#
- Clarion
- Lenguaje de programación D
- Delphi
- Harbour
- Eiffel
- Java
- Lexico (en castellano)
- Objective-C
- Ocaml
- Oz
- Lenguaje de programación R
- Perl (soporta herencia múltiple)
- PHP (en su versión 5)
- PowerBuilder
- Python
- Ruby
- Smalltalk
- Turbo Pascal 7
- Magik (SmallWorld)
- VB.NET
- Visual FoxPro
- XBase++
Muchos de estos lenguajes de programación no son puramente orientados a objetos, sino que son híbridos que combinan la POO con otros paradigmas.
Al igual que C++ otros lenguajes, como OOCOBOL, OOLISP, OOPROLOG y Object REXX, han sido creados añadiendo extensiones orientadas a objetos a un lenguaje de programación clásico.
Un nuevo paso en la abstracción de paradigmas de programación es la Programación Orientada a Aspectos (POA). Aunque es todavía una metodología en estado de maduración, cada vez atrae a más investigadores e incluso proyectos comerciales en todo el mundo.
También es necesario recalcar que en la programación orientada a objetos es factible de utilizar en JavaScript
Bibliografía.
Internet www.educaweb.com
www.e_magister.com
www.monografias.com
www.postgrado.inea.org
www.inea.uva.es
www.tu_discovery.com
www.aulafacil.com
www.tecniciencia.com
www.wikipedia.com
Elaborado por:
T.S.U. Henry Jesus Mendoza Pacheco,
37 Años de edad.
Trabajo elaborado el 20 de Enero de 2008.
Página anterior | Volver al principio del trabajo | Página siguiente |