Escolar Documentos
Profissional Documentos
Cultura Documentos
• El estado está compuesto de datos, será uno o varios atributos a los que se
habrán asignado unos valores concretos (datos).
• El comportamiento está definido por los procedimientos o Método (informática)
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).
Conceptos fundamentales
Características de POO
C++
Características
Tipos de datos
El modificador unsigned se puede aplicar a enteros para obtener números sin signo
(por omisión los enteros contienen signo), con lo que se consigue un rango mayor de
números naturales.
Tamaños Asociados
Según la máquina y el compilador que se Tamaños de tipos primitivos bajo i386 (GCC)
utilice los tipos primitivos pueden ocupar un Tipo Número de Bits
determinado tamaño en memoria. La char 8
siguiente lista ilustra el número de bits que
short 16
ocupan los distintos tipos primitivos la
arquitectura x86. int 32
float 32
Otras arquitecturas pueden requerir distintos double 64
tamaños de tipos de datos primitivos. C++ no dice nada acerca de cuál es el número
de bits en un byte, ni del tamaño de estos tipos; más bien, ofrece solamente las
siguientes "garantías de tipos":
• Un tipo char tiene el tamaño mínimo en bytes asignable por la máquina, y todos
los bits de este espacio deben ser "accesibles".
• El tamaño reconocido de char es de 1. Es decir, sizeof(char) siempre devuelve
1.
• Un tipo short tiene al menos el mismo tamaño que un tipo char.
• Un tipo long tiene al menos el doble tamaño en bytes que un tipo short.
• Un tipo int tiene un tamaño entre el de short y el de long, ambos inclusive,
preferentemente el tamaño de un apuntador de memoria de la máquina.
• Un tipo unsigned tiene el mismo tamaño que su versión signed.
wchar_t
Para la versión del estándar que se publicó en 1999, se decidió añadir el tipo de dato
wchar_t, que permite el uso de caracteres UNICODE, a diferencia del tradicional char,
que contempla simplemente al código de caracteres ASCII extendido. A su vez, se ha
definido para la mayoría de las funciones y clases, tanto de C como de C++, una
versión para trabajar con wchar_t, donde usualmente se prefija el carácter w al nombre
de la función (en ocasiones el carácter es un infijo). Por ejemplo:
• strcpy - wstrcpy
• std::string - std::wstring
• std::cout - std::wcout
Además se utiliza para determinar que una función no retorna un valor, como en:
Cabe destacar que void no es un tipo. Una función como la declarada anteriormente
no puede retornar un valor por medio de return: la palabra clave va sola. No es posible
una declaración del tipo:
void t;
void *memoria;
Principios
Todo programa en C++ debe tener la función main() (a no ser que se especifique en
tiempo de compilación otro punto de entrada, que en realidad es la función que tiene el
main())
int main()
{}
El tipo de retorno de main es int. Al finalizar la función main, debe incluirse el valor de
retorno (por ejemplo, return 0;, aunque el estándar prevé solamente dos posibles
valores de retorno: EXIT_SUCCESS y EXIT_ERROR, definidas en el archivo cstddef),
o salir por medio de la función exit. Alternativamente puede dejarse en blanco, en cuyo
caso el compilador es responsable de agregar la salida adecuada.
El Concepto de Clase
Los objetos en C++ son abstraídos mediante una Clase. Según el paradigma de la
programación orientada a objetos un objeto consta de:
1. Métodos o funciones
2. Atributos o Variables Miembro
Un ejemplo de clase que podemos tomar es la clase perro. Cada perro comparte unas
características (atributos). Su número de patas, el color de su pelaje o su tamaño son
algunos de sus atributos. Las funciones que lo hagan ladrar, cambiar su
comportamiento... esas son las funciones de la clase.
class Punto
{
//por omisión los miembros son 'private' para que sólo se puedan modificar desde la
propia clase.
private:
// Variable miembro privada
int id;
protected:
// Variables miembro protegidas
int x;
int y;
public:
// Constructor
Punto();
// Destructor
~Punto();
// Funciones miembro o métodos
int ObtenerX();
int ObtenerY();
};
Constructores
Tomando el ejemplo de la Clase Punto, si deseamos que cada vez que se cree un
objeto de esta clase las coordenadas del punto sean igual a cero podemos agregar un
constructor como se muestra a continuación:
class Punto
{
public:
float x;
float y;
// Constructor
};
int main()
{
Punto MiPunto; // creamos un elemento de la clase Punto llamado MiPunto
cout << "Coordenada X:" << MiPunto.x << endl; // mostramos el valor acumulado
en la variable x
cout << "Coordenada Y:" << MiPunto.y << endl; // mostramos el valor acumulado
en la variable y
return 0;
}
Si compilamos y ejecutamos el anterior programa, obtenemos una salida que debe ser
similar a la siguiente:
Destructores
Funciones Miembro
Función miembro es aquella que está declarada en ámbito de clase. Son similares a
las funciones habituales, con la salvedad de que el compilador realizara el proceso de
Decoración de nombre (Name Mangling en inglés): Cambiara el nombre de la función
añadiendo un identificador de la clase en la que está declarada, pudiendo incluir
caracteres especiales o identificadores numéricos. Además, las funciones miembro
reciben implícitamente un parámetro adicional: El puntero this, que referencia al objeto
que ejecuta la función.
Las funciones miembro se invocan accediendo primero al objeto al cual refieren, con la
sintaxis: myobject.mymemberfunction(), esto es un claro ejemplo de una función
miembro.
Plantillas
Por ejemplo:
Especialización
El siguiente ejemplo:
crea una plantilla bajo la cual pueden ser definidas en el código de cabecera
cualesquiera funciones especializadas para un tipo de datos como int myfunction(int),
int myfunction(std::string), int myfunction(bool), etcétera:
Cada una de estas funciones tiene su propia definición (cuerpo). Cada cuerpo
diferente, no equivalente ("no convertible") corresponde a una especialización. Si una
de estas funciones no fuera definida, el compilador tratará de aplicar las conversiones
de tipos de datos que le fuesen permitidas para "calzar" una de las plantillas, o
generará un mensaje de error si fracasa en ese proceso.
Todas las definiciones habilitadas de una plantilla deben estar disponibles al momento
de la compilación, por lo cual no es posible actualmente "compilar" una plantilla como
archivo de objeto, sino simplemente compilar especializaciones de la plantilla. Por lo
tanto, las plantillas se distribuyen junto con el código fuente de la aplicación. En otras
palabras, no es posible compilar la plantilla std::vector< > a código objeto, pero sí es
posible, por ejemplo, compilar un tipo de datos std::vector<std::string>.
Clases Abstractas
En C++ es posible definir clases abstractas. Una clase abstracta, o clase base
abstracta (ABC), es una que está diseñada sólo como clase padre de las cuales se
deben derivar clases hijas. Una clase abstracta se usa para representar aquellas
entidades o métodos que después se implementarán en las clases derivadas, pero la
clase abstracta en sí no contiene ninguna implementación -- solamente representa los
métodos que se deben implementar. Por ello, no es posible instanciar una clase
abstracta, pero sí una clase concreta que implemente los métodos definidos en ella.
Las clases abstractas son útiles para definir interfaces, es decir, un conjunto de
métodos que definen el comportamiento de un módulo determinado. Estas definiciones
pueden utilizarse sin tener en cuenta la implementación que se hará de ellos.
En C++ los métodos de las clases abstractas se definen como funciones virtuales
puras.
class Abstracta
{
public:
virtual int metodo() = 0;
};
Espacios de Nombres
Por ejemplo:
# include <iostream>
// Las funciones en esta cabecera existen dentro del espacio de nombres std::
namespace mi_paquete{
int mi_valor;
};
int main()
{
int mi_valor= 3;
mi_paquete::mi_valor= 4;
Como puede verse, las invocaciones directas a mi_valor darán acceso solamente a la
variable descrita localmente; para acceder a la variable del paquete mi_paquete es
necesario acceder específicamente el espacio de nombres. Un atajo recomendado
para programas sencillos es la directiva using namespace, que permite acceder a los
nombres de variables del paquete deseado en forma directa, siempre y cuando no se
produzca alguna ambigüedad o conflicto de nombres.
Excepciones
C++ permite la existencia de excepciones, las cuales son una metodología de flujo de
ejecución basada en la prueba del código deseado (try) seguida por la intercepción de
ciertas condiciones bajo un flujo de programa adicional (catch). La declaración de
estas condiciones se hace "arrojando" (throw) sentencias especiales que son
capturadas por el flujo catch correspondiente.
Por ejemplo:
# include <iostream>
int main()
{
std::string x = "Hola Mundo";
try {
std::cout<< x.at(99)<<std::endl;
}
catch (std::exception& X) {
std::cerr<< X.what()<<std::endl;
}
return 0;
}
Si una excepción se propaga sin ser atrapada por un bloque catch, y llegara hasta el
punto de terminación del programa, se produce la terminación abrupta de éste
("abort").
Herencia
Existen varios tipos de herencia entre clases en el lenguaje de programación C++.
Estos son:
Herencia Simple
En la herencia, las clases derivadas "heredan" los datos y las funciones miembro de
las clases base, pudiendo las clases derivadas redefinir estos comportamientos
(polimorfismo) y añadir comportamientos nuevos propios de las clases derivadas. Para
no romper el principio de encapsulamiento (ocultar datos cuyo conocimiento no es
necesario para el uso de las clases), se proporciona un nuevo modo de visibilidad de
los datos/funciones: "protected". Cualquier cosa que tenga visibilidad protected se
comportará como pública en la clase Base y en las que componen la jerarquía de
herencia, y como privada en las clases que NO sean de la jerarquía de la herencia.
Antes de utilizar la herencia, nos tenemos que hacer una pregunta, y si tiene sentido,
podemos intentar usar esta jerarquía: Si la frase <claseB> ES-UN <claseA> tiene
sentido, entonces estamos ante un posible caso de herencia donde clase A será la
clase base y clase B la derivada.
class Barco {
protected:
char* nombre;
float peso;
public:
//Constructores y demás funciones básicas de barco
};
y ahora las características de las clases derivadas, podrían (a la vez que heredan las
de barco) añadir cosas propias del subtipo de barco que vamos a crear, por ejemplo:
class Carguero: public Barco { // Esta es la manera de especificar que hereda de Barco
private:
float carga;
//El resto de cosas
};
• Herencia publica (class Derivada: public Base ) : Con este tipo de herencia se
respetan los comportamientos originales de las visibilidades de la clase Base
en la clase Derivada.
• Herencia privada (clase Derivada: private Base) : Con este tipo de herencia
todo componente de la clase Base, será privado en la clase Derivada (ojo!
siempre será privado aunque ese dato fuese público en la clase Base)
• Herencia protegida (clase Derivada: protected Base) : Con este tipo de
herencia, todo componente publico y protegido de la clase Base, será protegido
en la clase Derivada, y los componentes privados, siguen siendo privados.
Herencia Múltiple
class Persona {
...
Hablar();
Caminar();
...
};
class Empleado {
Persona jefe;
int sueldo;
Cobrar();
...
};
Por tanto, es posible utilizar más de una clase para que otra herede sus
características.
Sobrecarga de Operadores
• Operadores Unarios
o Operador * (de indirección)
o Operador -> (de indirección)
o Operador +
o Operador -
o Operador ++
o Operador --
• Operadores Binarios
o Operador ==
o Operador +
o Operador -
o Operador *
o Operador /
o Operador %
o Operador <<
o Operador >>
o Operador &
o Operador ^
o Operador |
o Operador []
o Operador ()
• Operadores de Asignación
o Operador =
o Operador +=
o Operador -=
o Operador *=
o Operador /=
o Operador %=
o Operador <<=
o Operador >>=
o Operador &=
o Operador ^=
o Operador |=
Dado que estos operadores son definidos para un tipo de datos definido por el usuario,
éste es libre de asignarles cualquiera semántica que desee. Sin embargo, se
considera de primera importancia que las semánticas sean tan parecidas al
comportamiento natural de los operadores como para que el uso de los operadores
sobrecargados sea intuitivo. Por ejemplo, el uso del operador unario - debiera cambiar
el "signo" de un "valor".
Los operadores sobrecargados no dejan de ser funciones, por lo que pueden devolver
un valor, si este valor es del tipo de datos con el que trabaja el operador, permite el
encadenamiento de sentencias. Por ejemplo, si tenemos 3 variables A,B y C de un tipo
T y sobrecargamos el operador = para que trabaje con el tipo de datos T, hay dos
opciones: si el operador no devuelve nada una sentencia como "A=B=C;" (sin las
comillas) daría error, pero si se devuelve un tipo de datos T al implementar el
operador, permitiría concatenar cuantos elementos se quisieran, permitiendo algo
como "A=B=C=D=...;"
De esta forma, para mostrar un punto, solo habría que realizar la siguiente expresión:
//...
Punto p(4,5);
//...
cout << "Las coordenadas son: " << p << endl;
//...
fstreams
Ejemplo: f.open("datos.txt",ios::in);
Ejemplo: f.close();
Leer un fichero:
Ejemplo: f>>HOLA;
2-Si es un fichero binario(.dat);
nombre_variable_fichero.read((char*)&nombre_variable,sizeof(tipo_variable));
Ejemplo:
f.read((char*)&e,sizeof(int));
Escribir un fichero:
Ejemplo: f<<HOLA;
2-Si es un fichero binario(.dat);
nombre_variable_fichero.write((char*)&nombre_variable,sizeof(tipo_variable));
Ejemplo:
f.write((char*)&e,sizeof(int));
ostringstream s;
s << nombre << "," << edad << "," << estatura << "," << punto(5,6) << endl;
cout << s.str();
istringstream s(cadena);
s >> nombre >> edad >> estatura >> p;
Contenedores
Son clases plantillas especiales utilizadas para almacenar tipos de datos genéricos,
sean cuales sean. Según la naturaleza del almacenado, disponemos de varios tipos:
• Colas dobles: son parecidas a los vectores, pero tienen mejor eficiencia para
agregar o eliminar elementos en las "puntas".
• Listas.
• Adaptadores de secuencia.
• Contenedores asociativos: map y multimap, que permiten asociar una "clave"
con un "valor".
• Contenedores asociativos: set y multiset, que ofrecen solamente la condición de
"pertenencia", sin la necesidad de garantizar un ordenamiento particular de los
elementos que contienen.
Iteradores
Algoritmos
Entre las funciones más conocidas están swap (variable1, variable2), que simplemente
intercambia los valores de variable1 y variable2; max (variable1, variable2) y su símil
min (variable1, variable2), que retornan el máximo o mínimo entre dos valores; find
(inicio, fin, valor) que busca valor en el espacio de variables entre inicio y fin; etcétera.
Los algoritmos son muy variados, algunos incluso tienen versiones específicas para
operar con ciertos iteradores o contenedores, y proveen un nivel de abstracción extra
que permite obtener un código más "limpio", que "describe" lo que se está haciendo, en
vez de hacerlo paso a paso explícitamente.
En C++, cualquier tipo de datos que sea declarado completo (fully qualified, en inglés)
se convierte en un tipo de datos único. Las condiciones para que un tipo de datos T
sea declarado completo son a grandes rasgos las siguientes:
En general, esto significa que cualquier tipo de datos definido haciendo uso de las
cabeceras completas, es un tipo de datos completo.
Los tipos enumerados, entonces, ya no son simplemente alias para tipos enteros, sino
que son tipos de datos únicos en C++. El tipo de datos bool, igualmente, pasa a ser un
tipo de datos único, mientras que en C funcionaba en algunos casos como un alias
para alguna clase de dato de tipo entero.
Compiladores
Uno de los compiladores libres de C++ es el de GNU, el compilador G++ (parte del
proyecto Gcc, que engloba varios compiladores para distintos lenguajes),
C #.
Caracteristicas
La creación del nombre del lenguaje, C♯, proviene de dibujar dos signos positivos
encima de los dos signos positivos de "C++", queriendo dar una imagen de salto
evolutivo del mismo modo que ocurrió con el paso de C a C++.
C♯, como parte de la plataforma.NET, está normalizado por ECMA desde diciembre de
2001 (ECMA-334 "Especificación del lenguaje C♯"). El 7 de noviembre de 2005 salió la
versión 2.0 del lenguaje que incluía mejoras tales como tipos genéricos, métodos
anónimos, iteradores, tipos parciales y tipos anulables. El 19 de noviembre de 2007
salió la versión 3.0 de C# destacando entre las mejoras los tipos implícitos, tipos
anónimos y LINQ (Language Integrated Query -consulta integrada en el lenguaje).
Tipos de datos
No existe una conversión definida entre bool y los valores enteros (1 no se convierte a
verdadero ni 0 se convierte a falso).
Constantes
Las constantes en C♯ se denominan literales. Todas las constantes tienen un tipo de
dato, en caso de ser una constante entera se usa la de menor tamaño que pueda
alojarla, empezando por int. En caso de punto flotante se considera como un double.
Sin embargo se puede especificar explícitamente el tipo de dato que una constante
deberá usar, por medio de los sufijos:
C♯, al igual que C++, es compatible con el tipo de constante cadena de caracteres.
Dentro de la cadena de caracteres se pueden usar secuencias de escape. Una cadena
de caracteres puede iniciarse con el símbolo @ seguido por una cadena entre comillas,
en tal caso, las secuencias de escape no tienen efecto y además la cadena puede
ocupar dos o más líneas.
Variables
Toda variable se debe declarar antes de ser utilizada. La forma en que se declara una
variable en C♯ es la siguiente:
tipo nombre_variable;
Operadores
C♯ tiene cuatro clases generales de operadores: aritméticos, a nivel de bit, relacionales
y lógicos.
Operadores
Operador Significado Tipo
+ Suma Aritmético
- Resta Aritmético
* Producto Aritmético
/ División Aritmético
% Módulo (residuo entero) Aritmético
++ Incremento Aritmético
-- Decremento Aritmético
== Igual que Relacional
!= Distinto que Relacional
> Mayor que Relacional
< Menor que Relacional
>= Mayor o igual que Relacional
<= Menor o igual que Relacional
& AND Lógico y a nivel de bits
| OR Lógico y a nivel de bits
^ XOR y de nivel de bits Lógico
|| OR de cortocircuito Lógico
&& AND de cortocircuito Lógico
! NOT Lógico
~ Complemento a uno A nivel de bits
<< Desplazamiento a la izquierda A nivel de bits
>> Desplazamiento a la derecha A nivel de bits
Instrucciones de control
Métodos
Todo método debe de ser parte de una clase, no existen métodos globales.
• De forma predeterminada, los parámetros se pasan por valor (se copia dicho
valor).
• El modificador ref fuerza a pasar los parámetros por referencia en vez de
pasarlos por valor.
• El modificador out es similar al modificador ref con una excepción: sólo se
puede utilizar para pasar un valor fuera de un método. El método debe de
asignar un valor al parámetro antes de que el método finalice.
• Cuando ref y out modifican un parámetro de referencia, la propia referencia se
pasa por referencia.
• El modificador params sirve para definir un número variable de argumentos los
cuales se implementan como una matriz. Ejemplo: public int maxVal(params
int[] nums){...}, esta función se podría llamar así: maxVal(23,3,a,-12);.
• Un método debe tener como máximo un único parámetro params y éste debe
de ser el último.
• Un método puede devolver cualquier tipo de datos, incluyendo tipos de clase.
• Ya que en C# las matrices se implementan como objetos, un método también
puede devolver una matriz (algo que se diferencia de C++ en que las matrices
no son válidas como tipos de valores devueltos).
• C♯ implementa sobrecarga de métodos, dos o más métodos pueden tener el
mismo nombre siempre y cuando se diferencien por sus parámetros.
• El método Main es un método especial al cual se refiere el punto de partida del
programa. Tiene la siguiente sintaxis: public static int Main(string[] args){...}.
Clases y objetos
Varios puntos a tener en cuenta en C♯ con respecto a clases y objetos son los
siguientes:
• Una variable de objeto de cierta clase no almacena los valores del objeto sino
su referencia (al igual que Java).
• El operador de asignación no copia los valores de un objeto, sino su referencia
a él (al igual que Java).
• Un constructor tiene el mismo nombre que su clase y es sintácticamente similar
a un método.
• Un constructor no devuelve ningún valor.
• Al igual que los métodos, los constructores también pueden ser sobrecargados.
• Si no se especifica un constructor en una clase, se usa uno por defecto que
consiste en asignar a todas las variables el valor de 0, null o false según
corresponda.
• Para crear un nuevo objeto se utiliza la siguiente sintaxis: variable = new
nombre_clase();.
• Un destructor se declara como un constructor, aunque va precedido por un
signo de tilde ~.
• Se emplea una desasignación de memoria de objetos no referenciados
(recolección de basura), y cuando esto ocurre se ejecuta el destructor de dicha
clase.
• El destructor de una clase no se llama cuando un objeto sale del ámbito.
• Todos los destructores se llamarán antes de que finalice un programa.
• La palabra clave this es un apuntador al mismo objeto en el cual se usa.
• La palabra clave static hace que un miembro pertenezca a una clase en vez de
pertener a objetos de dicha clase. Se puede tener acceso a dicho miembro
antes de que se cree cualquier objeto de su clase y sin referencias a un objeto.
• Un método static no tiene una referencia this.
• Un método static puede llamar sólo a otros métodos static.
• Un método static sólo debe tener acceso directamente a datos static.
• Un constructor static se usa para inicializar atributos que se aplican a una clase
en lugar de aplicarse a una instancia.
• C♯ permite la sobrecarga de operadores con la palabra clave operator.
Matrices
• Para crear una matriz se utiliza el siguiente formato: tipo[] nombre_matriz = new
tipo[tamaño];
• Se puede crear una matriz inicializada así: tipo[] nombre_matriz = { val1 , val2 ,
val3 , ... , valN };
• Los índices de las matrices comienzan en 0.
• Para crear una matriz bidimensional se utiliza el siguiente formato: tipo[,]
nombre_matriz = new tipo[filas,columnas]
• Para referirse a un elemento de una matriz bidimensional no se usa la forma
matriz[fila][columna] (la cual usa C++), si no matriz[fila,columna].
• Ya que C♯ implementa matrices como objetos, cada matriz tiene asociada una
propiedad Length que contiene el número de elementos que puede alojar cada
matriz.
Cadenas de carácteres
Compiladores
Java
Caracteristicas
Java en 1995 dió un salto al mundo de Internet con lo que representó un salto muy
importante dentro de este lenguaje de la programación exclusivamente enfocado a
trabajar con Objetos muy similar a C++
C# proporciona todos los tipos de datos que están disponibles en Java y agrega
compatibilidad para los números sin signo y un nuevo tipo de punto flotante de 128 bits
de alta precisión.
Para cada tipo de datos primitivo en Java, la biblioteca de clases principal proporciona
una clase contenedora, que lo representa como un objeto de Java. Por ejemplo, la
clase Int32 contiene el tipo de datos int y la clase Double contiene el tipo de datos
double.
Por otro lado, todos los tipos de datos primitivos en C# son objetos en el espacio de
nombres System. Para cada tipo de datos, se proporciona un nombre corto o alias. Por
ejemplo, int es el nombre corto correspondiente a System.Int32 y double es la forma
abreviada de System.Double.
Nombre Clase
Tipo Ancho Intervalo (bits)
corto .NET
byte Byte Entero sin signo 8 0 a 255
sbyte SByte Entero con signo 8 -128 a 127
-2.147.483.648 a
int Int32 Entero con signo 32
2.147.483.647
uint UInt32 Entero sin signo 32 0 a 4294967295
short Int16 Entero con signo 16 -32.768 a 32.767
ushort UInt16 Entero sin signo 16 0 a 65535
-922337203685477508 a
long Int64 Entero con signo 64
922337203685477507
ulong UInt64 Entero sin signo 64 0 a 18446744073709551615
Tipo de punto flotante de
float Single 32 -3,402823e38 a 3,402823e38
precisión simple
Tipo de punto flotante de -1,79769313486232e308 a
double Double 64
precisión doble 1,79769313486232e308
Símbolos Unicode utilizados
char Char Un carácter Unicode 16
en el texto
bool Boolean Tipo Boolean lógico 8 True o false
Tipo base de todos los otros
object Object
tipos
string String Una secuencia de caracteres
Tipo preciso fraccionario o
integral, que puede
decimal Decimal representar números 128 ±1.0 × 10e−28 a ±7.9 × 10e28
decimales con 29 dígitos
significativos
Dado que C# representa todos los tipos de datos primitivos como objetos, es posible
llamar a un método de objeto de un tipo de datos primitivo. Por ejemplo:
C#
static void Main()
{
int i = 10;
object o = i;
System.Console.WriteLine(o.ToString());
}
Constantes
Enumeraciones
Las enumeraciones se utilizan para agrupar constantes con nombres en forma similar
a la forma en que se utilizan en C y C++; no están disponibles en Java. En el ejemplo
siguiente se define una enumeración Color sencilla.
C#
public enum Color
{
Green, //defaults to 0
Orange, //defaults to 1
Red, //defaults to 2
Blue //defaults to 3
}
C#
public enum Color2
{
Green = 10,
Orange = 20,
Red = 30,
Blue = 40
}
En el siguiente ejemplo de código se llama al método GetNames del tipo Enum para
mostrar las constantes disponibles para una enumeración. Luego, asigna un valor a
una enumeración y muestra el valor.
C#
class TestEnums
{
static void Main()
{
System.Console.WriteLine("Possible color choices: ");
Cadenas
Operadores
Este lenguaje presenta un conjunto de operadores con los que escribir distintas
expresiones. Además, se pueden utilizar los paréntesis para agrupar subexpresiones.
Operadores Aritméticos
Son los operadores que permiten realizar la suma, resta, producto, división y módulo:
+, -, *, / y % [obligatorio implementar al menos uno]. Se aplican sobre datos enteros,
proporcionando un resultado entero.
Operadores de Relación
Son los operadores que permiten realizar las comparaciones de igual, distinto, menor,
mayor, menor o igual, mayor o igual: ==, !=, <, >, <= y >= [obligatorio implementar al
menos uno de los operadores]. Se aplican sobre datos enteros y proporcionan un
resultado lógico.
Operadores Lógicos
Operadores de asignación
n += m; /* es equivalente a n = n + m; */
Operador Condicional
El operador punto (.) permite utilizar los miembros de una clase. Ejemplo:
Tipos de clase
Hasta ahora sólo se ha utilizado la palabra clave public para calificar el nombre de las
clases que hemos visto, pero hay tres modificadores más. Los tipos de clases que
podemos definir son:
abstract
Una clase abstract tiene al menos un método abstracto. Una clase abstracta no se
instancia, sino que se utiliza como clase base para la herencia.
final
Una clase final se declara como la clase que termina una cadena de herencia. No se
puede heredar de una clase final. Por ejemplo, la clase Math es una clase final.
public
Las clases public son accesibles desde otras clases, bien sea directamente o por
herencia. Son accesibles dentro del mismo paquete en el que se han declarado. Para
acceder desde otros paquetes, primero tienen que ser importadas.
synchronizable
Este modificador especifica que todos los métodos definidos en la clase son
sincronizados, es decir, que no se puede acceder al mismo tiempo a ellos desde
distintos threads; el sistema se encarga de colocar los flags necesarios para evitarlo.
Este mecanismo hace que desde threads diferentes se puedan modificar las mismas
variables sin que haya problemas de que se sobreescriban.
ADA
Caracteristicas
Legibilidad
Los programas profesionales se leen muchas más veces de las que se escriben,
por tanto, conviene evitar una notación que permita escribir el programa
fácilmente, pero que sea difícil leerlo excepto, quizás, por el autor original y no
mucho tiempo después de escribirlo.
Tipado fuerte
Esto asegura que todo objeto tenga un conjunto de valores que esté claramente
definido e impide la confusión entre conceptos lógicamente distintos. Como
consecuencia, el compilador detecta más errores que en otros lenguajes.
Construcción de grandes programas
Se necesitan mecanismos de encapsulado para compilar separadamente y para
gestionar bibliotecas de cara a crear programas transportables y mantenibles de
cualquier tamaño.
Manejo de excepciones
Los programas reales raramente son totalmente correctos. Es necesario
proporcionar medios para que el programa se pueda construir en capas y por
partes, de tal forma que se puedan limitar las consecuencias de los errores que se
presenten en cualquiera de las partes.
Abstracción de datos
Se puede obtener mayor transportabilidad y mejor mantenimiento si se pueden
separar los detalles de la representación de los datos y las especificaciones de las
operaciones lógicas sobre los mismos.
Procesamiento paralelo
Para muchas aplicaciones es importante que el programa se pueda implementar
como una serie de actividades paralelas. Dotando al lenguaje de estos
mecanismos, se evita tener que añadirlos por medio de llamadas al sistema
operativo, con lo que se consigue mayor transportabilidad y fiabilidad.
Unidades genéricas
En muchos casos, la lógica de parte de un programa es independiente de los tipos
de los valores que estén siendo manipulados. Para ello, se necesita un mecanismo
que permita la creación de piezas de programa similares a partir de un único
original. Esto es especialmente útil para la creación de bibliotecas.
De este modo, el usuario debe conocer los detalles de la implementación y sabe que
se utiliza una representación cartesiana. Además, el usuario está obligado a hacer uso
de la representación.
Para impedir el uso del conocimiento de la representación con vistas, por ejemplo, a
poder cambiar ésta posteriormente, se puede hacer uso de los tipos privados
definiéndolos mediante la palabra reservada private:
Nótese que el valor de I no se puede dar pues no se conocen todavía los detalles de la
implementación, se declara como constante y se le asigna después un valor en la
parte privada.
declare use Números_complejos; C1, C2: TComplejo; R1, R2: Float; begin C1 :=
Construir_complejo (1.5, -6.0); C2 := C1 + I; R := Parte_real (C2) + 8.0; end;
-- ... private Pi: constant := 3.1416; type TComplejo is record R: Float; Theta: Float
range 0.0 .. 2*Pi; end recod; I: constant TComplejo := (1.0, 0.5*Pi); end
Números_complejos;
Operadores
declare
type Dia_Semana is
(Lunes, Martes, Miercoles, Jueves, Viernes, Sabado, Domingo);
subtype Dia_Laborable is Dia_Semana range Lunes .. Viernes;
Hoy : Dia_Semana := Obtener_Dia;
begin
Para los operadores lógicos existen versiones para minimizar las evaluaciones (short-
circuit). Es decir, se evalúa primero el operando de la izquierda y después, sólo si es
necesario para determinar el resultado, el de la derecha:
Instrucciones de control
Definición
bloque ::=
[ identificador : ]
[ declare
parte_declarativa ]
begin
sentencias
[ exception
manejador_de_excepción
{ manejador_de_excepción } ]
end [ identificador ] ;
Ejemplo
-- Supuestas X e Y declaradas con anterioridad de tipo Float:
declare
Temp: Float; -- Esta variable sólo es visible dentro del bloque.
begin -- Se intercambian 2 variables.
Temp := X;
X := Y;
Y := Temp;
end;
Definición
sentencia_selección ::=
if condición then secuencia_de_sentencias
[ { elsif condición then secuencia_de_sentencias } ]
[ else secuencia_de_sentencias ]
end if ;
begin
put("Escribe una frase"); --pedimos y recojemos texto
put (c);
n:=0; --inicializamos n a cero
cp:=' ';get(c); --si cp es espacio seguir leyendo
while c/='.' loop --mientras c sea diferente del PUNTO entrar en bucle if cp='L'and c='A'
then n:=n+1;end if; -- si cp es L y c es A incrementar n y finalizar el if
end comptar_LA;
Ejemplo
if Hoy = DOM then -- Si hoy es domingo.
Mañana := LUN;
elsif Hoy /= SAB then -- Si no es domingo ni sábado.
Laborable := True;
else -- Cualquier otro caso.
Mañana := TDía'Succ(Hoy);
end if;
[editar] Definición
sentencia_selección_por_casos ::=
case expresión is
alternativa_caso { alternativa_caso }
end case ;
alternativa_caso ::=
when elección { | elección } => secuencia_de_sentencias
elección ::= expresión_simple | rango_discreto | others
Ejemplo
case Hoy is
when MIE..VIE => Entrenar_duro; -- Rango.
when MAR | SAB => Entrenar_poco; -- Varias elecciones.
when DOM => Competir; -- Una elección.
when others => Descansar; -- Debe ser única y la última alternativa.
end case;
Bucles
Definición
sentencia_bucle_simple ::=
[ identificador_bucle : ] loop
secuencia_de_sentencias
end loop [ identificador_bucle ] ;
Ejemplo
Vida: loop -- El bucle dura indefinidamente.
Trabajar;
Comer;
Dormir;
end loop Vida;
Este bucle sólo se puede abandonar si alguno de los procedimientos levanta una
excepción.
El bucle simple a menudo se acompaña de una sentencia exit para abandonar el bucle
cuando se cumple una condición.
loop
Alimentar_Caldera;
Monitorizar_Sensor;
exit when Temperatura_Ideal;
end loop;
Definición
sentencia_bucle_iterativo ::=
[ identificador_bucle : ] for parámetros_for loop
secuencia_de_sentencias
end loop [ identificador_bucle ] ;
Ejemplo
for I in 1..N loop -- I se itera desde 1 hasta N.
V(I) := 0;
end loop;
Definición
sentencia_bucle_iterativo ::=
[ identificador_bucle : ] while condición loop
secuencia_de_sentencias
end loop [ identificador_bucle ] ;
Ejemplo
I := 1;
while I > N loop -- Se hace el bucle mientras se cumpla la condición.
V(I) := 0;
I := I + 1;
end loop;
Sentencia goto
Se especifica una etiqueta entre los símbolos << y >>, por ejemplo, <<Salto>>.
Se realiza el salto a dicha etiqueta con la sentencia goto Salto; que transferiría el
control a la siguiente sentencia después de la etiqueta.
Sentencia exit
Sentencia return
Sentencia abort
Se utiliza sólo para tareas. Implica la terminación incondicional de las tareas que se
especifiquen. Su notación sintáctica es:
Cadena de caracteres
Ejemplo:
cadena: string(1..20);
cad: string(1..5);
OPERADORES Y FUNCIONES:
PROCEDIMIENTOS:
with Ada.Strings.Bounded;
...
procedure .... is
Ejemplo:
package pCad20 is new Generic_Bounded_Length(20);
use pCad20;
laCad: Bounded_String;
...
laCad:= To_Bounded_String("Jose Luis");
Concatenación: &
Indexación de elementos:
Ejemplo:
Ejemplo:
Concepto de
clase
metodos Astract,final
Public
sincronozable
Cadena de
caracteres
operadores
2_ Visual Basic
Visual basic es un programa basado en objetos, pero no orientado a ojetos, la
diferencia esta en que visual basic utiliza objetos con propiedades y metodos pero
carece de los mecanismos de herencia y polimorfismo propios de los verdaderos
lenguajes orientados a objetos como java y c++.
La herencia permite escribir y depurar una clase una vez, y después volver a utilizar
ese código una y otra vez como base de nuevas clases. La herencia también permite
utilizar el polimorfismo basado en la herencia, la posibilidad de definir clases que
pueden utilizarse de forma intercambiable mediante código cliente en tiempo de
ejecución, pero con funcionalidad diferente, incluyo con métodos o propiedades
denominados de manera idéntica.
Compilador
El compilador de Visual Basic x.0 genera ejecutables que requieren una DLL para que
funcionen, en algunos casos llamada MSVBVMxy.DLL (acrónimo de "MicroSoft Visual
Basic Virtual Machine x.y", siendo x.y la versión) y en otros VBRUNXXX.DLL ("Visual
Basic Runtime X.XX"), que provee todas las funciones implementadas en el lenguaje.
Además existen un gran número de bibliotecas (DLL) que facilitan el acceso a muchas
funciones del sistema operativo y la integración con otras aplicaciones. Sin embargo
esto sólo es una limitación en sistemas obsoletos, ya que las bibliotecas necesarias, la
mayoria de componentes y controles adicionales inclusive, para ejecutar programas en
Visual Basic 5.0 y 6.0 vienen de serie en todas las versiones de Windows desde
Windows XP.
Entorno de desarrollo
• El espacio de trabajo donde se muestran todas las ventanas del proyecto, las
vistas de codigo de modulos y objetos, y las vistas de diseño de formularios y
componentes.
• El Cuadro de herramientas (por defecto a la izquierda) contiene los controles
con los que componer las ventanas de nuestra aplicacion. Por defecto
disponemos los controles básicos:
o (PictureBox) Caja de Imagen
o (Label) Etiqueta
o (TextBox) Caja de texto
o (Frame) Marco
o (CommandButton) Boton de comando
o (CheckBox) Casilla de verificación
o (OptionButton) Boton de opción
o (ComboBox) Lista desplegable
o (ListBox) Lista
o (HScrollBar) Barra de desplazamiento horizontal
o (VScrollBar) Barra de desplazamiento vertical
o (Timer) Temporizador
o (DriveListBox) Lista de unidades de disco
o (DirListBox) Lista de directorios
o (FileListBox) Lista de archivos
o (Shape) Figura
o (Line) Linea
o (Image) Imagen
o (Data) Conexion a origen de datos
o (OLE) Contenedor de documentos embebidos compatibles con Object
Linking and Embedding
Se pueden agregar todo tipo de controles de terceros, una gran cantidad de ellos de
serie con la instalacion de Visual Basic 6.0, que vienen embebidos dentro de archivos
de extension *.OCX.
Características :
• Es un lenguaje RAD.
• Posee una curva de aprendizaje muy rápida.
• Integra el diseño e implementación de formularios de Windows.
• Permite usar con suma facilidad la plataforma de los sistemas Windows dado
que tiene acceso practicamente total a la API de Windows incluidas librerías
actuales.
• El código en Visual Basic es fácilmente migrable a otros lenguajes.
• Es un lenguaje muy extendido por lo que resulta fácil encontrar información,
documentación y fuentes para los proyectos.
• Fácilmente extensible mediante librerías DLL y componentes ActiveX de otros
lenguajes.
• Posibilidad de añadir soporte para ejecución de scripts, VBScript o JScript, en
las aplicaciones mediante Microsoft Script Control.
• Acceso a la API multimedia de DirectX (versiones 7 y 8). También esta
disponible, de forma no oficial, un componente para trabajar con OpenGL 1.1:
VBOpenGL type library
• Existe una versión integrada en las aplicaciones de Office, versiones tanto
Windows como Mac, que permite programar macros para extender y
automatizar funcionalidades en documentos como por ejemplo una hoja de
calculo de EXCEL o una base de datos ACCESS (VBA)
• Es un entorno perfecto para realizar pequeños prototipos rápidos de ideas.
programacion estructurada
Programación estructurada
funcionamiento
SECUENCIA.
SELECCIÓN.
ITERACIÓN.
1.- SECUENCIA
Las cajas A y B pueden ser definidas para ejecutar desde una simple instrucción hasta
un módulo o programa completo, siempre y cuando que estos también sean
programas apropiados.
2.- SELECCIÓN
3.- ITERACIÓN
programacion funcional
• Programación declarativa
• Definición y evaluación de funciones
• Uso de la recursión
• Funciones como datos primitivos
(define (cuadrado x)
(* x x))
Estamos definiendo una función con un argumento formal (x) que tiene como cuerpo la
expresión (* x x) y le estamos dando el nombre de cuadrado. Después evaluamos una
expresión en la que llamamos a la función recién definida y a la función primitiva '+'.
Uso de la recursión
Otro elemento común a todos los lenguajes funcionales es el uso de la recursión para
expresar funciones que en otros lenguajes se expresan con iteraciones. Muchas veces
es más sencillo y natural utilizar una recursión en la definición de una función.
Veremos hoy algún ejemplo sencillo. En clases posteriores analizaremos más a fondo
la recursión en Scheme.
Factorial
(define (factorial x)
(if (= x 0)
1
(* x (factorial (- x 1)))))
>(factorial 8)
40320
>(factorial 30)
265252859812191058636308480000000
Sumatorio
En Scheme:
Por último un ejemplo utilizando símbolos y las funciones que vimos en una clase
anterior empty?, first, bf y equal?.
Otra característica fundamental de los lenguajes funcionales es que las funciones son
consideradas un tipo de dato primitivo.
Por ejemplo, los números, los caracteres o las cadenas son datos primitivos en la
mayor parte de lenguajes de programación. Sin embargo, resulta poco frecuente que
podamos hacer todas estas cosas con una función o un procedimiento. Es una de las
características más sorprendentes de los lenguajes funcionales:
(define suma +)
suma
>(suma 1 2 3)
6
(define + -)
(+ 4 2)
2
(define + suma)
Podemos comprobar en el ejemplo que los símbolos 'suma', '+' o '-' no son más que
identificadores ligados a procedimientos.
En Scheme cuando definimos una función con un nombre, la relación entre la función
y el nombre es la misma que la relación entre una variable y un valor. El nombre de la
función es el identificador que está ligado al procedimiento.
Por ejemplo, podemos defnir la siguiente función aplicar que toma como argumento
una función f 2 argumentos y realiza la llamada a f con los 2 argumentos:
(define (aplicar f x y)
(f x y))
> (aplicar + 2 3)
5
> (aplicar * 2 3)
6
(aplicar word 'hola 'adios)
holaadios
En el siguiente ejemplo definimos una función que toma dos procedimientos unarios
(de un argumento) f y g y los aplica a un número:
(define (aplicar-2 f g x)
(f (g x)))
(define (5+ x)
(+ 5 x))
(define (doble x)
(* 2 x))
> (aplicar-2 5+ doble 8)
21
Vamos a definir una función que devuelve otra función. La siguiente función hacer-
suma1 define en su interior la función suma1 y la devuelve.
(define (hacer-suma1)
(define (suma1 x)
(+ x 1))
suma1)
(define f (hacer-suma1))
> (f 3)
4
(define (hacer-sumak k)
(define (sumak x)
(+ x k))
sumak)
(define g (hacer-sumak 8))
> (g 5)
13
Por último, una función puede ser parte de una estructura de datos mayor.
Veamos un ejemplo que a primera vista puede parecer algo complicado (ya que
mezclamos recursión y funciones como tipos de datos primitivos). Se trata de construir
una función que recorra una lista de funciones unarias (se aplican a un único
argumento) y las vaya aplicando a un argumento.
Vamos a verlo paso a paso. Vamos a ver en primer lugar qué es eso de una lista de
funciones unarias.
(define (2+ x)
(+ 2 x))
(define (10* x)
(* 10 x))
(define (cuadrado x)
(* x x))
La lista lista-funcs es una lista que contiene funciones (no identificadores). Vamos a
comprobarlo. Si miramos su primer elemento el intérprete nos dice lo siguiente:
>((car lista-funcs) 3)
9
Podemos ahora hacer la función aplica-funcs que recorre la lista de funciones y las
aplica a un número:
(define (aplica-funcs lista x)
(if (empty? (cdr lista))
((car lista) x)
((car lista) (aplica-funcs (cdr lista) x))))
Lambda en Scheme
(cuadrado 4)
(define cuatro 4)
(cuadrado cuatro)
Hemos dicho que las funciones son en Scheme tipos de datos primitivos. ¿Cumplen
entonces la propiedad anterior? ¿Es posible usar una función sin darle un nombre? La
respuesta es que sí, utilizando la forma especial lambda.
La forma especial lambda construye una función sin nombre y la devuelve como
resultado. Para definir una función son necesarios dos elementos: sus argumentos y
su cuerpo. Estos dos elementos son los que se definen a continuación de la palabra
lambda.
(lambda (x)
(* x x))
se define una función que tiene un único argumento (x) y que tiene como cuerpo la
expresión (* x x). Es la función cuadrado.
1. Podemos darle un nombre y obtener una función con nombre que después
podremos usar:
2. > (define cuadrado (lambda (x) (* x x)))
3. > (cuadrado 3)
4. 9
5. Pasarlo como argumento de otra función que admite otras funciones como
parámetro:
6. >(define (aplicar-2 f g x)
7. (f (g x)))
8.
9. >(define (suma-5 x)
10. (+ 5 x))
11.
12. >(aplicar-2 suma-5 (lambda (x) (* x x)) 3)
13. 14
14. Podemos evaluarlo inmediatamente poniendo un paréntesis de apertura
(recordad lo que comentamos la primera semana de clase de que los
paréntesis de apertura "(" servían para lanzar funciones o formas especiales
que hay a continuación de ellos):
15. >((lambda (x) (* x x)) 3)
16. 9