Professional Documents
Culture Documents
Lenguaje de Programación C
Lenguaje de Programación C ++
Lenguaje de Programación C#
LENGUAJE DE PROGRAMACION JAVA
Historia
Java se creó como una herramienta de programación para ser usada en un proyecto de set-
top-box en una pequeña operación denominada the Green Project en Sun Microsystems en
el año 1991. El equipo (Green Team), compuesto por trece personas y dirigido por James
Gosling, trabajó durante 18 meses en Sand Hill Road, en Menlo Park, en su desarrollo.
El lenguaje se denominó inicialmente Oak (por un roble que había fuera de la oficina de
Gosling), luego pasó a denominarse Green tras descubrir que Oak era ya una marca
comercial registrada para adaptadores de tarjetas gráficas, y finalmente se renombró
como Java.
Es frecuentada por algunos de los miembros del equipo. Pero no está claro si es un acrónimo
o no, aunque algunas fuentes señalan que podría tratarse de las iniciales de sus
diseñadores: James Gosling, Arthur Van Hoff, y Andy Bechtolsheim. Otros abogan por el
siguiente acrónimo, Just Another Vague Acronym ("sólo otro acrónimo ambiguo más"). La
hipótesis que más fuerza tiene es la de que Java debe su nombre a un tipo de café disponible
en la cafetería cercana; de ahí que el icono de Java sea una taza de café caliente. Un pequeño
signo que da fuerza a esta teoría es que los cuatro primeros bytes (el número mágico) de los
archivos.class que genera el compilador, son en hexadecimal, 0xCAFEBABE. A pesar de
todas estas teorías, el nombre fue sacado al parecer de una lista aleatoria de palabras.5
Los objetivos de Gosling eran implementar una máquina virtual y un lenguaje con una
estructura y sintaxis similar a C++. Entre junio y julio de 1994, tras una sesión maratoniana
de tres días entre John Gaga, James Gosling, Patrick Naughton, Wayne Rosing y Eric
Schmidt, el equipo reorientó la plataforma hacia la Web. Sintieron que la llegada del
navegador web Mosaic propiciaría que Internet se convirtiese en un medio interactivo, como
el que pensaban era la televisión por cable. Naughton creó entonces un prototipo de
navegador, WebRunner, que más tarde sería conocido como HotJava.
En 1994, se les hizo una demostración de HotJava y la plataforma Java a los ejecutivos de
Sun. Java 1.0a pudo descargarse por primera vez en 1994, pero hubo que esperar al 23 de
mayo de 1995, durante las conferencias de SunWorld, a que vieran la luz pública Java y
HotJava, el navegador Web. El acontecimiento fue anunciado por John Gage, el director
científico de Sun Microsystems. El acto estuvo acompañado por una pequeña sorpresa
adicional, el anuncio por parte de Marc Andreessen, vicepresidente ejecutivo de Netscape,
de que Java sería soportado en sus navegadores. El 9 de enero del año siguiente, 1996, Sun
fundó el grupo empresarial JavaSoft para que se encargase del desarrollo tecnológico.[1] Dos
semanas más tarde la primera versión de Java fue publicada.
La promesa inicial de Gosling era Write Once, Run Anywhere (Escríbelo una vez, ejecútalo
en cualquier lugar), proporcionando un lenguaje independiente de la plataforma y un entorno
de ejecución (la JVM) ligero y gratuito para las plataformas más populares, de forma que los
binarios (bytecode) de las aplicaciones Java pudiesen ejecutarse en cualquier plataforma.
El entorno de ejecución era relativamente seguro y los principales navegadores web pronto
incorporaron la posibilidad de ejecutar applets Java incrustadas en las páginas web.
Java ha experimentado numerosos cambios desde la versión primigenia, JDK 1.0, así como
un enorme incremento en el número de clases y paquetes que componen la biblioteca
estándar.6
Desde J2SE 1.4, la evolución del lenguaje ha sido regulada por el JCP (Java Community
Process), que usa Java Specification Requests (JSRs) para proponer y especificar cambios en
la plataforma Java. El lenguaje en sí mismo está especificado en la Java Language
Specification (JLS), o Especificación del Lenguaje Java. Los cambios en los JLS son
gestionados en JSR 901.
J2SE 1.2 (8 de diciembre de 1998) — Nombre clave Playground. Esta y las siguientes
versiones fueron recogidas bajo la denominación Java 2 y el nombre "J2SE" (Java 2
Platform, Standard Edition) reemplazó a JDK para distinguir la plataforma base de J2EE
(Java 2 Platform, Enterprise Edition) y J2ME (Java 2 Platform, Micro Edition). Otras
mejoras añadidas incluían: comunicado de prensa
la palabra reservada (keyword) strictfp
reflexión en la programación
la API gráfica ( Swing) fue integrada en las clases básicas
la máquina virtual (JVM) de Sun fue equipada con un compilador JIT (Just in Time)
por primera vez
Java Plug-in
Java IDL, una implementación de IDL (Lenguaje de Descripción de Interfaz) para la
interoperabilidad con CORBA
Colecciones (Collections)
J2SE 1.3 (8 de mayo de 2000) — Nombre clave Kestrel. Los cambios más notables
fueron: comunicado de prensa lista completa de cambios
la inclusión de la máquina virtual de HotSpot JVM (la JVM de HotSpot fue lanzada
inicialmente en abril de 1999, para la JVM de J2SE 1.2)
RMI fue cambiado para que se basara en CORBA
JavaSound
se incluyó el Java Naming and Directory Interface (JNDI) en el paquete de
bibliotecas principales (anteriormente disponible como una extensión)
Java Platform Debugger Architecture (JPDA)
J2SE 1.4 (6 de febrero de 2002) — Nombre clave Merlin. Este fue el primer lanzamiento
de la plataforma Java desarrollado bajo el Proceso de la Comunidad Java como JSR 59.
Los cambios más notables fueron: comunicado de prensalista completa de cambios
Palabra reservada assert (Especificado en JSR 41.)
Expresiones regulares modeladas al estilo de las expresiones regulares Perl
Encadenación de excepciones Permite a una excepción encapsular la excepción de
bajo nivel original.
non-blocking NIO (New Input/Output) (Especificado en JSR 51.)
Logging API (Specified in JSR 47.)
API I/O para la lectura y escritura de imágenes en formatos como JPEG o PNG
Parser XML integrado y procesador XSLT (JAXP) (Especificado en JSR 5 y JSR
63.)
Seguridad integrada y extensiones criptográficas (JCE, JSSE, JAAS)
Java Web Start incluido (El primer lanzamiento ocurrió en marzo de 2001 para J2SE
1.3) (Especificado en JSR 56.)
J2SE 5.0 (30 de septiembre de 2004) — Nombre clave: Tiger. (Originalmente numerado
1.5, esta notación aún es usada internamente.[2]) Desarrollado bajo JSR 176, Tiger
añadió un número significativo de nuevas características comunicado de prensa
Plantillas (genéricos) — provee conversión de tipos (type safety) en tiempo de
compilación para colecciones y elimina la necesidad de la mayoría de conversión de
tipos (type casting). (Especificado por JSR 14.)
Metadatos — también llamados anotaciones, permite a estructuras del lenguaje
como las clases o los métodos, ser etiquetados con datos adicionales, que puedan ser
procesados posteriormente por utilidades de proceso de metadatos. (Especificado
por JSR 175.)
Autoboxing/unboxing — Conversiones automáticas entre tipos primitivos (Como
los int ) y clases de envoltura primitivas (Como Integer). (Especificado por JSR
201.)
Enumeraciones — la palabra reservada enum crea una typesafe, lista ordenada de
valores (como Dia.LUNES , Dia.MARTES , etc.). Anteriormente, esto solo podía
ser llevado a cabo por constantes enteras o clases construidas manualmente (enum
pattern). (Especificado por JSR 201.)
Varargs (número de argumentos variable) — El último parámetro de un método
puede ser declarado con el nombre del tipo seguido por tres puntos (e.g. void
drawtext(String... lines) ). En la llamada al método, puede usarse cualquier número
de parámetros de ese tipo, que serán almacenados en un array para pasarlos al
método.
Bucle for mejorado — La sintaxis para el bucle for se ha extendido con una sintaxis
especial para iterar sobre cada miembro de un array o sobre cualquier clase que
implemente Iterable, como la clase estándar Collection, de la siguiente forma:
Java SE 7 — Nombre clave Dolphin. En el año 2006 aún se encontraba en las primeras
etapas de planificación. Su lanzamiento fue en julio de 2011.
Soporte para XML dentro del propio lenguaje.
Un nuevo concepto de superpaquete.
Soporte para closures.
Introducción de anotaciones estándar para detectar fallos en el software.
No oficiales:
NIO2.
Java Module System.
Java Kernel.
Nueva API para el manejo de Días y Fechas, la cual reemplazará las antiguas clases
Date y Calendar.
Posibilidad de operar con clases BigDecimal usando operandos.
A) ORIENTADA A OBJETOS
La primera característica, orientado a objetos (“OO”), se refiere a un método de
programación y al diseño del lenguaje. Aunque hay muchas interpretaciones para OO, una
primera idea es diseñar el software de forma que los distintos tipos de datos que usen estén
unidos a sus operaciones. Así, los datos y el código (funciones o métodos) se combinan en
entidades llamadas objetos. Un objeto puede verse como un paquete que contiene el
“comportamiento” (el código) y el “estado” (datos). El principio es separar aquello que
cambia de las cosas que permanecen inalterables. Frecuentemente, cambiar una estructura de
datos implica un cambio en el código que opera sobre los mismos, o viceversa. Esta
separación en objetos coherentes e independientes ofrece una base más estable para el diseño
de un sistema software. El objetivo es hacer que grandes proyectos sean fáciles de gestionar
y manejar, mejorando como consecuencia su calidad y reduciendo el número de proyectos
fallidos.
Otra de las grandes promesas de la programación orientada a objetos es la creación de
entidades más genéricas (objetos) que permitan la reutilización del software entre proyectos,
una de las premisas fundamentales de la Ingeniería del Software. Un objeto genérico
“cliente”, por ejemplo, debería en teoría tener el mismo conjunto de comportamiento en
diferentes proyectos, sobre todo cuando estos coinciden en cierta medida, algo que suele
suceder en las grandes organizaciones. En este sentido, los objetos podrían verse como piezas
reutilizables que pueden emplearse en múltiples proyectos distintos, posibilitando así a la
industria del software construir proyectos de envergadura empleando componentes ya
existentes y de comprobada calidad, conduciendo esto finalmente a una reducción drástica
del tiempo de desarrollo. Podemos usar como ejemplo de objeto el aluminio. Una vez
definidos datos (densidad, maleabilidad, etc.), y su “comportamiento” (soldar dos piezas,
etc.), el objeto “aluminio” puede ser reutilizado en el campo de la construcción, del
automóvil, de la aviación, etc.
La reutilización del software ha experimentado resultados dispares, encontrando dos
dificultades principales: el diseño de objetos realmente genéricos es pobremente
comprendido, y falta una metodología para la amplia comunicación de oportunidades de
reutilización. Algunas comunidades de “código abierto” (open source) quieren ayudar en este
problema dando medios a los desarrolladores para diseminar la información sobre el uso y
versatilidad de objetos reutilizables y bibliotecas de objetos.
B) Independencia de la plataforma
La segunda característica, la independencia de la plataforma, significa que programas escritos
en el lenguaje Java pueden ejecutarse igualmente en cualquier tipo de hardware. Este es el
significado de ser capaz de escribir un programa una vez y que pueda ejecutarse en cualquier
dispositivo, tal como reza el axioma de Java, "write once, run anywhere".
C) El recolector de basura
En Java el problema fugas de memoria se evita en gran medida gracias a la recolección de
basura (o automatic garbage collector). El programador determina cuándo se crean los objetos
y el entorno en tiempo de ejecución de Java (Java runtime) es el responsable de gestionar el
ciclo de vida de los objetos. El programa, u otros objetos, pueden tener localizado un objeto
mediante una referencia a éste. Cuando no quedan referencias a un objeto, el recolector de
basura de Java borra el objeto, liberando así la memoria que ocupaba previniendo posibles
fugas (ejemplo: un objeto creado y únicamente usado dentro de un método sólo tiene entidad
dentro de éste; al salir del método el objeto es eliminado). Aun así, es posible que se
produzcan fugas de memoria si el código almacena referencias a objetos que ya no son
necesarios; es decir, pueden aún ocurrir, pero en un nivel conceptual superior. En definitiva, el
recolector de basura de Java permite una fácil creación y eliminación de objetos y mayor
seguridad.
SINTAXIS DE JAVA
La sintaxis de Java se deriva en gran medida de C++. Pero a diferencia de éste, que combina
la sintaxis para programación genérica, estructurada y orientada a objetos, Java fue
construido desde el principio para ser completamente orientado a objetos. Todo en Java es
un objeto (salvo algunas excepciones), y todo en Java reside en alguna clase (recordemos que
una clase es un molde a partir del cual pueden crearse varios objetos).
A diferencia de C++, Java no tiene sobrecarga de operadores7 o herencia
múltiple para clases, aunque la herencia múltiple está disponible para interfaces.
Aplicaciones autónomas
Este ejemplo necesita una pequeña explicación.
Los servlets no son procesos independientes (como los CGI) y por tanto se ejecutan
dentro del mismo proceso que la JVM mejorando notablemente el rendimiento y
reduciendo la carga computacional y de memoria requeridas.
Programación
Expresiones
Las expresiones son un conjunto de elementos o tokens junto con literales que son evaluados
para devolver un resultado. Los tokens son elemento más pequeño de un programa que es
significativo, e interpretado o entendido por el compilador, en Java los tokens se dividen en
cinco categorías que son:
Identificadores: Son las representaciones que se les da a los nombres que se asignan a las
variables, clases, paquetes, métodos y constantes en el código de Java para que el compilador
los identifique y el programador pueda entenderlos. En Java los identificadores pueden
diferenciar entre mayúsculas o minúsculas por ser case sensitive, por lo que la variable cuyo
nombre sea “Mivariable”, no es igual a “mivariable”, ya que Java identifica estas como
variables diferentes por el case sensitive, también se puede utilizar números, o el signo “_”
para asignar un identificador.
Palabras claves: Son los identificadores reservados por java para cumplir con un objetivo
específico en el código y el compilador, se usan de forma limitada y en casos específicos.
Las palabras claves que usa Java son las siguientes:
Las palabras que se encuentran en negrilla, son palabras claves para Java aunque actualmente
no se utilicen en la versión de Java, pero se pretenden integrar en las siguientes versiones de
Java.
Literales y constantes: Los literales son sintaxis para asignar valores a una variable, es decir
el valor que puede tomar una variable, también es un valor constante que puede ser de tipo
numérico. Las constantes son variables que tienen un valor fijo y no puede ser modificado
en el trascurso de la ejecución del código, estas se declaran por medio de los modificadores
final y static.
Operadores: Son los que nos indican una evaluación que se aplica a un objeto o un dato,
sobre un identificador o constante. Un ejemplo de operadores puede ser la suma, resta o
multiplicación.
Separadores: Se utilizan para indicarle al compilador de Java donde se ubican los elementos
del código, los separadores que admite Java son: { },:;
También el compilador de Java identifica y elimina los comentarios, retornos de carros
espacios vacíos y de tabulación a la hora de compilar por lo que no son considerados parte
de un token.
Las expresiones pueden ser una combinación en secuencia de variables, operadores y
métodos. Las expresiones son utilizadas para realizar cálculos, para asignar valores a
variables, o para controlar la ejecución del flujo del programa.
Operadores
Son las expresiones de Java que tras realizar una operación devuelven un resultado. Según el
número de operandos que maneje un operador, puede ser de dos tipos: unario o binario.
Los operadores unarios son aquellos que solo necesitan un operando para devolver un valor.
Operador Descripción
- Cambio de signo
! Operador NOT
~ Complemento a 1
Los operadores binarios son aquellos que necesitan dos o más operandos para devolver un
valor.
Operadores Descripción
+ Concatenación de cadenas
11001011
~ 11001011 resultado 00110100
situacion
01001101
& 10011011
______________
00001001
| Or a nivel de bit, este operador realiza una operación OR en donde si alguno de los dos
números es 1 el resultado será 1, un ejemplo puede ser:
11001101
| 01011101
______________
11011101
^ XOR a nivel de bit, este operador realiza la operación XOR en donde si los dos números
son iguales el resultado será 0 de lo contrario será 1, un ejemplo puede ser:
00101001
^ 01101101
______________
01000100
01101110
01101110 << 1 = 11011100
Suma +-
Igualdad == !=
OR a nivel bit |
OR lógico ||
Condicional ?:
int numero1 = 3;
int numero2 = 4;
int resultado;
resultado = numero1 + numero2 * 3;
System.out.println (resultado); //esto imprime el valor de 15
Según la precedencia de los operadores, la multiplicación "*" tiene mayor prioridad que la
suma "+", por lo que primero se ejecuta la multiplicación y luego se realiza la suma.
int numero1 = 3;
int numero2 = 4;
int resultado;
resultado = (numero1 + numero2) * 3;
System.out.println (resultado); //esto imprime el valor de 21
En este caso el resultado cambia ya que primero se evalúan los parámetros que están dentro
del paréntesis y luego se evalúa el resto de parámetros. Una de las recomendaciones que da
Java para el desarrollo es el uso de los paréntesis en las operaciones con más de 3 operandos,
así de esta forma el código se hace más legible y se evitan errores al momento de compilar.
Sentencias
Las sentencias son una representación de una secuencia de acciones que se realizan en Java.
La clave fundamental de las sentencias es su punto final que indica que ha finalizado la
sentencia y puede continuar con la siguiente, el indicador utilizado es el signo de punto y
coma (;). En Java contamos con sentencias que pueden ser de asignación, de bucles, de salto
y condicionales. Las sentencias se conforman comúnmente por una instancia y un operador,
un ejemplo es la sentencia de asignación que se conforma por una instancia de una variable,
el signo de asignación y una expresión, un ejemplo es:
Las sentencias de asignación son aquellas en las que se asigna un valor a una variable o
constante. Las sentencias condicionales son las que expresan una condición para definir el
flujo de ejecución del programa, entre ellas tenemos if-else y switch. Las sentencias de bucles
se encargar de realizar una acción cierta cantidad de tiempo dado, o hasta que se cumpla con
una condición, entre ellas tenemos el while, do-while, y for. Las sentencias de salto llevan al
compilador a un punto específico del programa o hacia la siguiente sentencia de ejecución,
entre ellas tenemos break, continue, y return.
Conversión de tipos
En algunos casos suele ser necesario convertir un tipo de dato a otro, esto se le conoce como
conversión de tipos, modelado, o tipado, así de esta forma poder realizar las operaciones
necesarias sobre el valor que se desea convertir. Se debe tener en cuenta el tipo de dato que
se va a convertir, ya que si se convierte un dato que tenga una cantidad menor de bit al anterior
este tendrá perdida de información, un ejemplo de tipado puede ser un número long que se
desea convertir a int, el compilador eliminara los primeros 32bit del long para ajustarlo al int
ya que el int es de 32bit y el long de 64. Si la conversión se realiza a un tipo de datos de
menos bit a un tipo de datos con mayor bit, la conversión se realiza automáticamente llamada
conversión implícita, pero si se realiza de un tipo de datos con mayor bit a menor bit se tiene
que realizar una conversión explícita, la cual se realiza con un casting, al usar este método se
obliga a realizar la conversión por lo cual puede haber perdida de datos en la conversión.
Para realizar una conversión explícita se tiene que poner el tipo de dato que se desea realizar
la conversión entre paréntesis, luego el valor o la variable que se desea convertir. Un ejemplo
de conversión de tipo explícito puede ser:
La siguiente tabla muestra los tipos de datos que se pueden realizar una conversión implícita
desde el dato origen, hasta el dato destino que es el dato en el que se va a convertir.
float double
Los tipos de datos booleanos no pueden ser convertidos a otro tipo de datos, por ningún
método mencionado anteriormente. Otro tipo de conversión que no se encuentre en esta tabla
desde el origen al destino, tiene que realizarse por medio de una conversión explícita por
casting. Cuando se desea realizar una conversión de un tipo string como origen a otro tipo,
es necesario utilizar una función que se encarga de convertir el tipo de dato, la función
necesaria se compone de la variable que va almacenar el resultado, y dependiendo de la
variable se usa el parámetro que inicia con el tipo de dato a convertir, Integer, Byte, Short, o
Long, seguida de punto “. “, el cual indica que se cargarán los atributos del parámetro, en
donde cargaremos el parseInt si queremos convertir a interger o parseByte si queremos
convertir a byte, o dependiendo del tipo de dato, seguido de paréntesis en donde se agregara
el valor de string a convertir. Algunos ejemplos puede ser:
int numero1;
long numero2;
byte numero3;
String texto= “2013”;
numero1 = Integer.parseInt ( texto );
numero2 = Long.parseLong ( texto);
numero3 = Byte.parseByte ( texto );
esto suele ser usado para realizar una conversión de texto cuando se ingresan valores
numéricos por una entrada a java, la cual los detecta como string, así de esta forma puede
convertir el texto que se ingresa a un número para realizar operaciones, como una
calculadora.
General
Java no ha aportado capacidades estándares para aritmética en punto flotante. El
estándar IEEE 754 para “Estándar para Aritmética Binaria en Punto Flotante” apareció en
1985, y desde entonces es el estándar para la industria. Y aunque la aritmética flotante de
Java (cosa que cambió desde el 13 de noviembre de 2006, cuando se abrió el código fuente
y se adoptó la licencia GPL, aparte de la ya existente)[cita requerida] se basa en gran medida en
la norma del IEEE, no soporta aún algunas características. Más información al respecto puede
encontrarse en la sección final de enlaces externos.
El lenguaje
En un sentido estricto, Java no es un lenguaje absolutamente orientado a objetos, a
diferencia de, por ejemplo, Ruby o Smalltalk. Por motivos de eficiencia, Java ha relajado
en cierta medida el paradigma de orientación a objetos, y así por ejemplo, no todos los
valores son objetos.
El código Java puede ser a veces redundante en comparación con otros lenguajes. Esto
es en parte debido a las frecuentes declaraciones de tipos y conversiones de tipo manual
(casting). También se debe a que no se dispone de operadores sobrecargados, y a una
sintaxis relativamente simple. Sin embargo, J2SE 5.0 introduce elementos para tratar de
reducir la redundancia, como una nueva construcción para los bucles ‘’’foreach’’’.
A diferencia de C++, Java no dispone de operadores de sobrecarga definidos por el
usuario. Los diseñadores de Java tomaron esta decisión puesto que consideraban que,
bajo ciertas circunstancias, esta característica podía complicar la lectura y mantenimiento
de los programas.
Apariencia
La apariencia externa (el ‘‘‘look and feel’’’) de las aplicaciones GUI (Graphical User
Interface) escritas en Java usando la plataforma Swing difiere a menudo de la que muestran
aplicaciones nativas. Aunque el programador puede usar el juego de herramientas AWT
(Abstract Windowing Toolkit) que genera objetos gráficos de la plataforma nativa, el AWT
no es capaz de funciones gráficas avanzadas sin sacrificar la portabilidad entre plataformas;
ya que cada una tiene un conjunto de APIs distinto, especialmente para objetos gráficos de
alto nivel. Las herramientas de Swing, escritas completamente en Java, evitan este problema
construyendo los objetos gráficos a partir de los mecanismos de dibujo básicos que deben
estar disponibles en todas las plataformas. El inconveniente es el trabajo extra requerido para
conseguir la misma apariencia de la plataforma destino. Aunque esto es posible (usando
GTK+ y el Look-and-Feel de Windows), la mayoría de los usuarios no saben cómo cambiar
la apariencia que se proporciona por defecto por aquella que se adapta a la de la plataforma.
Rendimiento
El bytecode de Java puede ser interpretado en tiempo de ejecución por la máquina virtual, o
bien compilado al cargarse el programa, o durante la propia ejecución, para generar código
nativo que se ejecuta directamente sobre el hardware. Si es interpretado, será más lento que
usando el código máquina intrínseco de la plataforma destino. Si es compilado, durante la
carga inicial o la ejecución, la penalización está en el tiempo necesario para llevar a cabo la
compilación.
Algunas características del propio lenguaje conllevan una penalización en tiempo, aunque no
son únicas de Java. Algunas de ellas son el chequeo de los límites de arrays, chequeo en
tiempo de ejecución de tipos, y la indirección de funciones virtuales.
El uso de un recolector de basura para eliminar de forma automática aquellos objetos no
requeridos, añade una sobrecarga que puede afectar al rendimiento, o ser apenas apreciable,
dependiendo de la tecnología del recolector y de la aplicación en concreto. Las JVM
modernas usan recolectores de basura que gracias a rápidos algoritmos de manejo de
memoria, consiguen que algunas aplicaciones puedan ejecutarse más eficientemente.
El rendimiento entre un compilador JIT y los compiladores nativos puede ser parecido,
aunque la distinción no está clara en este punto. La compilación mediante el JIT puede
consumir un tiempo apreciable, un inconveniente principalmente para aplicaciones de corta
duración o con gran cantidad de código. Sin embargo, una vez compilado, el rendimiento del
programa puede ser comparable al que consiguen compiladores nativos de la plataforma
destino, inclusive en tareas numéricas. Aunque Java no permite la expansión manual de
llamadas a métodos, muchos compiladores JIT realizan esta optimización durante la carga de
la aplicación y pueden aprovechar información del entorno en tiempo de ejecución para llevar
a cabo transformaciones eficientes durante la propia ejecución de la aplicación. Esta
recompilación dinámica, como la que proporciona la máquina virtual HotSpot de Sun, puede
llegar a mejorar el resultado de compiladores estáticos tradicionales, gracias a los datos que
sólo están disponibles durante el tiempo de ejecución.
Java fue diseñado para ofrecer seguridad y portabilidad, y no ofrece acceso directo al
hardware de la arquitectura ni al espacio de direcciones. Java no soporta expansión de código
ensamblador, aunque las aplicaciones pueden acceder a características de bajo nivel usando
bibliotecas nativas (JNI, Java Native Interfaces).
CARACTERÍSTICAS DE JAVA:
1. Lenguaje Simple: “Se lo conoce como lenguaje simple porque viene de la misma estructura
de c y c++; ya que c++ fue un referente para la creación de java por eso utiliza determinadas
características de c++ y se han eliminado otras.”
2. Orientado a Objetos.
3. Multihilos: Java tiene una facilidad de cumplir varias funciones al mismo tiempo, gracias
a su función de multihilos ya que por cada hilo que el programa tenga se ejecutaran en tiempo
real muchas funciones al mismo tiempo.
Alto Rendimiento: Java es considerado de alto rendimiento por ser tan veloz en el momento
de correr los programas y por ahorrarse muchas líneas de código.
Recursos
JRE
El JRE (Java Runtime Environment, o Entorno en Tiempo de Ejecución de Java) es el
software necesario para ejecutar cualquier aplicación desarrollada para la plataforma Java.
El usuario final usa el JRE como parte de paquetes software o plugins (o conectores) en un
navegador Web. Sun ofrece también el SDK de Java 2, o JDK (Java Development Kit) en
cuyo seno reside el JRE, e incluye herramientas como el compilador de Java, Javadoc para
generar documentación o el depurador. Puede también obtenerse como un paquete
independiente, y puede considerarse como el entorno necesario para ejecutar una aplicación
Java, mientras que un desarrollador debe además contar con otras facilidades que ofrece el
JDK.
Componentes
Bibliotecas de Java, que son el resultado de compilar el código fuente desarrollado por
quien implementa la JRE, y que ofrecen apoyo para el desarrollo en Java. Algunos
ejemplos de estas bibliotecas son:
Las bibliotecas centrales, que incluyen:
Una colección de bibliotecas para implementar estructuras de datos como listas,
arrays, árboles y conjuntos.
Bibliotecas para análisis de XML.
Seguridad.
Bibliotecas de internacionalización y localización.
Bibliotecas de integración, que permiten la comunicación con sistemas externos.
Estas bibliotecas incluyen:
La API para acceso a bases de datos JDBC (Java DataBase Conectivity).
La interfaz JNDI (Java Naming and Directory Interface) para servicios de
directorio.
RMI (Remote Method Invocation) y CORBA para el desarrollo de aplicaciones
distribuidas.
Bibliotecas para la interfaz de usuario, que incluyen:
El conjunto de herramientas nativas AWT (Abstract Window Toolkit), que
ofrece componentes GUI (Graphical User Interface), mecanismos para usarlos y
manejar sus eventos asociados.
Las Bibliotecas de Swing, construidas sobre AWT pero ofrecen
implementaciones no nativas de los componentes de AWT.
APIs para la captura, procesamiento y reproducción de audio.
Una implementación dependiente de la plataforma en que se ejecuta de la máquina virtual
de Java (JVM), que es la encargada de la ejecución del código de las bibliotecas y las
aplicaciones externas.
Plugins o conectores que permiten ejecutar applets en los navegadores Web.
Java Web Start, para la distribución de aplicaciones Java a través de Internet.
Documentación y licencia.
API
Sun define tres plataformas en un intento por cubrir distintos entornos de aplicación. Así, ha
distribuido muchas de sus API(Application Program Interface) de forma que pertenezcan a
cada una de las plataformas:
Java ME (Java Platform, Micro Edition) o J2ME — orientada a entornos de limitados
recursos, como teléfonos móviles, PDAs (Personal Digital Assistant), etc.
Java SE (Java Platform, Standard Edition) o J2SE — para entornos de gama media y
estaciones de trabajo. Aquí se sitúa al usuario medio en un PC de escritorio.
Java EE (Java Platform, Enterprise Edition) o J2EE — orientada a entornos distribuidos
empresariales o de Internet.
Las clases en las API de Java se organizan en grupos disjuntos llamados paquetes. Cada
paquete contiene un conjunto de interfaces, clases y excepciones relacionadas. La
información sobre los paquetes que ofrece cada plataforma puede encontrarse en la
documentación de ésta.
El conjunto de las API es controlado por Sun Microsystems junto con otras entidades o
personas a través del programa JCP (Java Community Process). Las compañías o individuos
participantes del JCP pueden influir de forma activa en el diseño y desarrollo de las API, algo
que ha sido motivo de controversia.
Extensiones y arquitecturas relacionadas
Las extensiones10 de Java están en paquetes que cuelgan de la raíz javax: javax.* . No se
incluyen en la JDK o el JRE. Algunas de las extensiones y arquitecturas ligadas
estrechamente al lenguaje Java son:
Java EE (Java Platform, Enterprise Edition; antes J2EE) —para aplicaciones distribuidas
orientadas al entorno empresarial
“PROGRAMACIÓN C”
C es un lenguaje de
programación originalmente desarrollado
por Dennis Ritchie entre 1969 y 1972 en
los Laboratorios Bell,2 como evolución del
anterior lenguaje B, a su vez basado
en BCPL.
Al igual que B, es un lenguaje orientado a la
implementación de Sistemas operativos,
concretamente Unix. C es apreciado por la
eficiencia del código que produce y es el
lenguaje de programación más popular para
crear software de sistemas, aunque también se
utiliza para crear aplicaciones.
Se trata de un lenguaje de tipos de datos
estáticos, débilmente tipificado, de medio
nivel, ya que dispone de las estructuras típicas
de los lenguajes de alto nivel pero, a su vez,
dispone de construcciones del lenguaje que
permiten un control a muy bajo nivel. Los
compiladores suelen ofrecer extensiones al
lenguaje que posibilitan mezclar código
en ensamblador con código C o acceder
directamente a memoria o dispositivos
periféricos.
La primera estandarización del lenguaje C fue
en ANSI, con el estándar X3.159-1989. El
lenguaje que define este estándar fue
conocido vulgarmente como ANSI C.
Posteriormente, en 1990, fue ratificado como
estándar ISO(ISO/IEC 9899:1990). La
adopción de este estándar es muy amplia por
lo que, si los programas creados lo siguen, el
código es portable entre plataformas y/o
arquitecturas.
El lenguaje "C" se ha creado entre 1969 y 1973 en el AT & T Bell Labs, desarrollado
inicialmente para la implementación del sistema de Unix (que fue escrito originalmente en
PDP-7 Assembly, por Dennis Ritchie y Kenneth Thompson). Al final del 70 UNIX dejó el
laboratorio y fue puesto a disposición de las universidades, que por cierto fue un gran éxito
en el tiempo por lo que favorecio la popularidad del lenguaje de programación C. Vale la
pena mencionar que este fue uno de los primeros núcleos del sistema operativo que se
implementó en un lenguaje distinto al Assembly.
El lenguaje de programación C es también denominado lenguaje compilado. Esto significa
que una vez escrito un programa en C, este debe ser aprobado por un compilador, para poder
convertir su programa en un código ejecutable para que una computadora lo pueda ejecutar.
Un programa escrito en C tiene un formato legible para el hombre, mientras que el programa
ya compilado y convertido en código ejecutable es legible para el computador. Esto significa
que para escrbir y ejecutar un programa en C, es necesario contar o tener un compilador de
C y también un editor de texto plano, cualquier sistema operativo se puede utilizar para poder
programar en C, siempre y cuando tengas el compilador necesario. Si estás trabajando en un
computador con un sistema operativo Windows, tendrás que descargarte un compilador de C
libre o también puedes comprar un compilador comercial.
OBJETIVOS- FILOSOFIA
Uno de los objetivos de diseño del lenguaje C es que sólo sean necesarias unas pocas
instrucciones en lenguaje máquinapara traducir cada elemento del lenguaje, sin que haga falta
un soporte intenso en tiempo de ejecución. Es muy posible escribir C a bajo nivel de
abstracción; de hecho, C se usó como intermediario entre diferentes lenguajes.
En parte a causa de ser de relativamente bajo nivel y de tener un modesto conjunto de
características, se pueden desarrollar compiladores de C fácilmente. En consecuencia, el
lenguaje C está disponible en un amplio abanico de plataformas (más que cualquier otro
lenguaje). Además, a pesar de su naturaleza de bajo nivel, el lenguaje se desarrolló para
incentivar la programación independiente de la máquina. Un programa escrito cumpliendo
los estándares e intentando que sea portátil puede compilarse en muchos computadores.
C se desarrolló originalmente (conjuntamente con el sistema operativo Unix, con el que ha
estado asociado mucho tiempo) por programadores para programadores. Sin embargo, ha
alcanzado una popularidad enorme, y se ha usado en contextos muy alejados de
la programación de software de sistema, para la que se diseñó originalmente.
Características
Propiedades
Núcleo del lenguaje simple, con funcionalidades añadidas importantes, como funciones
matemáticas y de manejo de archivos, proporcionadas por bibliotecas.
Es un lenguaje muy flexible que permite programar con múltiples estilos. Uno de los más
empleados es el estructurado "no llevado al extremo" (permitiendo ciertas licencias de
ruptura).
Un sistema de tipos que impide operaciones sin sentido.
Usa un lenguaje de preprocesado, el preprocesador de C, para tareas como definir macros e
incluir múltiples archivos de código fuente.
Acceso a memoria de bajo nivel mediante el uso de punteros.
Interrupciones al procesador con uniones.
Un conjunto reducido de palabras clave.
Por defecto, el paso de parámetros a una función se realiza por valor. El paso por referencia
se consigue pasando explícitamente a las funciones las direcciones de memoria de dichos
parámetros.
Punteros a funciones y variables estáticas, que permiten una forma rudimentaria
de encapsulado y polimorfismo.
Tipos de datos agregados (struct) que permiten que datos relacionados (como un empleado,
que tiene un id, un nombre y un salario) se combinen y se manipulen como un todo (en una
única variable "empleado").
Carencias
Recolección de basura nativa, sin embargo se encuentran a tal efecto bibliotecas como la
"libgc" desarrollada por Sun Microsystems, o el Recolector de basura de Boehm.
Soporte para programación orientada a objetos, aunque la implementación original de C++
fue un preprocesador que traducía código fuente de C++ a C. Véase también la
librería GObject.
Funciones anidadas, aunque GCC tiene esta característica como extensión.
Soporte nativo para programación multihilo. Disponible usando librerías como libpthread.
Aunque la lista de las características útiles de las que carece C es larga, este factor ha sido
importante para su aceptación, porque escribir rápidamente nuevos compiladores para
nuevas plataformas, mantiene lo que realmente hace el programa bajo el control directo del
programador, y permite implementar la solución más natural para cada plataforma. Ésta es
la causa de que a menudo C sea más eficiente que otros lenguajes. Típicamente, sólo la
programación cuidadosa en lenguaje ensamblador produce un código más rápido, pues da
control total sobre la máquina, aunque los avances en los compiladores de C y la complejidad
creciente de los microprocesadores modernos han reducido gradualmente esta diferencia.
En algunos casos, una característica inexistente puede aproximarse. Por ejemplo, la
implementación original de C++ consistía en un preprocesador que traducía código fuente
C++ a C. La mayoría de las funciones orientadas a objetos incluyen un puntero especial, que
normalmente recibe el nombre "this", que se refiere al objeto al que pertenece la función.
Mediante el paso de este puntero como un argumento de función, esta funcionalidad puede
desempeñarse en C. Por ejemplo, en C++ se puede escribir:
stack.push(val);
Mientras que en C se podría escribir:
push(stack, val);
Donde el argumento stack es un puntero a una struct equivalente al puntero this de C++, que
es un puntero a un objeto.
Ventajas[
Lenguaje muy eficiente puesto que es posible utilizar sus características de bajo nivel para
realizar implementaciones óptimas.
A pesar de su bajo nivel es el lenguaje más portado en existencia,
habiendo compiladores para casi todos los sistemas conocidos.
Proporciona facilidades para realizar programas modulares y/o utilizar código o bibliotecas
existentes.
Inconvenientes
El mayor problema que presenta el lenguaje C frente a los lenguajes de tipo de dato dinámico
es la gran diferencia en velocidad de desarrollo: es más lento programar en C, sobre todo
para el principiante. La razón estriba en que el compilador de C se limita a traducir código
sin apenas añadir nada. La gestión de la memoria es un ejemplo clásico: en C el programador
ha de reservar y liberar la memoria explícitamente. En otros lenguajes (como BASIC, Matlab
o C#) la memoria es gestionada de forma transparente para el programador. Esto alivia la
carga de trabajo humano y en muchas ocasiones evita errores, aunque también supone mayor
carga de trabajo para el procesador.
El mantenimiento en algunos casos puede ser más difícil y costoso que con ciertos lenguajes
de más alto nivel. El código en C se presta a sentencias cortas y enrevesadas de difícil
interpretación[cita requerida].
Cabe destacar el contexto y época en la que fue desarrollado C. En aquellos tiempos existían
muy pocos programadores, los cuales, a su vez, eran prácticamente todos expertos en el área.
De esta manera, se asumía que los programadores eran conscientes de sus trabajos y capaces
de manejar perfectamente el lenguaje. Por esta razón es muy importante que los recién
iniciados adopten buenas prácticas a la hora de escribir en C y manejar la memoria, como
por ejemplo un uso intensivo de indentación y conocer a fondo todo lo que implica el manejo
de punteros y direcciones de memoria.
Historia
Desarrollo inicial
Ken Thompson (izquierda) con Dennis Ritchie (derecha, el inventor del lenguaje de
programación C)
El desarrollo inicial de C se llevó a cabo en los Laboratorios Bell de AT&T entre 1969 y
1973; según Dennis Ritchie, el periodo más creativo tuvo lugar en 1972. Se le dio el nombre
"C" porque muchas de sus características fueron tomadas de un lenguaje anterior llamado
"B".
Hay muchas leyendas acerca del origen de C y el sistema operativo con el que está
íntimamente relacionado, Unix. Algunas de ellas son:
El desarrollo de C fue el resultado del deseo de los programadores de jugar con Space Travel.
Habían estado jugando en el mainframe de su compañía, pero debido a su poca capacidad de
proceso y al tener que soportar 100 usuarios, Ken Thompson y Dennis Ritchie no tenían
suficiente control sobre la nave para evitar colisiones con los asteroides, por ese motivo
decidieron portar el juego a un PDP-7 de la oficina que no se utilizaba; pero esa máquina no
tenía sistema operativo, así que decidieron escribir uno. Finalmente decidieron portar el
sistema operativo del PDP-11 que había en su oficina, pero era muy costoso, pues todo el
código estaba escrito en lenguaje ensamblador. Entonces decidieron usar un lenguaje de alto
nivel y portátil para que el sistema operativo se pudiera portar fácilmente de un ordenador a
otro, consideraron usar B pero carecía de las funcionalidades necesarias para aprovechar
algunas características avanzadas del PDP-11 entonces empezaron a crear un nuevo lenguaje,
C.
La justificación para obtener el ordenador original que se usó para desarrollar Unix fue crear
un sistema que automatizase el archivo de patentes. La versión original de Unix se desarrolló
en lenguaje ensamblador. Más tarde, el lenguaje C se desarrolló para poder reescribir el
sistema operativo.
En 1973, el lenguaje C se había vuelto tan potente que la mayor parte del kernel Unix,
originalmente escrito en el lenguaje ensamblador PDP-11/20, fue reescrita en C. Éste fue uno
de los primeros núcleos de sistema operativo implementados en un lenguaje distinto al
ensamblador. (Algunos casos anteriores son el sistema Multics, escrito en PL/I, y Master
Control Programpara el B5000 de Burroughs, escrito en ALGOL en 1961).
El C de Kernighan y Ritchie
En 1978, Ritchie y Brian Kernighan publicaron la primera edición de El lenguaje de
programación C, también conocido como La biblia de C. Este libro fue durante años
la especificación informal del lenguaje. El lenguaje descrito en este libro recibe
habitualmente el nombre de "el C de Kernighan y Ritchie" o simplemente "K&R C" (La
segunda edición del libro cubre el estándar ANSI C, descrito más abajo).
Kernighan y Ritchie introdujeron las siguientes características al lenguaje:
El tipo de datos struct.
El tipo de datos long int.
El tipo de datos unsigned int.
Los operadores =+ y =- fueron sustituidos por += y -= para eliminar la ambigüedad
sintáctica de expresiones como i=-10, que se podría interpretar bien como i =- 10 o bien
como i = -10.
El C de Kernighan y Ritchie es el subconjunto más básico del lenguaje que un compilador
debe de soportar. Durante muchos años, incluso tras la introducción del ANSI C, fue
considerado "el mínimo común denominador" en el que los programadores debían programar
cuando deseaban que sus programas fueran transportables, pues no todos los compiladores
soportaban completamente ANSI, y el código razonablemente bien escrito en K&R C es
también código ANSI C válido.
En las primeras versiones del lenguaje, la definición de funciones se hacía mediante un
'prototipo de función' (function prototype), el cual indicaba al compilador el tipo de retorno
de la función. Aunque este método tiene una gran desventaja respecto al nuevo, debido a que
no comprueba el número ni el tipo en la lista de argumentos; en otras palabras, es mucho más
fácil cometer errores al hacer una llamada a una función con argumentos incorrectos.
Ejemplo del "viejo estilo":
int power(); /* Podria haberse omitido (*) */
power()
int a, b;
{
int n;
for (n = 1; b > 0; --b)
n *= a;
return n;
}
Ejemplo de la nueva definición:
int power(int a, int b) {
int n;
for (n = 1; b > 0; --b)
n *= a;
return n;
}
(*) Por defecto, el tipo de retorno en C es int, por lo que la declaración entera int
power(); podría haberse omitido.
En los años siguientes a la publicación del C de Kernighan y Ritchie, se añadieron al lenguaje
muchas características no oficiales, que estaba soportadas por los compiladores de AT&T,
entre otros. Algunas de estas características eran:
Funciones void y el tipo de datos void *.
Funciones que retornaban tipos de datos struct o union (en lugar de punteros).
Asignación de tipos de datos struct.
Calificador const, que hace que un objeto sea de sólo lectura.
Una biblioteca estándar, que incorporaba la mayoría de las funcionalidades implementadas
por varios desarrolladores de compiladores.
Enumeraciones.
ANSI C e ISO C
A finales de la década de 1970, C empezó a sustituir a BASIC como lenguaje de
programación de microcomputadores predominante. Durante la década de 1980 se empezó a
usar en los IBM PC, lo que incrementó su popularidad significativamente. Al mismo
tiempo, Bjarne Stroustrup empezó a trabajar con algunos compañeros de Bell Labs para
añadir funcionalidades de programación orientada a objetos a C. El lenguaje que crearon,
llamado C++, es hoy en día el lenguaje de programación de aplicaciones más común en el
sistema operativo Microsoft Windows; mientras que C sigue siendo más popular en el
entorno Unix. Otro lenguaje que se desarrolló en esa época, Objective C, también añadió
características de programación orientada a objetos a C. Aunque hoy en día no es tan popular
como C++, se usa para desarrollar aplicaciones Cocoa para Mac OS X.
En 1983, el Instituto Nacional Estadounidense de Estándares (ANSI) organizó un comité,
X3j11, para establecer una especificación estándar de C. Tras un proceso largo y arduo, se
completó el estándar en 1989 y se ratificó como el "Lenguaje de Programación C" ANSI
X3.159-1989. Esta versión del lenguaje se conoce a menudo como ANSI C, o a veces como
C89 (para distinguirla de C99).
En 1990, el estándar ANSI (con algunas modificaciones menores) fue adoptado por
la Organización Internacional para la Estandarización (ISO) en el estándar ISO/IEC
9899:1990. Esta versión se conoce a veces como C90. No obstante, "C89" y "C90" se refieren
en esencia al mismo lenguaje.
Uno de los objetivos del proceso de estandarización del ANSI C fue producir una extensión
al C de Kernighan y Ritchie, incorporando muchas funcionalidades no oficiales. Sin
embargo, el comité de estandarización incluyó también muchas funcionalidades nuevas,
como prototipos de función, y un preprocesador mejorado. También se cambió la sintaxis de
la declaración de parámetros para hacerla semejante a la empleada habitualmente en C++:
main(argc, argv)
int argc;
char **argv;
{
...
}
pasó a ser
int main(int argc, char *argv[]) {
...
}
ANSI C está soportado hoy en día por casi la totalidad de los compiladores. La mayoría del
código C que se escribe actualmente está basado en ANSI C. Cualquier programa
escrito sólo en C estándar sin código que dependa de un hardware determinado funciona
correctamente en cualquier plataforma que disponga de una implementación de C
compatible. Sin embargo, muchos programas han sido escritos de forma que sólo pueden
compilarse en una cierta plataforma, o con un compilador concreto, esto puede ser debido a
diversos motivos:
La utilización de bibliotecas no estándar, como interfaces gráficas de usuario.
El uso de compiladores que no cumplen las especificaciones del estándar.
El uso de tipos de datos suponiendo que tendrán el mismo tamaño u orden de los bits en todas
las plataformas.
La macro __STDC__ puede usarse para dividir el código en secciones ANSI y K&R para el
compilador.
# if __STDC__
extern int getopt(int, char * const *, const char *);
# else
extern int getopt();
# endif
Algunos programadores recomiendan usar "#if __STDC__", como en el ejemplo, en lugar
de "#ifdef __STDC__" porque algunos compiladores le asignan el valor cero a __STDC__
para indicar que no son compatibles con ANSI.
En el siguiente ejemplo, el programa pide al usuario que introduzca un número. El programa
dividirá dicho número entre 2 e imprimirá el resultado mientras que este sea par, y terminará
cuando el número sea impar:
#include <stdio.h>
int main(void) {
int numero;
fputs("Introduzca un numero entero par: ", stdout);
scanf("%d", &numero);
if (!numero) {
fputs("Error: numero no valido.\n", stderr);
return -1;
}
int i = 1;
while (numero%2 == 0) {
printf ("%.3d| %d/2 =", i++, numero);
numero /=2;
printf("%d\n", numero);
}
int main(void) {
printf("Hola Mundo\n");
return 0;
}
El siguiente escribe "Hola Mundo" en C89
/* comentarios con '//' no permitidos en C89, sí en C99 */
# include <stdio.h> /* necesario para utilizar printf */
Ejemplos
A continuación se cita un programa de ejemplo Hola mundo escrito en C++:
/* Esta cabecera permite usar los objetos que encapsulan los descriptores stdout
y stdin: cout(<<) y cin(>>)*/
#include <iostream>
int main()
{
cout << "Hola mundo" << endl;
return 0;
}
Al usar la directiva #include se le dice al compilador que busque e interprete todos los
elementos definidos en el archivo que acompaña la directiva (en este caso, iostream ). Para
evitar sobrescribir los elementos ya definidos al ponerles igual nombre, se crearon los
espacios de nombres o namespace del singular en inglés. En este caso hay un espacio de
nombres llamado std , que es donde se incluyen las definiciones de todas las funciones y
clases que conforman la biblioteca estándar de C++. Al incluir la sentencia using namespace
std le estamos diciendo al compilador que usaremos el espacio de nombres std por lo que
no tendremos que incluirlo cuando usemos elementos de este espacio de nombres, como
pueden ser los objetos cout y cin , que representan el flujo de salida estándar (típicamente la
pantalla o una ventana de texto) y el flujo de entrada estándar (típicamente el teclado).
La definición de funciones es igual que en C, salvo por la característica de que si main no
va a recoger argumentos, no tenemos por qué ponérselos, a diferencia de C, donde había que
ponerlos explícitamente, aunque no se fueran a usar. Queda solo comentar que el
símbolo << se conoce como operador de inserción, y grosso modo está enviando a cout lo
que queremos mostrar por pantalla para que lo pinte, en este caso la cadena "Hola mundo" .
El mismo operador << se puede usar varias veces en la misma sentencia, de forma que
gracias a esta característica podremos concatenar el objeto endl al final, cuyo resultado será
imprimir un retorno de línea.
Tipos de datos
C++ tiene los siguientes tipos fundamentales:
strcpy - wstrcpy
std::string - std::wstring
std::cout - std::wcout
Cabe resaltar que en C se define wchar_t como:
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 *memoria;
Indica que memoria es un puntero a alguna parte, donde se guarda información de algún
tipo. El programador es responsable de definir estos "algún", eliminando toda ambigüedad.
Una ventaja de la declaración "void *" es que puede representar a la vez varios tipos de datos,
dependiendo de la operación de cast escogida. La memoria que hemos apuntado en alguna
parte, en el ejemplo anterior, bien podría almacenar un entero, un flotante, una cadena de
texto o un programa, o combinaciones de estos. Es responsabilidad del programador recordar
qué tipo de datos hay y garantizar el acceso adecuado.
La palabra "NULL"
Además de los valores que pueden tomar los tipos anteriormente mencionados, existe un
valor llamado NULL, sea el caso numérico para los enteros, carácter para el tipo char, cadena
de texto para el tipo string, etc. El valor NULL, expresa, por lo regular, la representación de
una Macro, asignada al valor "0".
Tenemos entonces que:
El valor de las variables anteriores nos daría 0. A diferencia de la variable "caracter", que nos
daría el equivalente a NULL, '\0', para caracteres.
Principios
Todo programa en C++ debe tener la función principal 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()
{}
La función principal del código fuente main debe tener uno de los siguientes prototipos:
int main()
int main(int argc, char** argv)
Aunque no es estándar algunas implementaciones permiten
int main(int argc, char** argv, char** env)
La primera es la forma por omisión de un programa que no recibe parámetros ni argumentos.
La segunda forma tiene dos parámetros: argc, un número que describe el número de
argumentos del programa (incluyendo el nombre del programa mismo), y argv, un puntero a
un array de punteros, de argc elementos, donde el elemento argv[i] representa el i-ésimo
argumento entregado al programa. En el tercer caso se añade la posibilidad de poder acceder
a las variables de entorno de ejecución de la misma forma que se accede a los argumentos
del programa, pero reflejados sobre la variable env.
El tipo de retorno de main es un valor entero 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_FAILURE, definidas en el archivo cstdlib), 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. Identidad, que lo diferencia de otros objetos (Nombre que llevará la clase a la que
pertenece dicho objeto).
2. Métodos o funciones miembro
3. 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.
Este es otro ejemplo de una clase:
class Punto
{
//por omisión, los miembros son 'private' para que solo 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
Son unos métodos especiales que se ejecutan automáticamente al crear un objeto de la clase.
En su declaración no se especifica el tipo de dato que devuelven, y poseen el mismo nombre
que la clase a la que pertenecen. Al igual que otros métodos, puede haber varios constructores
sobrecargados, aunque no pueden existir constructores virtuales.
Como característica especial a la hora de implementar un constructor, justo después de la
declaración de los parámetros, se encuentra lo que se llama "lista de inicializadores". Su
objetivo es llamar a los constructores de los atributos que conforman el objeto a construir.
Cabe destacar que no es necesario declarar un constructor al igual que un destructor, pues el
compilador lo puede hacer, aunque no es la mejor forma de programar.
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:
// Constructor
Punto() : x(0), y(0){ // Inicializamos las variables "x" e "y"
}
};
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
getchar(); // le indicamos al programa que espere al buffer de entrada (detenerse)
return 0;
}
Si compilamos y ejecutamos el anterior programa, obtenemos una salida que debe ser similar
a la siguiente:
Coordenada X: 0 Coordenada Y: 0
Existen varios tipos de constructores en C++:
int main() {
Punto *unPunto = new Punto(); //esto llama al constructor que se describe más arriba
delete unPunto; //no hay que olvidarse de liberar la memoria ocupada por el
objeto(ver la sección destructores, más abajo)
return 0;
}
Además, con el operador new[] se pueden crear arrays (colecciones o listas ordenadas) de
tamaño dinámico:
Destructores
Los destructores son funciones miembro especiales llamadas automáticamente en la
ejecución del programa, y por tanto no tienen por qué ser llamadas explícitamente por el
programador. Sus principales cometidos son:
Liberar los recursos computacionales que el objeto de dicha clase haya adquirido en
tiempo de ejecución al expirar este.
Quitar los vínculos que pudiesen tener otros recursos u objetos con este.
Los destructores son invocados automáticamente al alcanzar el flujo del programa el fin del
ámbito en el que está declarado el objeto. El único caso en el que se debe invocar
explícitamente al destructor de un objeto, es cuando este fue creado mediante el operador
new, es decir, que este vive en memoria heap, y no en la pila de ejecución del programa. La
invocación del destructor de un objeto que vive en heap se realiza a través del operador delete
o delete[] para arrays. Ejemplo:
int main() {
int *unEntero = new int(12); //asignamos un entero en memoria heap con el valor 12
int *arrayDeEnteros = new int[25]; //asignamos memoria para 25 enteros(no están
inicializados)
delete unEntero; //liberamos la memoria que ocupaba unEntero
delete[] arrayDeEnteros; //liberamos la memoria ocupada por arrayDeEnteros
return 0;
}
Si no se utilizara el operador delete y delete[] en ese caso, la memoria ocupada por unEntero
y arrayDeEnteros respectivamente, quedaría ocupada sin sentido. Cuando una porción de
memoria queda ocupada por una variable que ya no se utiliza, y no hay forma de acceder a
ella, se denomina un 'memory leak'. En aplicaciones grandes, si ocurren muchos memory
leaks, el programa puede terminar ocupando bastante más memoria RAM de la que debería,
lo que no es para nada conveniente. Es por esto, que el manejo de memoria heap debe usarse
conscientemente.
Existen dos tipos de destructores pueden ser públicos o privados, según si se declaran:
Si es público se llama desde cualquier parte del programa para destruir el objeto.
Si es privado no se permite la destrucción del objeto por el usuario.
El uso de destructores es clave en el concepto de Adquirir Recursos es Inicializar.
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): Cambiará 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. Este proceso es invisible al programador. 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.
Caso especial es el de las funciones miembro estáticas. A pesar de que son declaradas dentro
de la clase, con el uso de la palabra clave static no recibirán el puntero this. Gracias a esto no
es necesario crear ninguna instancia de la clase para llamar a esta función, sin embargo, solo
se podrá acceder a los miembros estáticos de la clase dado que estos no están asociados al
objeto sino al tipo. La sintaxis para llamar a esta función estática
es mytype::mystaticmember().
Plantillas
Las plantillas son el mecanismo de C++ para implantar el paradigma de la programación
genérica. Permiten que una clase o función trabaje con tipos de datos abstractos,
especificándose más adelante cuales son los que se quieren usar. Por ejemplo, es posible
construir un vector genérico que pueda contener cualquier tipo de estructura de datos. De
esta forma se pueden declarar objetos de la clase de este vector que contengan enteros,
flotantes, polígonos, figuras, fichas de personal, etc.
La declaración de una plantilla se realiza anteponiendo la declaración template <typename
A,....> a la declaración de la estructura (clase, estructura o función) deseado.
Por 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 solo 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;
}
# 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;
return 0;
}
Como puede verse, las invocaciones directas a mi_valor darán acceso solamente a la variable
descrita localmente; para acceder a la variable del espacio de nombres 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.
Herencia
Existen varios tipos de herencia entre clases en el lenguaje de programación C++. Estos son:
Herencia simple
La herencia en C++ es un mecanismo de abstracción creado para poder facilitar y mejorar el
diseño de las clases de un programa. Con ella se pueden crear nuevas clases a partir de clases
ya hechas, siempre y cuando tengan un tipo de relación especial.
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.
Ejemplo: clases Barco, Acorazado, Carguero, etc. Un Acorazado ES-UN Barco, un Carguero
ES-UN Barco, un Trasatlántico ES-UN Barco, etc.
En este ejemplo tendríamos las cosas generales de un Barco (en C++)
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
};
Por último, hay que mencionar que existen 3 clases de herencia que se diferencian en el modo
de manejar la visibilidad de los componentes de la clase resultante:
Herencia pública (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 (las propiedades
heredadas serán privadas aunque estas sean públicas en la clase Base)
Herencia protegida (clase Derivada: protected Base): Con este tipo de herencia, todo
componente público y protegido de la clase Base, será protegido en la clase Derivada, y
los componentes privados, siguen siendo privados.
Herencia múltiple
La herencia múltiple es el mecanismo que permite al programador hacer clases derivadas a
partir, no de una sola clase base, sino de varias. Para entender esto mejor, pongamos un
ejemplo: Cuando ves a quien te atiende en una tienda, como persona que es, podrás suponer
que puede hablar, comer, andar, pero, por otro lado, como empleado que es, también podrás
suponer que tiene un jefe, que puede cobrarte dinero por la compra, que puede devolverte el
cambio, etc. Si esto lo trasladamos a la programación sería herencia múltiple (clase
empleado_tienda):
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
La sobrecarga de operadores es una forma de hacer polimorfismo. Es posible definir el
comportamiento de un operador del lenguaje para que trabaje con tipos de datos definidos
por el usuario. No todos los operadores de C++ son factibles de sobrecargar, y, entre aquellos
que pueden ser sobrecargados, se deben cumplir condiciones especiales. En particular, los
operadores sizeof y :: no son sobrecargables.
No es posible en C++ crear un operador nuevo.
Los comportamientos de los operadores sobrecargados se implementan de la misma manera
que una función, salvo que esta tendrá un nombre especial: Tipo de dato de
devolución operator<token del operador>(parámetros)
Los siguientes operadores pueden ser sobrecargados:
Operadores Unarios
Operador * (de indirección)
Operador -> (de indirección)
Operador & (de dirección)
Operador +
Operador -
Operador ++
Operador --
Operadores Binarios
Operador ==
Operador +
Operador -
Operador *
Operador /
Operador %
Operador <<
Operador >>
Operador &
Operador ^
Operador |
Operador []
Operador ()
Operadores de Asignación
Operador =
Operador +=
Operador -=
Operador *=
Operador /=
Operador %=
Operador <<=
Operador >>=
Operador &=
Operador ^=
Operador |=
Dado que estos operadores son definidos para un tipo de datos definido por el usuario, este
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;
//...
int main() {
ifstream entrada;
entrada.open("textoPlano.txt");
string unString;
while(entrada >> unString)
cout << "Lei: " << unString << endl;
return 0;
}
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:
Pueden abrirse pasando al constructor los parámetros relativos a la ubicación del fichero y el
modo de apertura:
Sstreams
Se destacan dos clases, ostringstream e istringstream. Todo lo anteriormente dicho es
aplicable a estas clases. Tratan a una cadena como si de un flujo de datos se tratase.
ostringstream permite elaborar una cadena de texto insertando datos cual flujo, e
istringstream puede extraer la información contenida en una cadena (pasada como parámetro
en su constructor) con el operador >> . Ejemplos:
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. Todos los contenedores son homogéneos, es decir, una vez que se declaran para
contener un tipo de dato determinado, en ese contenedor, solo se podrán meter elementos de
ese tipo. Según la naturaleza del almacenado, disponemos de varios tipos:
vector<tipo_de_dato> nombre_del_vector;
int main() {
vector<int> intVector; //crea un vector de enteros (sin elementos)
intVector.push_back(25); //agrega el entero 25 al vector
cout << "El primer elemento es: " << intVector.front() <<
" y mi vector tiene " << intVector.size() << " elementos." << endl; //imprime el primer
elemento, retornado por el método front()
return 0;
}
Colas dobles: son parecidas a los vectores, pero tienen mejor eficiencia para agregar o
eliminar elementos en las "puntas".
deque<tipo_de_dato> nombre_de_la_cola;
int main() {
deque<int> intDeque;
intDeque.push_front(25);
intDeque.push_back(12);
while(intDeque.size())
intDeque.pop_back(); //borra todos los elementos
return 0;
}
Listas: Son eficientes a la hora de agregar elementos. La diferencia con las colas dobles,
es que son más eficientes para eliminar elementos que no estén en alguna de las "puntas"
list<tipo_de_dato> nombre_de_la_lista;
Adaptadores de secuencia.
Contenedores asociativos: map y multimap, que permiten asociar una "clave" con un
"valor". map no permite valores repetidos, mientras que multimap si.
int main() {
map<int, string> intAString;
intAString[1] = "uno";
intAString[10] = "diez";
cout << "En intAString[1]: " << intAString[1] << endl;
cout << "En intAString[10]: " << intAString[10] << endl;
return 0;
}
De este modo, todos los datos que están entre inicio_origen y fin_origen, excluyendo el dato
ubicado en este último, son copiados a un lugar descrito o apuntado por inicio_destino.
Un algoritmo muy importante que viene implementado en la biblioteca STL, es el sort. El
algoritmo sort, ordena cualquier tipo de contenedor, siempre y cuando se le pasen como
argumentos, desde donde y hasta donde se quiere ordenarlo.
#include <vector>
#include <deque>
#include <algorithm>
int main() {
vector<int> intVector;
intVector.push_back(60);
intVector.push_back(12);
intVector.push_back(54); //para este momento, el vector tiene 60,12,54
sort(intVector.begin(), intVector.end()); //listo, array ordenado, ahora tiene 12,54,60
/*Notar que si en vez de un vector, fuese una deque, se ordenaría de la misma manera. */
}
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.
C++11
El 12 de agosto de 2011, Herb Sutter, presidente del comité de estándares de C++, informó
la aprobación unánime del nuevo estándar.2 La publicación del mismo se realizó en algún
momento del 2011.
Entre las características del nuevo estándar se pueden destacar:
Funciones lambda;
Referencias rvalue;
La palabra reservada auto;
Inicialización uniforme;
Plantillas con número variable de argumentos.
Además se ha actualizado la biblioteca estándar del lenguaje.
Actualidad y futuro
La continuidad de C++14 es C++17, que es la versión actual, y en el futuro, se estima que en
2020, será C++20
Diferencias de tipos respecto a C
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:
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). Otros
compiladores comunes son Intel C++ Compiler, el compilador de Xcode, el compilador
de Borland C++, el compilador de CodeWarrior C++, el compilador g++ de Cygwin, el
compilador g++ de MinGW, el compilador de Visual C++, Carbide.c++, entre otros.
#include <cstdlib>
using namespace std;
system("color 45");
En este caso se ha definido el fondo de pantalla de color rojo y las letras rosadas.
LENGUAJE DE PROGRAMACION PYTHON
Python es un lenguaje de
programación interpretado cuya filosofía
hace hincapié en una sintaxis que favorezca
un código legible.
Se trata de un lenguaje de
programación multiparadigma, ya que
soporta orientación a objetos, programación
imperativa y, en menor
medida, programación funcional. Es
un lenguaje interpretado, usa tipado
dinámico y es multiplataforma.
Es administrado por la Python Software
Foundation. Posee una licencia de código
abierto, denominada Python Software
Foundation License,3 que es compatible
con la Licencia pública general de GNU a
partir de la versión 2.1.1, e incompatible en
ciertas versiones anteriores.
Historia
Python fue creado a finales de los ochenta4 por Guido van Rossum en el Centro para las
Matemáticas y la Informática (CWI, Centrum Wiskunde & Informatica), en los Países Bajos,
como un sucesor del lenguaje de programación ABC, capaz de manejar excepciones e
interactuar con el sistema operativo Amoeba.5
El nombre del lenguaje proviene de la afición de su creador por los humoristas
británicos Monty Python.6
Van Rossum es el principal autor de Python, y su continuo rol central en decidir la dirección
de Python es reconocido, refiriéndose a él como Benevolente Dictador Vitalicio (en
inglés: Benevolent Dictator for Life, BDFL); sin embargo el 12 de julio de 2018 declinó de
dicha situación de honor sin dejar un sucesor o sucesora y con una declaración altisonante:7
Entonces, ¿qué van a hacer todos ustedes? ¿Crear una democracia? ¿Anarquía? ¿Una
dictadura? ¿Una federación?
Guido van Rossum8
En 1991, van Rossum publicó el código de la versión 0.9.0 en alt.sources.9 En esta etapa del
desarrollo ya estaban presentes clases con herencia, manejo de excepciones, funciones y los
tipos modulares, como: str , list , dict , entre otros. Además en este lanzamiento inicial
aparecía un sistema de módulos adoptado de Modula-3; van Rossum describe el módulo
como “una de las mayores unidades de programación de Python”.4 El modelo de excepciones
en Python es parecido al de Modula-3, con la adición de una cláusula else .5 En el año 1994
se formó comp.lang.python, el foro de discusión principal de Python, marcando un hito en el
crecimiento del grupo de usuarios de este lenguaje.
Python alcanzó la versión 1.0 en enero de 1994. Una característica de este lanzamiento fueron
las herramientas de la programación funcional: lambda , reduce , filter y map . Van Rossum
explicó que “hace 12 años, Python adquirió lambda, reduce(), filter() y map(), cortesía de un
hacker informático de Lisp que las extrañaba y que envió parches”.10 El donante fue Amrit
Prem; no se hace ninguna mención específica de cualquier herencia de Lisp en las notas de
lanzamiento.
La última versión liberada proveniente de CWI fue Python 1.2. En 1995, van Rossum
continuó su trabajo en Python en la Corporation for National Research Initiatives (CNRI) en
Reston, Virginia, donde lanzó varias versiones del software.
Durante su estancia en CNRI, van Rossum lanzó la iniciativa Computer Programming for
Everybody (CP4E), con el fin de hacer la programación más accesible a más gente, con un
nivel de 'alfabetización' básico en lenguajes de programación, similar a la alfabetización
básica en inglés y habilidades matemáticas necesarias por muchos trabajadores. Python tuvo
un papel crucial en este proceso: debido a su orientación hacia una sintaxis limpia, ya era
idóneo, y las metas de CP4E presentaban similitudes con su predecesor, ABC. El proyecto
fue patrocinado por DARPA.11 En el año 2007, el proyecto CP4E está inactivo, y mientras
Python intenta ser fácil de aprender y no muy arcano en su sintaxis y semántica, alcanzando
a los no-programadores, no es una preocupación activa.12
En el año 2000, el equipo principal de desarrolladores de Python se cambió
a BeOpen.com para formar el equipo BeOpen PythonLabs. CNRI pidió que la versión 1.6
fuera pública, continuando su desarrollo hasta que el equipo de desarrollo abandonó CNRI;
su programa de lanzamiento y el de la versión 2.0 tenían una significativa cantidad de
traslapo.13 Python 2.0 fue el primer y único lanzamiento de BeOpen.com. Después que
Python 2.0 fuera publicado por BeOpen.com, Guido van Rossum y los otros desarrolladores
de PythonLabs se unieron en Digital Creations.
Python 2.0 tomó una característica mayor del lenguaje de programación funcional Haskell:
listas por comprensión. La sintaxis de Python para esta construcción es muy similar a la de
Haskell, salvo por la preferencia de los caracteres de puntuación en Haskell, y la preferencia
de Python por palabras claves alfabéticas. Python 2.0 introdujo además un sistema
de recolección de basura capaz de recolectar referencias cíclicas.13
Posterior a este doble lanzamiento, y después que van Rossum dejó CNRI para trabajar con
desarrolladores de software comercial, quedó claro que la opción de usar Python con software
disponible bajo GNU GPL era muy deseable. La licencia usada entonces, la Python License,
incluía una cláusula estipulando que la licencia estaba gobernada por el estado de Virginia,
por lo que, bajo la óptica de los abogados de Free Software Foundation (FSF), se hacía
incompatible con GPL. CNRI y FSF se relacionaron para cambiar la licencia de software
libre de Python para hacerla compatible con GPL. En el año 2001, van Rossum fue premiado
con FSF Award for the Advancement of Free Software.
Python 1.6.1 es esencialmente el mismo que Python 1.6, con unos pocos arreglos de bugs, y
con una nueva licencia compatible con GPL.3
Código Python con coloreado de sintaxis.
Python 2.1 fue un trabajo derivado de Python 1.6.1, así como también de Python 2.0. Su
licencia fue renombrada a: Python Software Foundation License. Todo el código,
documentación y especificaciones añadidas, desde la fecha del lanzamiento de la versión alfa
de Python 2.1, tiene como dueño a Python Software Foundation (PSF), una organización sin
ánimo de lucro fundada en el año 2001, tomando como modelo la Apache Software
Foundation.3 Incluido en este lanzamiento fue una implementación del scoping más parecida
a las reglas de static scoping (del cual Scheme es el originador).14
Una innovación mayor en Python 2.2 fue la unificación de los tipos en Python (tipos escritos
en C), y clases (tipos escritos en Python) dentro de una jerarquía. Esa unificación logró un
modelo de objetos de Python puro y consistente.15 También fueron agregados
los generadores que fueron inspirados por el lenguaje Icon.16
Las adiciones a la biblioteca estándar de Python y las decisiones sintácticas fueron
influenciadas fuertemente por Java en algunos casos: el package logging ,17 introducido en
la versión 2.3, está basado en log4j; el parser SAX, introducido en 2.0; el
package threading ,18 cuya clase Thread expone un subconjunto de la interfaz de la clase
homónima en Java.
Características y paradigmas
Python es un lenguaje de programación multiparadigma. Esto significa que más que forzar a
los programadores a adoptar un estilo particular de programación, permite varios
estilos: programación orientada a objetos, programación imperativa y programación
funcional. Otros paradigmas están soportados mediante el uso de extensiones.
Python usa tipado dinámico y conteo de referencias para la administración de memoria.
Una característica importante de Python es la resolución dinámica de nombres; es decir, lo
que enlaza un método y un nombre de variable durante la ejecución del programa (también
llamado enlace dinámico de métodos).
Otro objetivo del diseño del lenguaje es la facilidad de extensión. Se pueden escribir nuevos
módulos fácilmente en C o C++. Python puede incluirse en aplicaciones que necesitan una
interfaz programable.
Aunque la programación en Python podría considerarse en algunas situaciones hostil a la
programación funcional tradicional del Lisp, existen bastantes analogías entre Python y los
lenguajes minimalistas de la familia Lisp como puede ser Scheme.
Filosofía
Los usuarios de Python se refieren a menudo a la Filosofía Python que es bastante análoga
a la filosofía de Unix. El código que sigue los principios de Python de legibilidad y
transparencia se dice que es "pythonico". Contrariamente, el código opaco u ofuscado es
bautizado como "no pythonico" ("unpythonic" en inglés). Estos principios fueron descritos
por el desarrollador de Python Tim Peters en El Zen de Python
Modo interactivo
El intérprete de Python estándar incluye un modo interactivo en el cual se escriben las
instrucciones en una especie de intérprete de comandos: las expresiones pueden ser
introducidas una a una, pudiendo verse el resultado de su evaluación inmediatamente, lo que
da la posibilidad de probar porciones de código en el modo interactivo antes de integrarlo
como parte de un programa. Esto resulta útil tanto para las personas que se están
familiarizando con el lenguaje como para los programadores más avanzados.
Existen otros programas, tales como IDLE, bpython o IPython,21 que añaden
funcionalidades extra al modo interactivo, como el autocompletado de código y el coloreado
de la sintaxis del lenguaje.
Ejemplo del modo interactivo:
>>> 1 + 1
2
>>> a = range(10)
>>> print( list(a) )
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Comentarios
Los comentarios se pueden poner de dos formas. La primera y más apropiada para
comentarios largos es utilizando la notación ''' comentario ''', tres apóstrofos de apertura y
tres de cierre. La segunda notación utiliza el símbolo # , y se extienden hasta el final de la
línea.
El intérprete no tiene en cuenta los comentarios, lo cual es útil si deseamos poner información
adicional en el código. Por ejemplo, una explicación sobre el comportamiento de una sección
del programa.
'''
Comentario más largo en una línea en Python
'''
print "Hola mundo" # También es posible añadir un comentario al final de una línea de
código
Variables
Las variables se definen de forma dinámica, lo que significa que no se tiene que especificar
cuál es su tipo de antemano y puede tomar distintos valores en otro momento, incluso de un
tipo diferente al que tenía previamente. Se usa el símbolo = para asignar valores.
x=1
x = "texto" # Esto es posible porque los tipos son asignados dinámicamente
Tipos de datos
Los tipos de datos se pueden resumir en esta tabla:
Número
long Precisión arbitraria 42L ó 456966786151987643L
entero
Número
complex Parte real y parte imaginaria j. (4.5 + 3j)
complejo
Bucle for
El bucle for es similar a foreach en otros lenguajes. Recorre un objeto iterable, como
una lista, una tupla o un generador, y por cada elemento del iterable ejecuta el bloque de
código interno. Se define con la palabra clave for seguida de un nombre de variable, seguido
de in , seguido del iterable, y finalmente el bloque de código interno. En cada iteración, el
elemento siguiente del iterable se asigna al nombre de variable especificado:
Bucle while
El bucle while evalúa una condición y, si es verdadera, ejecuta el bloque de código interno.
Continúa evaluando y ejecutando mientras la condición sea verdadera. Se define con la
palabra clave while seguida de la condición, y a continuación el bloque de código interno:
>>> numero = 0
>>> while numero < 10:
... print numero,
... numero += 1 #un buen programador modificará las variables de control al finalizar el
ciclo while
...
0123456789
Listas y Tuplas
Para declarar una lista se usan los corchetes [] , en cambio, para declarar una tupla se
usan los paréntesis () . En ambas los elementos se separan por comas, y en el caso de
las tuplas es necesario que tengan como mínimo una coma.
Tanto las listas como las tuplas pueden contener elementos de diferentes tipos. No
obstante las listas suelen usarse para elementos del mismo tipo en cantidad variable
mientras que las tuplas se reservan para elementos distintos en cantidad fija.
Para acceder a los elementos de una lista o tupla se utiliza un índice entero (empezando
por "0", no por "1"). Se pueden utilizar índices negativos para acceder elementos a partir
del final.
Las listas se caracterizan por ser mutables, es decir, se puede cambiar su contenido en
tiempo de ejecución, mientras que las tuplas son inmutables ya que no es posible
modificar el contenido una vez creada.
Listas
Tuplas
Diccionarios
Para declarar un diccionario se usan las llaves {} . Contienen elementos separados por
comas, donde cada elemento está formado por un par clave:valor (el símbolo : separa
la clave de su valor correspondiente).
>>> diccionario = {"cadena": "abc", "numero": 42, "lista": [True, 42L]} # Diccionario que
tiene diferentes valores por cada clave, incluso una lista
>>> diccionario["cadena"] # Usando una clave, se accede a su valor
'abc'
>>> diccionario["lista"][0] # Acceder a un elemento de una lista dentro de un valor (del valor
de la clave "lista", mostrar el primer elemento)
True
>>> diccionario["cadena"] = "xyz" # Re-asignar el valor de una clave
>>> diccionario["cadena"]
'xyz'
>>> diccionario["decimal"] = 3.1415927 # Insertar un nuevo elemento clave:valor
>>> diccionario["decimal"]
3.1415927
>>> diccionario_mixto = {"tupla": (True, 3.1415), "diccionario": diccionario} # También es
posible que un valor sea un diccionario
>>> diccionario_mixto["diccionario"]["lista"][1] # Acceder a un elemento dentro de una
lista, que se encuentra dentro de un diccionario
42L
>>> diccionario = {("abc",): 42} # Sí es posible que una clave sea una tupla, pues es
inmutable
>>> diccionario = {["abc"]: 42} # No es posible que una clave sea una lista, pues es mutable,
lo que provocará una excepción
( Excepción )
>>> if condicion1:
... hacer1
>>> elif condicion2:
... hacer2
>>> elif condicion3:
... hacer3
>>> else:
... hacer
Podriamos decir que el lado negativo de la sentencia armada con if, elif y else es que si la
lista de posibles operaciones es muy larga, las tiene que recorrer una por una hasta llegar a la
correcta.
Usando diccionario[editar]
Podemos usar un diccionario para el mismo ejemplo:
De esta manera si las opciones fueran muchas no recorrería todas. Solo iría directamente a la
operación buscada. en la ultima linea .get(op, lambda: None)() estamos dando la opción por
defecto.
Conjuntos
Los conjuntos se construyen mediante set(items) donde items es cualquier
objeto iterable, como listas o tuplas. Los conjuntos no mantienen el orden ni contienen
elementos duplicados.
>>> conjunto_inmutable = frozenset(["a", "b", "a"]) # Se utiliza una lista como objeto
iterable
>>> conjunto_inmutable
frozenset(['a', 'b'])
>>> conjunto1 = set(["a", "b", "a"]) # Primer conjunto mutable
>>> conjunto1
set(['a', 'b'])
>>> conjunto2 = set(["a", "b", "c", "d"]) # Segundo conjunto mutable
>>> conjunto2
set(['a', 'c', 'b', 'd']) # Recuerda, no mantienen el orden, como los diccionarios
>>> conjunto1 & conjunto2 # Intersección
set(['a', 'b'])
>>> conjunto1 | conjunto2 # Unión
set(['a', 'c', 'b', 'd'])
>>> conjunto1 - conjunto2 # Diferencia (1)
set([])
>>> conjunto2 - conjunto1 # Diferencia (2)
set(['c', 'd'])
>>> conjunto1 ^ conjunto2 # Diferencia simétrica
set(['c', 'd'])
>>> range(5) # La función "range" devuelve una lista, empezando en 0 y terminando con el
número indicado menos uno
[0, 1, 2, 3, 4]
>>> [i*i for i in range(5)] # Por cada elemento del rango, lo multiplica por sí mismo y lo
agrega al resultado
[0, 1, 4, 9, 16]
>>> lista = [(i, i + 2) for i in range(5)]
>>> lista
[(0, 2), (1, 3), (2, 4), (3, 5), (4, 6)]
Funciones
Las funciones se definen con la palabra clave def , seguida del nombre de la función y
sus parámetros. Otra forma de escribir funciones, aunque menos utilizada, es con la
palabra clave lambda (que aparece en lenguajes funcionales como Lisp).
El valor devuelto en las funciones con def será el dado con la instrucción return .
def :
>>> def suma(x, y = 2):
... return x + y # Retornar la suma del valor de la variable "x" y el valor de "y"
...
>>> suma(4) # La variable "y" no se modifica, siendo su valor: 2
6
>>> suma(4, 10) # La variable "y" sí se modifica, siendo su nuevo valor: 10
14
lambda :
Clases
Las clases se definen con la palabra clave class , seguida del nombre de la clase y,
si hereda de otra clase, el nombre de esta.
En Python 2.x es recomendable que una clase herede de "object", en Python 3.x esto ya
no hará falta.
En una clase un "método" equivale a una "función", y un "atributo" equivale a una
"variable".
"__init__" es un método especial que se ejecuta al instanciar la clase, se usa generalmente
para inicializar atributos y ejecutar métodos necesarios. Al igual que todos los métodos
en Python, debe tener al menos un parámetro, generalmente se utiliza self . El resto de
parámetros serán los que se indiquen al instanciar la clase.
Los atributos que se desee que sean accesibles desde fuera de la clase se deben declarar
usando self. delante del nombre.
En python no existe el concepto de encapsulación,26 por lo que el programador debe ser
responsable de asignar los valores a los atributos
Módulos
Existen muchas propiedades que se pueden agregar al lenguaje importando módulos, que son
"minicódigos" (la mayoría escritos también en Python) que proveen de ciertas funciones y
clases para realizar determinadas tareas. Un ejemplo es el módulo Tkinter27, que permite
crear interfaces gráficas basadas en la biblioteca Tk. Otro ejemplo es el módulo os, que
provee acceso a muchas funciones del sistema operativo. Los módulos se agregan a los
códigos escribiendo import seguida del nombre del módulo que queramos usar.28
Para tareas de administración de archivos, el módulo shutil provee una interfaz de más alto
nivel:
Comodines de archivos
El módulo glob provee una función para crear listas de archivos a partir de búsquedas con
comodines en carpetas:
Matemática
El módulo math permite acceder a las funciones de matemática de punto flotante:
El módulo statistics se utiliza para estadística básica, por ejemplo: media, mediana, varianza,
etc:
Fechas y Tiempos
El módulo datetime permite manejar fechas y tiempos:
Sistema de objetos
En Python todo es un objeto (incluso las clases). Las clases, al ser objetos, son instancias de
una metaclase. Pythonademás soporta herencia múltiple y polimorfismo.
>>> cadena = "abc" # Una cadena es un objeto de "str"
>>> cadena.upper() # Al ser un objeto, posee sus propios métodos
'ABC'
>>> lista = [True, 3.1415] # Una lista es un objeto de "list"
>>> lista.append(42L) # Una lista también (al igual que todo) es un objeto, y también posee
sus propios métodos
>>> lista
[True, 3.1415, 42L]
Biblioteca estándar
Python tiene una gran biblioteca estándar, usada para una diversidad de tareas. Esto viene de
la filosofía "pilas incluidas" ("batteries included") en referencia a los módulos de Python.
Los módulos de la biblioteca estándar pueden mejorarse por módulos personalizados escritos
tanto en C como en Python. Debido a la gran variedad de herramientas incluidas en la
biblioteca estándar, combinada con la habilidad de usar lenguajes de bajo nivel como C y
C++, los cuales son capaces de interactuar con otras bibliotecas, Python es un lenguaje que
combina su clara sintaxis con el inmenso poder de lenguajes menos elegantes.
Implementaciones
Existen diversas implementaciones del lenguaje:
LENGUAJE DE PROGRAMACIÓN C#
(pronunciado si sharp en inglés) es un lenguaje
de programaciónorientado a
objetos desarrollado y estandarizado
por Microsoft como parte de su
plataforma .NET, que después fue aprobado
como un estándar por la ECMA (ECMA-334)
e ISO (ISO/IEC 23270). C# es uno de los
lenguajes de programación diseñados para
la infraestructura de lenguaje común.
Su sintaxis básica deriva de C/C++ y utiliza el
modelo de objetos de la plataforma .NET,
similar al de Java, aunque incluye mejoras
derivadas de otros lenguajes.
El nombre C Sharp fue inspirado por el signo
'#' que se compone de cuatro signos '+'
pegados.
Aunque C# forma parte de la plataforma .NET,
ésta es una API, mientras que C# es un
lenguaje de programación independiente
diseñado para generar programas sobre dicha
plataforma. Ya existe
un compilador implementado que provee el
marco Mono - DotGNU, el cual genera
programas para distintas plataformas
como Windows
Microsoft, Unix, Android, iOS, Windows
Phone, Mac OS y GNU/Linux.
Historia
Durante el desarrollo de la plataforma .NET, las bibliotecas de clases fueron escritas
originalmente usando un sistema de código gestionado llamado Simple Managed C (SMC).
En enero de 1999, Anders Hejlsberg formó un equipo con la misión de desarrollar un nuevo
lenguaje de programación llamado Cool (Lenguaje C orientado a objetos). Este nombre
tuvo que ser cambiado debido a problemas de marca, pasando a llamarse C#.1 La biblioteca
de clases de la plataforma .NET fue migrada entonces al nuevo lenguaje, este después fue
modificado por Joseth M.
Hejlsberg lideró el proyecto de desarrollo de C#. Anteriormente, ya había participado en el
desarrollo de otros lenguajes como Turbo Pascal, Delphi y J++.
Tipos de datos
C# contiene veinte categorías generales de tipos de datos integrados: tipos de valor y tipos
de referencia. El término tipo de valor indica que esos tipos contienen directamente sus
valores. Tipos para definir números enteros:
Los tipos de coma flotante pueden representar números con componentes fraccionales.
Existen dos clases de tipos de coma flotante: float y double. El tipo double es el más
utilizado porque muchas funciones matemáticas de la biblioteca de clases de C# usan
valores double. Quizá, el tipo de coma flotante más interesante de C# es decimal, dirigido
al uso de cálculos monetarios. La aritmética de coma flotante normal está sujeta a una
variedad de errores de redondeo cuando se aplica a valores decimales. El
tipo decimal elimina estos errores y puede representar hasta 28 lugares decimales.
Coma
32-bit
float System.Single ±1.401298E−45 a ±3.402823E+38 flotante
(4-byte)
corto
Coma
64-bit ±4.94065645841246E−324 a
double System.Double flotante
(8-byte) ±1.79769313486232E+308
largo
−7.92281625142643375935439503
decima 128-bit Coma
35 a
System.Decimal (16- flotante
l +7.92281625142643375935439503
byte) monetario
35
Para los tipos de datos lógicos no existen conversiones automáticas de tipo entero a bool .
Literales
En ocasiones, resulta más sencillo usar un sistema numérico en base 16 en lugar de 10, para
tal caso C# permite especificar números enteros en formato hexadecimal, y se define
anteponiendo 0x , por ejemplo: 0xFF , que equivale a 255 en decimal.
C# tiene caracteres denominados secuencias de escape para facilitar la escritura con el
teclado de símbolos que carecen de representación visual.
C#, al igual que C++, define un tipo de 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.
Enteros
Coma flotante
decimal 9.95M
Caracteres
Cadenas
String "Hello, world" ; "C:\\Windows\\" , @"C:\Windows\"
Secuencias de escape
Alerta (timbre) \a
Retroceso \b
Avance de página \f
Nueva línea \n
Retorno de carro \r
Tabulador horizontal \t
Tabulador vertical \v
Nulo \0
Barra inversa \\
Variables
Las variables son identificadores asociados a valores. Se declaran indicando el tipo de dato
que almacenará y su identificador.
Un identificador puede:
Para asignar un valor a una variable, se indica el identificador de la misma, seguido del
símbolo igual ( = ) y el valor que queremos que almacene:
También puedes declarar una variable sin especificar el tipo de dato, utilizando el
mecanismo de inferencia mediante la palabra clave var donde el compilador determina el
tipo de dato que se le asignará a la variable y sólo es permitida para variables locales, no
para parámetros o datos miembro.
var numero1 = 5;
Leyenda
byt sbyt sho usho in uin lon ulon flo doub decim cha bo
e e rt rt t t g g at le al r ol
byte E A A A A A A E E E E I
sbyte E A E A E A A E E E E I
short E E E A A A A E E E E I
ushor
E E E A A A A E E E E I
t
int E E E E E A A E E E E I
uint E E E E E A A E E E E I
long E E E E E E E E E E E I
ulong E E E E E E E E E E E I
float E E E E E E E E A E I I
doubl
E E E E E E E E E E I I
e
decim
E E E E E E E E E E I I
al
char E E E A A A A A A A A I
bool I I I I I I I I I I I I
Además de realizarse dentro de una asignación, las conversiones de tipos también tienen
lugar dentro de una expresión, pues en cada operación ambos operandos deben de ser del
mismo tipo. Si la conversión es del tipo implícito se efectúa el siguiente algoritmo en dicho
orden:
1. Si un operando es decimal , el otro operando se transforma a decimal .
2. Si un operando es double , el otro operando se transforma a double .
3. Si un operando es float , el otro operando se transforma a float .
4. Si un operando es ulong , el otro operando se transforma a ulong .
5. Si un operando es long , el otro operando se transforma a long .
6. Si un operando es uint , y si el otro operando es de tipo sbyte , short o int , los dos
se transforman a long .
7. Si un operando es uint , el otro operando se transforma a uint .
8. Si no es ninguno de los casos anteriores, los dos operandos se transforman a int .
Constantes
Las constantes son valores inmutables, y por tanto no se pueden cambiar.
const
Cuando se declara una constante con la palabra clave const , también se debe asignar el
valor. Tras esto, la constante queda bloqueada y no se puede cambiar. Son implícitamente
estáticas ( static ).
readonly
A diferencia de const , no requiere que se asigne el valor al mismo tiempo que se declara.
Pueden ser miembros de la instancia o miembros estáticos de la clase ( static ).
readonly double E;
E = 2.71828;
Operadores
Categoría Operadores
Aritméticos + - * / %
Lógicos ! && ||
A nivel de bits & | ^ ~
Concatenación +
Incremento, decremento ++ --
Acceso a miembro .
Indexación []
Conversión ()
Condicional ? : ??
Instrucciones de control
if-else
if (i == 2)
{
// ...
}
else if (i == 3)
{
// ...
}
else
{
// ...
}
switch
switch (i)
{
case 1:
...
break;
case 2:
case 3:
...
break;
default:
...
break;
}
for
while
do-while
do
{
// ...
} while (true);
foreach
Las instrucciones if-else , for , while , do-while , switch , return , break , continue son,
básicamente, iguales que en C, C++ y Java.
La instrucción foreach , al igual que en Java, realiza un ciclo a través de los elementos
de una matriz o colección. En este ciclo se recorre la colección y la variable recibe un
elemento de dicha colección en cada iteración.
La instrucción goto se sigue utilizando en C# a pesar de la polémica sobre su uso.
Métodos
Todo método debe ser parte de una clase, no existen métodos globales (funciones).
Por defecto, los parámetros se pasan por valor. (Nótese que las listas y otras
colecciones son variables por referencia(referencias al espacio reservado para esa lista
en la pila) y que se pasa por valor al método la referencia, pero el espacio reservado
para la lista es común, por lo que si elimina un elemento lo hace también de la
original).
El modificador ref fuerza a pasar los parámetros por referencia en vez de pasarlos por
valor y obliga a inicializar la variable antes de pasar el parámetro.
El modificador out es similar al modificador ref , con la diferencia de que no se obliga
a inicializar la variable antes de pasar el parámetro.
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.
Un método debe tener como máximo un único parámetro params y éste debe ser el
último.
int z = 0;
PassRef(ref z);
out
int z;
PassOut(out z);
params
int a = 1;
MaxVal('a', 23, 3, a, -12); // El primer parámetro es obligatorio, seguidamente se pueden
poner tantos números enteros como se quiera
Sobrecarga de métodos
Main
Matrices
Acceder a un elemento:
Declarar e inicializar una matriz multidimensional (el tamaño de la matriz se puede omitir):
Clases y objetos
Una variable de objeto de cierta clase no almacena los valores del objeto sino su
referencia (al igual que Java).
class Clase
{
}
Iniciar una clase (también llamado crear un objeto de la clase o instanciar una clase):
class Clase
{
~Clase()
{
// ...
}
}
this :
class Clase
{
int i = 1;
Clase()
{
this.Arrancar(); // Llamará al método 'Arrancar' del objeto
}
void Arrancar()
{
// ...
}
}
static :
class Clase
{
static int i = 1;
}
Clase.i; // Retornará el valor '1'. No hace falta crear un objeto, ya que al ser 'static',
pertenece a la clase.
operator :
class Clase
{
static int operator +(int x, int y)
{
// Sobrecarga el operador '+'
// ...
}
static int operator -(int x, int y)
{
// Sobrecarga el operador '-'
// ...
}
static int operator int(byte x)
{
// Sobrecarga la conversión de tipo 'byte' a 'int'
// ...
}
}
Comparación de objetos:
class Clase
{
}
Clase c1 = new Clase();
Clase c2 = new Clase();
bool b = c1 == c2; // Retornará 'false', ya que son dos objetos distintos
Cadenas de caracteres
bool b = "texto" == "texto"; // Retornará 'true', ya que ambas cadenas contienen "texto"
Concatenar cadenas:
string texto = "Cadena de" + " caracteres"; // Nótese el espacio antes de "caracteres", si no
se pusiera, aparecería junto: "decaracteres"
La clase System.String , y una instancia de la misma, string , poseen algunos métodos para
trabajar con cadenas, como:
static string Copy(string str) : devuelve una copia de str .
string Substring : devuelve una subcadena, indicando la posición de inicio y la longitud que
se desea.
Ejemplos[editar]
Ejemplo básico "Hola mundo":
using System;
Suma y concatenación:
using System;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PruebaVector10
{
class PruebaVector10
{
private string[] nombres;
private int[] edades;
firma: RSRR
Compiladores e IDE's
En la actualidad existen los siguientes compiladores o IDE para el lenguaje C#:
Microsoft .NET Framework 2.0 (SDK) incluye un compilador de C#, pero no un IDE.
Microsoft Visual Studio, IDE por excelencia de este lenguaje.
SharpDevelop, IDE libre para C# bajo licencia GNU LGPL, con una interfaz muy
similar a Microsoft Visual Studio.
Mono, es una implementación con licencia GNU GPL de todo el
entorno .NET desarrollado por Novell. Como parte de esta implementación se incluye
un compilador de C#.
DotGNU Portable.NET, de la Free Software Foundation.