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
buclevar = 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 bucleprintf("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
Bucledo
var = var + 2
if var = 10 then 'Codigo para salir del
buclegoto 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
bucleexit 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.
- Si la condición se cumple, se
- 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.
- En su lugar, se puede utilizar también la
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
formalesValores pasados (en tiempo de
ejecución) argumentos
actualesLa 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ámetrosint 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
OkSi 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 defectoNota: 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
referenciaHemos 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
enterox = x * 2;
}
float f = 3.14;
func(f); //
f es promovido a int antes de asignación a
'x'//
x == 6Lo 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 = 4int& ry = i;
x = pru
(ry); // ahora: x =
12, i = 4Observe 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 = 12Observe 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 = 12Atenció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
POOPensar 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 concurrenciaEl 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 imperativosEn 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.
- Declaraciones de tipo,
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.
- Si una declaración está
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 |