Está en la página 1de 56

Abstracción y

Polimorfismo

Programación
Orientada a
Objetos

1
¿Qué es la Abstracción?
La abstracción es uno La abstracción es la acción o efecto de abstraer o abstraerse (RAE, 2018) y
de los principios más siguiendo con la Real Academia española, abstraerse, es
importantes en la “Separar por medio de una operación intelectual un rasgo o una cualidad d
ingeniería de software e algo para analizarlos aisladamente o considerarlos en su pura esencia o
orientada a objetos y
está estrechamente
noción” (RAE, 2018).
relacionada con varios
otros conceptos La abstracción es el acto de representar características esenciales sin incluir
importantes, como la los detalles o explicaciones de fondo. En el dominio de la informática y la
encapsulación, la ingeniería de software, el principio de abstracción se utiliza para reducir la
herencia y el
polimorfismo.
complejidad y permitir un diseño e implementación eficientes de sistemas
de software complejos.
La abstracción se
aplica en el proceso de Algunas áreas de diseño e implementación de software donde se aplica el
identificación de principio de abstracción incluyen lenguajes de programación
artefactos de software
(objetos) para modelar
(principalmente en lenguajes de programación orientados a objetos),
el dominio del lenguajes de especificación, abstracción de control, abstracción de datos y
problema. Es el la arquitectura de los sistemas de software.
proceso de reducir
estos objetos a su Más precisamente se puede decir que la abstracción es la calidad de tratar
esencia de tal manera
con ideas en lugar de hechos. Por ejemplo, cuando considera el caso del
que solo se
representan los correo electrónico, detalles complejos como lo que sucede tan pronto como
elementos necesarios. envía un correo electrónico, el protocolo que utiliza su servidor de correo
La abstracción define electrónico está oculto para el usuario. Por lo tanto, para enviar un correo
un objeto en términos electrónico, solo necesita escribir el contenido, mencionar la dirección del
de sus propiedades,
destinatario y hacer clic en enviar.
funcionalidad e
interfaz (medios de
comunicación con Del mismo modo, en la programación orientada a objetos, la abstracción es
otros objetos) un proceso de ocultar los detalles de la implementación al usuario, solo se
(Techopedia, 2018). le proporcionará la funcionalidad. En otras palabras, el usuario tendrá la
información sobre lo que hace el objeto en lugar de cómo lo hace.

En Java, la abstracción se logra utilizando interfaces y clases abstractas.

Clase abstracta

Una clase en Java que contiene la palabra clave abstract en su declaración


se la conoce como clase abstracta.

Las clases abstractas pueden o no contener métodos abstractos, es decir,


métodos sin cuerpo, por ejemplo la línea de codigo “public void get ();” para
un método de tipo procedimiento llamado “get”. Pero, si una clase tiene al
menos un método abstracto, entonces la clase debe ser declarada abstracta.

2
Si una clase se declara abstracta con “abstract”, no puede ser instanciada
directamente sino que para usar una clase “abstract”, debe ser heredada de
otra clase, es decir proporcionar implementaciones a los métodos
abstractos en ella.

Si otra clase cualquiera, hereda de una clase abstracta, debe proporcionar


implementaciones a todos los métodos abstractos que contiene aquella.

Ejemplo:

Esta sección le proporciona un ejemplo de la clase abstracta. Para crear una


clase abstracta, solo use la palabra clave “abstract” antes de la palabra clave
de clase, en la declaración de clase.

Figura 1: Ejemplo de clase abstracta

/* Archivo llamado: Empleado.java */


public abstract class Empleado {
private String nombre;
private String direccion;
private int numero;
public Empleado(String nombre, String direccion, int number) {
System.out.println("Construyendo un Empleado");
this. nombre = nombre;
this. direccion = direccion;
this.number = numero;
}
public double computePay() {
System.out.println("Dentro del pago de salario de Empleado");
return 0.0;
}
public void mailCheck() {
System.out.println("Enviando por correo un cheque a " +
this. nombre +
" " + this.direccion);
}
public String toString() {
return nombre + " " + direccion + " " + numero;
}
public String getNombre () {
return nombre;
}
public String getDireccion() {
return direccion;
}
public int getNumero() {
return numero;
}
public void setDireccion(String newDireccion) {
address = newDireccion;

3
}
}
Fuente: elaboración propia

Puede observar que, excepto los métodos abstractos, la clase empleados es


la misma que la clase normal en Java. La clase ahora es abstracta, pero
todavía tiene tres campos, siete métodos y un constructor.

Ahora puede intentar crear una instancia de la clase Empleados de la


siguiente manera:

Figura 2: Ejemplo de clase abstracta II

/* File name : AbstractDemo.java */


public class AbstractDemo {
public static void main(String [] args) {
/* Lo que sigue no esta permitido! Y dará error */
Empleado e = new Empleado("Jose de S.M.", "Yapeyu, CORR", 43);
System.out.println("\n Call mailCheck usando una referencia a
Empleado--");
e.mailCheck();
}
}
Fuente: elaboración propia

Heredando la clase abstracta

Podemos heredar las propiedades de la clase Empleado como una clase


concreta y usando “extends” de la siguiente manera:

Figura 3: Ejemplo de clase abstracta III

/* File name : Salario.java */


public class Salario extends Empleado {
private double salario; // Salario Anual
public Salario(String nombre, String direccion, int numero,
double salario) {
super(nombre, direccion, numero);
setSalario(salario);
}

public void mailCheck() {


System.out.println("Dentro de mailCheck de la clase Salario
");
System.out.println("Revisión de Envío por correo para " +
getNombre() + " con salario " + salario);
}

public double getSalario() {

4
return salarioy;
}

public void setSalario(double newSalario) {


if(newSalario >= 0.0) {
salario = newSalario;
}
}

public double computarPago() {


System.out.println("Computando el salario para " +
getName());
return salario/52;
}
}
Fuente: Elaboración propia

Aquí, no puede crear una instancia de la clase Empleado, pero puede crear
una instancia de la clase Salario, y al usar esta instancia puede acceder a los
tres campos y los siete métodos de la clase Empleado como se muestra a
continuación.

Figura 4: Ejemplo de clase abstracta IV

/* File name : AbstractDemo.java */


public class AbstractDemo {

public static void main(String [] args) {


Salario s = new Salario("Juan Perez", "Cordoba, CBA", 3,
3600.00);
Empleado e = new Salario("Jose Suarez", "Villa Maria, CBA",
2, 2400.00);
System.out.println("Llama mailCheck con referencia a Salario
--");
s.mailCheck();
System.out.println("\n Llama mailCheck con referencia a
Salario --");
e.mailCheck();
}
}
Fuente: elaboración propia

5
Esto produce el siguiente resultado:

Figura 5: Ejemplo de clase abstracta V

Construyendo un Empleado
Construyendo un Empleado
Llama a mailCheck con referencia a Salario –
Dentro de mailCheck de la clase Salario
Revision de Mailing para Juan Perez con salario 3600.0

Llama a mailCheck con referencia a Salario --


Dentro de mailCheck de la clase Salario
Revision de Mailing para Jose Suarez con salario 2400.0
Fuente: elaboración propia

Asi es que la abstracción puede aplicarse creando las clases abstractas y con
el correcto manejo de la herencia podemos aplicar en objetos que recibiran
las definiciones generales para ser implementadas, extendiéndolas en los
objetos.

6
Polimorfismo (más detallado)

Contexto

Los objetos en la programación orientada a objetos (POO), estan


compuestos por atributos y métodos. A cada uno de estos se puede acceder
para su modificación (atributos) o para ejecutarlos (métodos) de acuerdo a
lo permitido con los modificadores public, private y restricted, que figuran al
comienzo de su declaración. A los modificadores private y restricted los
podriamos pensar como una frontera entre el interior y el exterior de los
objetos.

Esta separación, total (private) o parcial (restricted), aísla a un objeto de


otros objetos y será imprescindible usar “mensajes” (usando los metodos
“set…” y “set…”) para traspasar esta frontera. Así se habla de que un objeto
encapsula sus componentes (datos y métodos) y los oculta con los
modificadores de acceso.

Para que un objeto use un método de otro objeto, esta comunicación basada
en mensajes debe poder llamar al método adecuado por las características
del mensaje, ya que contiene la signatura o firma del método a ejecutar.

La signatura o firma de métodos


Es la combinación entre el nombre del método, cantidad, tipo de dato y
orden de los parámetros, es decir que si tengo un método llamado correr(int
a) y otro correr(String b), se llaman métodos polimórficos (Vivona, 2011).

Métodos polimórficos
La acción para escribir dos métodos con el mismo nombre pero diferente
signatura se llama sobrecarga y permite mantener el mismo nombre de
método. Con un cambio en el número, tipo y orden de los parámetros,
podremos escribir la respuesta ajustada a las necesidades del problema. Hay
que aclarar que en caso de funciones que tienen en su declaración el tipo de
dato de retorno no se pueden sobrecargar dos funciones con la misma firma
y diferentes tipos de dato de retorno. Esta situación se llama isomorfismo.

“Un objeto es polimórfico con otro cuando ambos responden a un mismo


mensaje de formas distintas. El mensaje en cuestion es polimórfico y

7
permite que haya polimorfismo entre dos o más objetos” (Vivona, 2012, p.
18).

En detalle, este fenómeno, sucede cuando uno de los métodos, al


reconocerse en la firma del mensaje, responde ejecutándose. La capacidad
de seleccionar en la clase origen del objeto, entre los métodos de mismo
nombre pero con distinta firma, y responder adecuadamente se denomina
despacho dinámico (dynamic dispatch).

Tomemos el ejemplo de un método del objeto que es una función, llamada


“entre” que esta devolverá o retornará el valor true (verdadero) si los
argumentos están ordenados, es decir, si el segundo valor, “b” está entre
“a” y “c”. “Estos métodos que realizan tests se llaman predicados” (Bailey,
2000, p. 99).

Aquí, consideraremos el método o predicado anterior para ver si un número


se ubica entre otros dos, esto es: dados los números a, b y c debemos
verificar si a ≤ b ≤ c. La solución es muy sencilla:

public static boolean entre(double a, double b, double c)


// devuelve true si a <= b <= c
{
return (a <= b) && (b <= c);
}

Considerando la cantidad de instrucciones que demandan un valor


booleano, es claramente útil disponer de funciones que devuelvan este tipo
de valores. Otra situación que necesitaría usar un predicado similar al
anterior sería para la verificación de si un número es primo o perfecto.

Recordemos que las comparaciones (como <=) devuelven un valor booleano


y, por lo tanto no tiene sentido (en Java) escribir la expresión a <= b <= c,
puesto que después de la primera evaluación (a <= b), estaríamos
comparando el resultado (es decir, un booleano) con un double (c).
Podríamos, también, haber escrito una función equivalente:

public static boolean entre(double a, double b, double c)


// post: devuelve true sii a <= b <= c
{
if ((a <= b) && (b <= c)) return true;
else return false;
}

Sin embargo, es más conveniente, por razones de sencillez, escribir la


función como se escribió por primera vez. Podemos también escribir

8
funciones que son útiles para manipular caracteres. Estas son usadas a
menudo para convertir caracteres leídos desde el teclado. Las funciones que
escribiremos usan el hecho de que los valores “a” a “z” y “A” a la “Z”
aparecen uno a continuación del otro y en orden. Nuestra primera función
testea si un carácter ingresado es una letra minúscula o no:

public static boolean esMinuscula(char c)


// post: devuelve true si c es letra minuscula
{
return (’a’ <= c) && (c <= ’z’);
}

Nótese que el cálculo que se hace en la función es igual al que hace la función
entre escrita más arriba. Escribamos ahora una función entre que trabaje en
caracteres:

public static boolean entre(char a, char b, char c)


// post: devuelve true sii a <= b <= c en el orden ASCII
{
return (a <= b) && (b <= c);
}

La función “entre” tiene diferentes implementaciones con diferente


signatura porque la primera “entre” recibe parametros de tipo char,
mientras que la definición de “entre” (inmediatamente antes) acepta
parametros de tipo double. El programa decide cual de las dos funciones
“entre” va ser ejecutada y lo decidirá en base al tipo de parámetros con los
que se la llama.

Esta sobrecarga del nombre es llamada polimorfismo. En esencia, hay una


sola función abstracta que puede recibir como parámetros distintos tipos.
Podemos usar la función “entre” para escribir esMinuscula.

También podemos escribir la función esMayuscula de esta manera:

public static boolean esMayuscula(char c)


// post: devuelve true si c es letra mayuscula
{
return entre(’A’,c,’Z’);
}

El uso más frecuente de la definición de sobrecarga de métodos es el que se


le dá a los constructores, ya que por definición deben tener todos el mismo
nombre que la clase. Esto hace que si se quieren distintas opciones de crear

9
objetos, se deberán escribir varios métodos con el mismo nombre y
diferentes parámetros.

El siguiente es un código de ejemplo de un método constructor simple, sin


sobrecarga:

Figura 6: Constructor de la clase MaquinaDeBoleto

Fuente: Barnes y Kolling, 2007, p. 27.

La siguiente versión de la clase tiene dos constructores con el mismo nombre


(requisito indispensable para un constructor) y distinta lista de argumentos.
En este caso, es porque el método constructor original no daba información
del saldo inicial que es mayor a cero y conocido al inicio de la operación en
situaciones especiales.

Figura 7: Constructor de la clase MaquinaDeBoleto versión 2

Fuente: Barnes y Kolling, 2007, p. 27.

10
El ejemplo anterior muestra que se aplica polimorfismo cuando se necesitan
varios constructores para las distintas situaciónes que debemos atender en
la gestión de los objetos en una aplicación y el despacho dinámico lo
permite.

El polimorfismo está basado en la biología celular, donde las


células poseen una frontera llamada pared celular la cual
oculta y protege el interiór de éstas células, las que se
comunican entre sí por medio de mensajes químicos. En la
pared celular se encuentran los receptores que son proteínas
que le permiten recibir los mensajes químicos ¡Despacho
Dinámico en la naturaleza!. (Vivona, 2011, p. 16).

11
Referencias
Bailey, D. A., y Bailey, D. W. (2000). Methods [Métodos]. En D. A. Bailey, Java
Elements: Principles of Programming in Java [Elementos de Java: Principios de
programación en Java] (pp. 90-101). Boston, MA: Mc Graw Hill.

Barnes, D., y Kolling, M. (2007). Programación Orientada a Objetos con Java.


Madrid: Pearson Educación.

RAE (2018) (a). Real Academia Española. Recuperado de:


http://dle.rae.es/?id=0CwVYCX Octubre 2018

RAE (2018) (b). Real Academia Española. Recuperado de:


http://dle.rae.es/?id=0CxZRfR Octubre 2018

Techopedia (2018). Techopedia explains Abstraction. Recuperado de:


http://dle.rae.es/?id=0CxZRfR Octubre 2018

Vivona, I. (2011). Programación Orientada a Objetos. En I. Vivona, Java (pp. 15-18).


Buenos Aires: Fox Andina.

12
Dos paradigmas
de Programación
(PE y POO)

Programación
Orientada a
Objetos

1
Dos paradigmas de
programación (PE y POO)
Introducción

Paradigma es una palabra Existen numerosos paradigmas de programación: modular, procedimental,


latina con origen griego, estructurado, orientado a eventos, a objetos, etcétera. Para complementar
que significa, según la
Real Academia Española
el material de la bibliografía obligatoria, haremos algunas marcaciones sobre
“Teoría o conjunto de el paradigma orientado a objetos y la programación estructurada, porque
teorías cuyo núcleo entendemos que hay una convivencia al escribir métodos, ya que en ellos
central se acepta sin puede decirse que estamos usando programación estructurada. Sea
cuestionar y que entonces armónica esta convivencia de paradigmas para que podamos
suministra la base y
modelo para resolver
escribir aplicaciones que cumplan con los requerimientos de los usuarios.
problemas y avanzar en
el conocimiento.” (Rae,
Programación estructurada (PE)
2017)
A medida que el uso de computadoras y programas se fue extendiendo,
aparecieron nuevos desafíos. Las universidades con sus científicos y las
empresas con sus inversiones en investigación fueron proponiendo nuevas
formas de programar, de manera que esta tarea fuera más eficiente y
efectiva. Así, surgieron diferentes paradigmas y, entre ellos, una forma de
programar que se llamó programación estructurada (PE), que parte del
principio de diseñar programas con un enfoque de arriba hacia abajo, lo que
significa que se comienza escribiendo las especificaciones del problema a
resolver y gradualmente se va refinando la solución dividiéndola en partes,
que también pueden ser divididas en más partes.

2
Figura 1: Enfoque top-down de la programacion estructurada

Fuente: Patterson Hume y Stephenson, 2000, p. 69.

La programación estructurada se basa en refinamiento


sucesivos: Se plantea una operación como un todo y se divide
en segmentos más sencillos o de menor complejidad. Una vez
terminado todos los segmentos del programa, se procede a
unificar las aplicaciones realizadas por el pool de
programadores. La programación estructurada propone
segregar los procesos en estructuras lo más simple posibles,
las cuales se conocen como secuencial, repetitiva, selectiva.
Combinando esquemas sencillos se pueden llegar a construir
sistemas amplios y complejos pero de facil entendimiento.
(lenguajesdeprogramacion, 2016, goo.gl/FYM2YI).

En este enfoque se da por supuesto que los datos son mantenidos


centralizados en un programa principal (main program) y que si un
procedimiento es cambiado, puede causar algun efecto que altere la forma
en que otro procedimiento funcione, si es que estos dos comparten los
datos. Se dice en este entorno que los datos son globales a todos los
procedimientos.

3
Figura 2: Los datos son centralizados y accedidos por programas.

Fuente: elaboracion propia.

La programación orientada a objetos (POO)

La POO tiene como fundamento la idea de agrupar en objetos a los métodos


y los datos, y que estos datos deben ser accedidos y modificados por estos
métodos propios, así, los otros objetos no podrían tener acceso directo a los
datos de otros objetos. Esta interacción será llevada a cabo por mensajes
entre objetos.

Se podría decir que un lenguaje que permite definir los tipos de datos, las
acciones sobre estos y que se puedan reusar, estaría cumpliendo la idea
central de la POO. La diferencia entre estos lenguajes se puede marcar por
los métodos de instanciación o creación de objetos que usan, por ejemplo,
las clases y, entre otros, los prototipos.

En esta materia estudiaremos, Java que usa a la clase como forma de crear
objetos.

Esta forma de trabajar le permite a Java poder instanciar objetos desde las
clases, crear nuevas clases en base a las clases preexistentes o clases-base y
hasta crear bibliotecas con clases para ser reusadas y que eviten tener que
escribir la solución a un problema ya resuelto.

4
Una clase es un molde, template o plantilla para construir múltiples
instancias de objetos similares que pueden crearse.

Gracias a la herencia, todos los objetos tendrán los mismos componentes


que indica la clase (métodos y atributos), lo que servirá para construir
aplicaciones que usen a los objetos, trabajando en conjunto, para resolver
problemas muy complejos con múltiples características de calidad de
software.

En la POO se aplica PE dentro de los métodos de las clases y así convive con
mejorando el paradigma orientado a objetos.

5
Referencias
Lenguajes de programación. (2016). Programación estructurada.
Recuperado de http://www.lenguajes-de-
programacion.com/programacion-estructurada.shtml

Patterson Hume, J. N., y Stephenson, C. (2000). A brief history of


Programming. En J. N. Patterson Hume y C. Stephenson, Introduction to
programming in Java (pp 6-13). Toronto: Holt Software Associates.

Real Academia Española. (2017). Diccionario de la Lengua Española


“Paradigma” Recuperado de: http://dle.rae.es/?id=RpXSRZJ

6
Lenguajes de
Programación

Programación
Orientada a
Objetos

1
Lenguajes de programación
Las computadoras funcionan por la unión del hardware, es decir, sus
componentes físicos, circuitos, discos, memoria, pantalla, teclado y mouse,
entre otros, con el software, que son los programas que le dan indicaciones
a los anteriores para que funcionen de la manera en que lo hacen. Existen
dintintos tipos de programas que necesitan comunicarse entre sí y para
entenderlos mejor, podemos distinguir entre ellos al sistema operativo, que
es el programa principal que se comunica a traves de los manejadores o
drivers (otro tipo de programa) con los dispositivos físicos, para realizar el
trabajo del todo el sistema completo y con las aplicaciones (otro tipo mas de
software) que el usuario ha determinado ejecutar en la computadora. Así,
sistema operativo, manejadores o drivers, y aplicaciones son los tipos de
programas vistos desde una clasificación inicial del software y que están
escritos en algún lenguaje de programación como C, C++, Java, entre otros.

Esta lectura contiene una breve historia de la programación basada en el


desarrollo de los primeros lenguajes de programación hasta llegar a Java.

Una breve historia de la programación

La persona considerada como la primera programadora de computadoras


fue Ada Byron, condesa de Lovelace, la hija del poeta romántico inglés Lord
Byron. Era una atípica mujer en el siglo XIX temprano, ya que era autodidácta
en matematicas. Esto era a la vez notable y la única manera de ser
matemática para una mujer, ya que en ese momento a las mujeres no se les
permitía ni siquiera entrar en una biblioteca y mucho menos asistir a la
universidad. Durante sus estudios, Ada Byron se comunicó a través de cartas
con muchos de los matemáticos ingleses importantes y finalmente, llegó a
trabajar con Charles Babbage, mientras este se concentraba en diseñar el
hardware de la máquina analítica, una calculadora mecánica que fue
diseñada para realizar cálculos complejos. Por esta relación con Babbage,
Ada Byron se convirtió en la primera persona en desarrollar un conjunto de
instrucciones para la máquina analítica de Babbage, que luego se llamó
programa de computadora. Dada la epoca de este suceso, Ada nunca pudo
ver funcionar un programa en una computadora, ya que faltarían todavía
más de un siglo para que estas se construyeran por primera vez. Pero Ada
Byron ya habia creado el concepto de programa.

2
Cuando las computadoras aparecieron

A medida que el hardware evolucionó desde los primeros prototipos o


modelos a las máquinas rápidas y potentes de hoy en día, las formas en que
la información y las instrucciones fueron preparadas para la computadora
también cambiaron radicalmente. Con el tiempo, el énfasis paso de hacer las
instrucciones lo suficientemente simples para que la computadora
entendiera, a hacerlas lo suficientemente parecida a la lengua hablada para
que las personas lo puedieran escribir y fueran ejecutados por una
computadora.

Computadoras como ENIAC y EDVAC almacenaban


información, tanto números como instrucciones de
programa, como grupos de dígitos binarios 0 y 1.

Cada instrucción se compone a menudo de dos partes, un


grupo de bits (dígitos binarios) que representan la operación
a realizar, y un grupo que representa el operando, es decir, la
dirección de máquina de los datos a ser operados.

Un programa consistía en una serie de instrucciones


escritas en este lenguaje de máquina. (Patterson Hume y
Stephenson, 2000, p. 7).

Entonces, en los primeros tiempos, el lenguaje de máquina requería que se


escribieran series muy largas de instrucciones numeradas y con los códigos
binarios para los diferentes comandos que tenía el set de instrucción de la
máquina. También se debía llevar un registro de las direcciones de
almacenamiento de los datos y las instrucciones. Como resultado, un solo
programa, a menudo, tomaba meses para escribirse y no eran raro que
tuvieran errores difíciles de encontrar.

Lenguajes de ensamblaje

Una gran mejora en los lenguajes de programación comenzó en la década


de 1950 con el desarrollo de lenguajes simbólicos de máquina, llamados
lenguajes de ensamblaje.

“Los lenguajes de ensamblaje permitieron al programador escribir


instrucciones usando símbolos y letras en lugar de códigos de operación
binarios en un programa fuente. El ensamblador luego traduce estas
instrucciones escritas simples en lenguaje de máquina en un programa
objeto” (Patterson Hume y Stephenson, 2000, p. 7).

3
Los lenguajes de ensamblaje tienen una serie de ventajas en comparación
con el lenguaje de máquina, por que son más fáciles:

 y rápidos en ser escritos;


 de depurar (encontrar y corregir errores);
 de cambiar en una fecha posterior.

Pero los lenguajes de ensamblaje también tienen un inconveniente


importante. Debido a que la comunicación se lleva a cabo directamente con
la máquina, cada lenguaje de ensamblaje está diseñado para una marca
específica y el modelo de procesador de la computadora. Esto significa que
un programa escrito para ejecutarse en una computadora no funcionará en
otra. Por lo tanto, se dice que los lenguajes de ensamblaje están orientados
a la máquina.

El direccionamiento simbólico era otro elemento importante de los


lenguajes de programación mas novedosos. El direccionamiento simbólico
implicaba el uso de símbolos para representar la asignación de direcciones
de almacenamiento a datos. Los programadores podían, así, crear nombres
simbólicos para representar los elementos de datos y estos nombres podían
ser utilizados a lo largo de un programa. Los programadores ya no tenían
que asignar direcciones de máquina reales a elementos de datos simbólicos.
El procesador asigna automáticamente esas ubicaciones de
almacenamiento cuando el programa es ejecutado.

Lenguajes de alto nivel

El desarrollo de lenguajes de alto nivel fue el siguiente paso importante en


la informática. Al igual que un programa escrito en lenguaje ensamblador,
un programa escrito en un lenguaje de alto nivel todavía necesitaba ser
traducido al código de la máquina. Los lenguajes de alto nivel incluían su
propio software de traducción para realizar esta tarea. El programa de
traducción se denomina compilador. Los compiladores a menudo generan
muchas instrucciones de máquina para cada instrucción de código fuente.
Hoy en día, sin embargo, muchas computadoras personales utilizan un
intérprete en lugar de un compilador. Un compilador traduce el programa
fuente en código objeto y luego lo ejecuta. El intérprete convierte cada
instrucción de programa de origen en lenguaje de máquina cada vez que se
ejecuta la instrucción. No guarda el código objeto.

Los lenguajes de alto nivel proporcionan una serie de beneficios:

4
 liberan de preocupaciones acerca de los detalles de máquina de bajo
nivel, como el direccionamiento de memoria y la dependencia de la
máquina;
 se pueden ejecutar en diferentes marcas de ordenadores;
 son más fáciles de usar que los lenguajes de ensamblaje;
 son más fáciles de aprender para los programadores.

A continuación presentamos un ejemplo de una instrucción simple que


muestra el lenguaje de alto nivel, el lenguaje ensamblador y las versiones
binarias.

Figura 1: Muestras de codigo de lenguajes

Fuente: adaptado de Patterson Hume y Stephenson, 2000.

Hasta finales de los años 50, las computadoras todavía se usaban


principalmente para el cálculo matemático y científico. Las computadoras
utilizaron la aritmética binaria y no fue hasta que las máquinas fueron
desarrolladas para usar la aritmética decimal que comenzaron a ser
prácticas para los cálculos de negocio.

El principal problema con la programación en los primeros días fue que era
un trabajo largo y difícil y los programas a menudo no funcionaban. El
creciente reconocimiento del uso potencial de las computadoras en muchos

5
campos llevó a la evolución de los lenguajes de programación modernos,
que se volvieron más fáciles de desarrollar, usar y modificar.

En 1954, John Backus comenzó a dirigir un comité patrocinado por IBM para
desarrollar un nuevo lenguaje de programación científico-matemático. En
1957, este comité introdujo un nuevo lenguaje de alto nivel denominado
FORTRAN (formula translator) para la computadora IBM 704. FORTRAN ganó
amplia aceptación, especialmente entre los científicos y los estadísticos,
debido a su utilidad para expresar las ecuaciones matemáticas. Muchas
versiones de FORTRAN se han desarrollado ha lo largo de los años.

A medida que más empresas empezaron a apreciar el potencial de las


computadoras, se desarrollaron nuevos idiomas para satisfacer sus
necesidades particulares. En 1959, Grace Murray Hopper ayudó a crear
COBOL (Common business-oriented language). COBOL fue diseñado para
procesar datos de negocios y durante muchos años fue utilizado, en gran
medida, por los seguros y la industria bancaria, entre otros. El lenguaje
ALGOL también fue desarrollado por un comité internacional para uso
científico.

En 1957, John McCarthy en el Massachusetts Institute of Technology


desarrolló LISP, que fue diseñado para apoyar la investigación en el campo
de la inteligencia artificial (Al).

Los creadores del BASIC fueron John George Kemeny y


Thomas Eugene Kurtz en el año 1964. Fue inventado para
permitir a los estudiantes escribir programas usando
terminales de computador de tiempo compartido. Con el
BASIC se quiso hacer un lenguaje de programación mucho
más sencillo que los que existían por aquel entonces. Porque
los lenguajes que existían requerían tener conocimiento
específicos en lenguajes más complejos que eran hechos a
medida, principalmente para científicos y matemáticos.
(Felipe U.,2006).

LOGO fue desarrollado en la década de 1960 por Seymour Papert en el


Instituto de Tecnología de Massachusetts. El objetivo de Papert era ayudar
a los niños pequeños a explorar un entorno matemático utilizando una
tortuga en la pantalla para dibujar figuras y crear animaciones sencillas.

6
Programación estructurada. Una forma de escribir los programas

El paso de la programación no estructurada al paradigma estructurado


de programación fue una mejora significativa en la forma en que se
escribieron y desarrollaron los programas. Siguiendo las reglas asociadas,
con la programación estructurada, los programadores hicieron que la lógica
de sus programas fuese más fácil de seguir. Esto significaba que era más fácil
localizar y corregir errores y hacer cambios a esos programas según lo
requerido.

Pero la realidad es que incluso los programas estructurados son a menudo


consumidores de tiempo para escribir, difíciles de entender e inflexibles,
dado que son diseñados para una cumplir una tarea específica y de un modo
específico.

En 1970, Pascal (nombrado así por el matemático francés del siglo XVII Blaise
Pascal) fue desarrollado por Niklaus Wirth en el Instituto Federal de
Tecnología de Suiza. Uno de los principales beneficios de Pascal sobre BASIC
fue su diseño para apoyar los conceptos de programación estructurada.

“En el caso de lenguas anteriores como BASIC, la estructura de un programa


puede ser bastante compleja e intentar seguir la Secuencia de ejecución
(cómo se ejecuta un programa) era como tratar de desenredar un plato de
espaguetis” (Patterson Hume y Stephenson, 2000, p. 11).

Los lenguajes de alto nivel considerados estructurados usan dentro del


programa algunas sentencias que controlan el flujo de información, a
menudo denominados estructuras de control, que son tres, a saber:

Estructura secuencial: las sentencias se ejecutan una tras otra en el orden


en que se escriben.
Estructura repetitiva: un grupo de declaraciones debe ser ejecutado
repetidamente.
Estructura de bifurcación: se selecciona una alternativa que contiene una o
mas sentencias para su ejecución a partir de un número de 1 a n alternativas,
según la estructura.

Dentro de un programa estructurado, estas estructuras de control están


organizadas para que el programa pueda leerse de arriba a abajo. Cada
estructura permite solo una entrada y una salida. La indentación de las
instrucciones en un programa ayuda a alguien que lee un programa a
entender su lógica más fácilmente.

7
El término programación estructurada ahora se relaciona no
sólo con la lógica de control del programa, sino con cómo se
diseñan y desarrollan los programas. Hoy en día, las personas
que hablan de programación estructurada, a menudo se
refieren a una forma sistemática de analizar los problemas
informáticos y diseñar soluciones llamadas de arriba a abajo.
En la programación de arriba abajo, el problema se
descompone en una serie de problemas más pequeños, y a
cada uno de ellos se los resuelve. Una vez que se resuelven
los problemas más pequeños, las soluciones se combinan
para resolver el problema más grande. (Patterson Hume y
Stephenson, 2000, p. 9).

El antepasado remoto de Java: el lenguaje C

En Bell Labs, Dennis Ritchie y Brian Kernighan, a principios de los 70,


desarrollaron un lenguaje de programación llamado C. Este lenguaje
permitía un fácil acceso al hardware y era muy eficiente. Fue diseñado para
programar sistemas grandes, por lo que se convirtió en el lenguage de
programación favorito de los programadores de sistemas operativos y
drivers de dispositivos. Se utilizó para producir el sistema operativo UNIX y
su derivado Linux.

Línea de tiempo de los lenguajes de programación


Para una mejor comprension y estudio del tema, hemos buscado la siguiente
imagen donde se grafican en secuencia, en base al año de aparicion, los
lenguajes de programación.

8
Figura 2: Línea de tiempo de los lenguajes de programación

Fuente: (Edmond, 2012, http://goo.gl/RAjfGU)

9
Programación orientada a objetos
La situación de la notable caída de los costos de equipamiento y una
equivalente subida de los costos de desarrollos de software desataron lo que
se llamó la crisis del software (OTAN, 1968).

El acuciante problema del software es que no se terminaba o que los equipos


de trabajo tenían bajo rendimiento. Hasta ese momento, la actitud de
muchas de las personas involucradas en la industria de la computación había
sido tratar a las computadoras casi como si fueran una industria artesanal
(Kimble, 2016). Como los programas y las tareas que los mismos
desempeñan se han vuelto más complejas, los programadores, científicos y
académicos han trabajado, desde aquel planteo de crisis del software,
durante mucho tiempo para encontrar nuevas maneras de pensar,
desarrollar y mantener a través del tiempo a estos programas.

Es así que una nueva forma de organizar grandes programas, la


Programación Orientada a Objetos (POO), es lo que surge como respuesta
a esta crisis del software, para aumentar la productividad y eficiencia al
escribir programas y sistemas a traves de, entre otras estrategias, el reuso
de software.

“El término Paradigma de Programación se refiere al conjunto de ideas que


constituye la base de un modo particular de programación” (Patterson
Hume y Stephenson, 2000, p. 13).

La POO es una forma de diseñar y escribir programas basados


en el concepto de que un programa puede ser creado como
una colección de objetos que trabajan juntos. Cada uno de
estos objetos es un conjunto de datos y métodos que operan
en este conjunto de datos. Los detalles de cómo se guardan
los datos y cómo funcionan los métodos son ocultados del
usuario. (Alvarez, M. , 2001).

Se crea un objeto a partir de una clase y, a partir de ella, se pueden crear


muchos de estos objetos. Una clase puede heredar (o tomar prestado)
características de otra clase. Las clases realizan tareas específicas también y
pueden ser reutilizadas en otros programas, acelerando así el desarrollo de
programas. Los lenguajes actuales de POO incluyen a C ++ (desarrollado por
Bjarne Stroustrup), Java (desarrollado por James Gosling) y Object Oriented
Turing (desarrollado por Ric Holt), entre otros.

10
Referencias
Alvarez, M. (2001) “Qué es la programacion orientada a objetos”
Recuperado de: https://desarrolloweb.com/articulos/499.php

Edmond, D (2012) “The Evolution of Programming [Infographic]”


Recuperado de: http://siliconangle.com/blog/2012/02/29/the-
evolution-of-programming-infographic/

Felipe U., (2006) “Lenguaje de programación Basic”. Recuperado de


http://www.larevistainformatica.com/BASIC.htm

J. N. Patterson Hume, C. Stephenson (2000) “A brief history of


Programming” en J. N. Patterson Hume, C. Stephenson, “Introduction to
programming in Java” (pp 6-13). Toronto: Holt Software Associates Inc.

Kimble, Ch. (2016). The Software Crisis. Some Notes on the background and
nature of the software crisis. Recuperado de: http://www.chris-
kimble.com/Courses/World_Med_MBA/Software_Crisis.html

OTAN (1996) “The NATO Software Engineering Conferences”. Dagstuhl-


Seminar 9635: "History of Software Engineering" Schloss Dagstuhl.
Recuperado de:
http://homepages.cs.ncl.ac.uk/brian.randell/NATO/NATOReports/

11
Más sobre Clases
y Métodos

Programación
Orientada a
Objetos

1
Más sobre clases
Las clases como forma de encapsular
En Java, las clases son usadas para agrupar y manejar los detalles de
métodos relacionados. Por ejemplo, la clase de sistema provista por el JDK,
java.lang. Math, contiene funciones matemáticas simples y funciones
trigonométricas entre otras. De manera similar, cuando construimos un
programa, escribimos una sola clase que contiene todos los métodos que
sirven para correr nuestro programa.

Una aplicación típica de POO debiera consistir en varias clases y una de ellas,
solo una, contener el único punto de inicio: el método main junto a los
métodos generales, es decir que sirven a toda a la aplicación, por ejemplo,
como un menú de llamada a los distintos métodos ubicados en las restantes
clases de la aplicación. Cuando todos los métodos que necesitamos han sido
escritos, deberán ser convocados desde esta clase principal. Esta clase es
nuestro programa. Las clases, a su vez, pueden estar contenidas en packages
(paquetes). Las clases de sistema, por ejemplo la clase Math mencionada
antes, se encuentra en el package java.lang. A veces, el nombre de la clase
es interpretado como el path de directorios donde está ubicado el package.
La mayoría de los programadores escriben sus clases dentro del directorio
donde están trabajando. Este es llamado el default package (paquete por
defecto). Todas las clases dentro del default package están disponibles para
el programa principal (o la clase donde está el método main). Luego, es
posible que un programa esté compuesto por métodos guardados en
diferentes clases. En un videojuego uno podría imaginar que una clase
contiene todos los métodos que soportan los gráficos, otra guarda los
métodos de puntuación y la última guarda las rutinas relacionadas con el
dispositivo de input (teclado, mouse, etc.). Con esto queda claro que el
método main debe ser declarado public, de otra forma no podríamos correr
el programa.

Nombres de métodos
Los programas grandes conllevan un esfuerzo importante en su
planificación. En la práctica, la construcción de programas no triviales
requiere el uso de un gran número de componentes, usualmente asociados
La estructura de un
a diferentes funciones lógicas o distintos objetos dentro de los programas.
programa debería
modelar la estructura
del problema. En Java este tipo de modularización depende fuertemente del uso de
métodos.

2
Si consideramos que tenemos que realizar las siguientes tareas de
programación:

 El cálculo de una lista del primer millón de números primos. Es claro que
un componente de ese programa es calcular si un número es o no primo.
 La construcción de un procesador de textos.
 El manejo de la ventana de ayuda es una porción lógica aislada del
programa.
 El lanzamiento de una nave espacial. Las pruebas previas al vuelo las hace
(en algún nivel) una entidad lógica aislada. A su vez, estas pruebas pueden
estar agrupadas en varios módulos.

En cada una de estas tareas, algunas características aparecen aisladas. Aún


cuando no sepamos como están programadas, nosotros podemos estar
confiados de que el código que las soporta está aislado dentro del programa.

En la mayoría de los lenguajes de programación, el método (procedimiento


o función) es usado para implementar código que realiza una tarea
específica y bien documentada. El método organizacional que identifica los
componentes lógicos de un proceso complejo y realiza esas tareas con sus
propios procedimientos es llamado abstracción procedural y es la forma
más básica que se encuentra en la mayoría de los lenguajes de
programación.

En realidad, ya hemos visto un método: el método main. Siempre que


corremos una aplicación, Java, localiza el método main y ejecuta sus
instrucciones en orden. Usted puede probar esto escribiendo un programa
con dos métodos: main y maine. Cuando corremos el programa, las únicas
instrucciones que se ejecutan son aquellas que se encuentran en el método
main. La declaración del método main siempre debe ser:

public static void main(String args[])


Siguiendo CamelCase,
en Java los nombres La palabra reservada public indica que este método está disponible para ser
de métodos se inician
usado fuera de la definición de clase que lo contiene. En particular, esto hace
con minúscula y las
restantes palabras que posible que se pueda llamar al método main para que sea corrido. Si el
forman el nombre se método no fuera public, podría ser declarado protected o private, haciendo
inician con mayúscula. imposible que desde otra clase se lo pueda usar o referenciar.

La palabra reservada static indica que este método siempre está disponible.

3
Métodos: ¿procedimientos o funciones?
La palabra reservada void indica que, una vez completado, el método no deja
o devuelve nada, los métodos que tienen esta definición se llaman
procedimientos, como veremos enseguida.

Puede parecer extraño que nosotros podamos producir una respuesta al


completar la ejecución del programa o método, pero existen métodos (por
ejemplo, el método que calcula la raíz cuadrada de un número) que están
diseñados para producir valores para ser usados en el método que lo
convocó. Estos métodos que devuelven valores al finalizar son llamados
funciones y se caracterizan porque en vez de void tienen la indicación del
tipo de dato que devuelven. Los que no producen valores de respuestas y
finalizan sin ninguna devolución directa son llamados procedimientos.

Para definir sin ambigüedad qué método se debe a ejecutar, el nombre


completo del método debe incluir el nombre de la clase que lo contiene.

En la mayoría de los casos cuando usamos métodos comunes de paquetes


provistos en el mismo lenguaje en la clase “Standard”, el nombre de la clase
puede ser evitado, pero en otros casos (por ejemplo Math.sin), Java
considera un error omitir el nombre de la clase.

Completa el nombre (o signatura) del método, entre paréntesis, la lista de


uno o más parámetros. Los parámetros describen los datos o recursos
necesarios que deben estar disponibles antes de que el método se aplique.
Las declaraciones de parámetros son similares a las declaraciones de
variables. Los parámetros múltiples son separados con comas. En el método
main tenemos un parámetro: un arreglo (indicado por los corchetes [ ]) de
cadenas (string). Este arreglo es simplemente una lista de cadenas que
podría ser útil a nuestro método main. Todos los métodos main deben ser
declarados de esta manera.

“Java identifica a los métodos por la signatura que está


determinada por su nombre y sus parámetros. Dos métodos
no pueden tener la misma signatura. En particular en Java, no
es posible declarar una función y un procedimiento con la
misma signatura. Es importante observar que si dos métodos
tiene el mismo nombre pero diferentes parámetros,
entonces, tienen signatura distinta y Java los compilará
correctamente. “ (Bailey, 2010)

4
Como un ejemplo de declaración de un método, consideremos la
declaración del método cos que está dentro de la clase Math. Su declaración
es:

public static double cos(double theta)

Los diseñadores de la clase Math estaba interesados en que todos pudieran


hacer uso de la función cos (coseno de un ángulo), por eso la declararon
public. La función está disponible en cada momento, pues es declarada
static. Para poder ser utilizada, la función necesita de un valor de entrada,
simbolizado por theta, un número decimal (double) que representa un
ángulo en radianes. La función devuelve un double entre −1,0 y 1,0.

La función sin (seno) tiene una declaración similar, aunque, obviamente, su


nombre es sin.

El método lineTo es un procedimiento contenido en la clase


DrawingWindow. A diferencia de otros métodos vistos, está solo disponible
cuando la DrawingWindow está funcionando. Su comportamiento,
entonces, es dinámico. Su declaración, en aquella clase, es:

public void lineTo(int x, int y)

Vale aclarar que estamos viendo declaraciones en sus clases de origen y que
para ser usados, Java debe conocer la clase de origen que lo contiene, en
algún caso con Math.’nombre’ y en otros casos con el prefijo de un objeto
creado a partir de la clase correspondiente.

La palabra void indica que lineTo no devuelve un valor. El efecto de invocar


este método es que se dibuja una línea en la DrawingWindow.

El procedimiento o método que tiene la palabra void en su definición provee


un mecanismo para encapsular, abstraer u ocultar los detalles de un proceso
particular. Por ejemplo, podríamos querer escribir un procedimiento que
simplemente espere por un segundo. Podría escribirse como sigue:

public static void espereUnSegundo()


{
long ahora = System.currentTimeMillis();
long despues = ahora + 1000; // un segundo son 1000 milisegundos
while (System.currentTimeMillis() < despues)
{
// nada!
}
}

5
Es claro que este procedimiento tiene un finalidad muy simple. Al usuario (el
programador) no le interesa conocer los detalles de implementación y por
lo tanto, preferirá usar este método. Estos detalles son, por ejemplo, que el
tiempo en Java se mide en milisegundos o que necesitamos un ciclo para
implementar el procedimiento. Para llamar, ejecutar o invocar este
procedimiento, tipeamos el nombre seguido por una lista vacía de
parámetros:

public static void main(String args[])


{
espereUnSegundo();
}

La lista de parámetros es vacía, pues este proceso (esperar un segundo) no


depende de ningún input que el usuario o el programa le deba dar.

¿Cuál es el efecto de correr el procedimiento? La computadora aparenta


detenerse por un segundo.

Teniendo en mente un procedimiento más versátil, podríamos preguntar:


¿podemos detener la computadora un número arbitrario de segundos? Por
supuesto que sí:

public static void espereNSegundos (int number)


{
int i;
for (i = 0; i < number; i++)
{
espereUnSegundo();
}
}

Aquí decimos que number es un parámetro formal, es decir, que


representará, dentro del método, el número de segundos que se va a
esperar.

Este número es claramente referenciado en las instrucciones que siguen:


hacemos un ciclo number veces cuando llamamos wait1second. La variable
que controla ese ciclo, i, es una variable local . Mantiene un valor mientras
el ciclo es activo.

Observemos que si no conocemos el valor de number, no podemos correr el


método. Es necesario, entonces, tener este número antes de que el método
sea invocado. Este número es llamado el parámetro real o argumento real.

6
Nosotros especificamos el parámetro real cuando llamamos a un
procedimiento.

espereNSegundos(60/5);

En este caso, la computadora detendrá la ejecución del programa por un


quinto de minuto o 12 segundos. Cualquier expresión que resulte en un int
es válida como parámetro real en este método. Este proceso (pasar de un
parámetro real a un parámetro formal) sirve para inicializar los valores de
los parámetros formales del método antes de que el método comience a
correr. Este proceso es llamado pasaje de parámetros. Debemos aclarar que
el método, en este caso, espera un int y que si el parámetro real es un
double, esto causará problemas.

7
Referencias
Bailey, D. A., & Bailey, D. W. (2000). “Methods” (pp. en Bailey, D. A. “Java
Elements: Principles of Programming in Java”. Boston, MA: Mc Graw Hill

8
Variables y
Constantes en
Java

Programación
Orientada a
Objetos

1
Variables y constantes en Java
Uso de Java Java es un lenguaje fuertemente tipado, lo que significa que el almacenado
de datos en el programa debe ser en variables previamente declaradas que
"A pesar de ser deben tener algún tipo de dato asignado. Esto permite al compilador
internamente anticipar el uso que le dará a los datos y reservar lugar en la memoria para
complejo, Java tiene ellos. También le permite al compilador controlar que el uso de los datos es
una sensación de
consistente con los tipos que se han declarado.
simplicidad inicial”
(Beneke, 2015,
Como habíamos mencionado, el estado de un programa está determinado
goo.gl/OKF1oc).
por las variables y constantes dentro del programa. Las variables no solo
nos dan el estado inicial y final del programa, sino que van dando, paso a
paso, los estados intermedios por los que el programa pasa.

En esta lectura veremos los tipos de datos primitivos que representan las
formas más simples de datos, incluidos enteros y caracteres.

Veamos un sencillo ejemplo:


7 es de tipo entero, mientras 7.0 es de tipo punto flotante (lo que
usualmente llamamos números decimales) y 7 es un carácter.

Aunque 7 y 7.0 tienen el mismo valor aritmético, Java no los considera


iguales (desde el punto de vista de la programación), pues tienen diferente
tipo. Por otro lado 7 ya no representa un número, sino el carácter y Java lo
considera una letra y no un número.

Otros identificadores mantienen el mismo valor durante todo el programa


(por ejemplo, un identificador que indique MESESPORAÑO). Este
identificador corresponde a una constante y será declarada de forma
especial.

No parece tener sentido ponerle nombre a las constantes, pues podríamos


escribir el valor de la constante cada vez que aparece en el programa. Sin
embargo, si se le da nombre a las constantes y si por alguna razón
queremos cambiar su valor, solo debemos cambiar una línea de
programación donde se la define y se le asigna el valor de la constante y
luego, compilar el archivo .java para obtener el archivo .class con el valor
cambiado (Programar ya, 2015).

Como mencionamos anteriormente, las variables nos sirven para observar


los distintos estados de un programa. Para declarar una variable de tipo int,
debemos incluir sentencias como los siguientes ejemplos:

 int i; // “i” es usado frecuentemente como un contador;

2
 int j,k; //dos variables en una declaración de tipo de datos int.

Una declaración de tipo de dato que tendrá el identificador le sirve al


compilador para reservar espacio para guardar un valor, en este caso, de
Claridad de código tipo int. Las declaraciones deben aparecer antes de que la variable sea
"La legibilidad es usada por primera vez. En Java, las declaraciones son instrucciones simples
crítica porque, con el
y deben terminar con punto y coma (;).
software, la cantidad
de tiempo que pasas
A una variable se le puede asignar un valor haciendo una asignación. Por
escribiendo un pedazo
ejemplo, la expresión:
de código que entra en
producción es
microscópico
j = 1200
comparado con el
tiempo que tú y tus le asigna a la variable de la izquierda (j) el valor de la derecha (1200). La
sucesores pasarán variable retiene ese valor hasta que se le asigne otro valor y hasta el final
leyéndolo" (Beneke, de la ejecución del programa.
2015,
goo.gl/OKF1oc). Si miramos a = como un operador, este operador devuelve el valor
asignado a la variable y este valor puede ser usado en una expresión más
grande. Por ejemplo,

int miEdad, tuEdad;


tuEdad = (miEdad = 14);

Luego de declararlas como int, le asigna 14 a miEdad y ese contenido lo


asigna a tuEdad. Como se puede observar en la tabla 1, con los operadores
Java, el operador = es asociativo a derecha, con lo cual la asignación
anterior es equivalente a la expresión:

tuEdad = miEdad = 14;

que es la forma que más se utiliza. También se utiliza una tercera variante
equivalente:

miEdad = 14;
tuEdad = miEdad;

3
Tabla 1 : Operadores Java

Operador Significado Asociativo Orden de Tipos


por precedencia aplicables
var++ var- Postincremento/decre - 8 Alfanumérico
- m.
++var --- Preincremento/decrem - 8 Alfanumérico
var .
! NO lógico, negación derecha 7 Booleanos
* / Producto, división y izquierda 6 Alfanumérico
% resto
+ - Suma, resta Izquierda 5 Alfanumérico
< <= > Comparación de orden Izquierda 4 Alfanumérico
>=
== != Pruebas de igualdad Izquierda 3 Todos
&& Y lógico Izquierda 2 Booleanos
|| O lógico izquierda 1 Booleanos
= Asignación Derecha 0 Todos

Fuente: elaboración propia.

El orden de precedencia indica que los valores mas altos corresponden a


los operadores que van a ser evaluados primero, a menos que se indique lo
contrario con el uso de paréntesis. Los tipos alfanuméricos incluyen a int,
long, float, double y char (que es convertido automáticamente en int).

Si una variable es declarada, pero no se le asigna un valor, entonces no


debería ser utilizada. Todas las variables de un programa deben ser
inicializadas asignándoles el valor que se considere más útil. Por ejemplo,
podría ser razonable inicializar con 0 una variable que acumula una suma o
con 1 una variable que acumula productos. Para facilitar estos
procedimientos, Java nos permite inicializar las variables cuando las
declaramos, por ejemplo:

int miEdad = 14

4
Inicialice las variables antes de usarlas

Java considera las constantes como un tipo especial de variables a las


cuales se les puede asignar un solo valor. Este valor es llamado el valor final
y se indica agregando al comienzo de la declaración el modificador final:
¡Recordar!
Las constantes de Java, final int MAX = 2147483647; // el entero mas grande de Java
según CamelCase, final int SEGUNDOSAÑO = 365*24*60*60 //segundos en un año no bisiesto
deben ir en
mayúsculas. El último ejemplo muestra que en el momento de la asignación podemos
también calcular el valor de la variable o constante.

Tipos de datos primitivos


Java proporciona ocho tipos de datos primitivos, que pueden ser usados
para operaciones básicas.

Tabla 2: Tipos de datos primitivos

Nombre Tipo y tamaño Rango de valores


byte Entero, 1 byte -128 a 127
short Entero, 2 bytes -32768 a 32767
int Entero, 4 bytes -2**31 a (2**31) -1
long Entero, 8 bytes -2**63 a (2**63)-1
float Decimal, 4 bytes Muy grande
double Decimal, 8 bytes Muy grande
Char Carácter simple, 2 0 a 65535
bytes
Boolean Valor lógico true o false

Fuente: elaboración propia.

5
Tipo de datos entero

Ya estamos en condiciones de diseñar programas sencillos que usen


números enteros. Computemos la suma de los primeros cinco números
naturales.

Un entero o int, i, mantiene el valor del número entero que debe ser
acumulado a la suma y otro entero, sum, mantiene los valores intermedios
de la suma.

Archivo CalculoSuma.java
// Calcula la suma de los primeros cinco numeros naturales
public class CalculoSuma {
public static void main(String args[])
{
int suma = 0;
int a = 1;
suma = suma + a; // suma vale 1
a = a+1; // a vale 2
suma = suma + i; // suma vale 3
a = a+1; // ahora a vale 3
suma = suma + a; // suma vale 6
a = a+1; // ahora a vale 4
suma = suma + a; // ahora suma vale 10
a = a+1; // ahora a vale 5
suma = suma + a; // ahora suma vale 15
System.out.println(suma); // muestra el valor de suma
}
}

Es bastante tedioso que para un programa tan sencillo se deba tipear


tanto, más aún cuando repetimos dos instrucciones (i = i + 1 y sum = sum +
i) cinco veces cada una. Veremos más adelante que existen varios métodos
para realizar estas repeticiones en forma concisa (observa que, en realidad,
este problema se resuelve matemáticamente en forma más sencilla: la
suma de los primeros n números naturales es: n(n + 1)/2).

El rango de int es lo suficientemente grande como para abarcar casi todos


los casos que necesitaremos. Sin embargo, de hacer falta, Java provee el
tipo long para números mucho más grandes.

Los enteros de tipo long reciben los valores con una L al final del número,
por ejemplo:

6
final long VELOCIDADLUZ = 300000000L //velocidad de la luz en metros por
segundo

La anterior es una declaración válida. No es conveniente trabajar con long


si no es necesario, puesto que ocupan mucho más lugar en memoria que
los int. Los números de tipo long permiten escribir todos los números
enteros de hasta 18 cifras.

Veamos ahora formas equivalentes de realizar asignaciones. La expresión


sum += i es equivalente a sum = sum + i.

Las expresiones -= i y *=i son expresiones análogas para la resta y el


producto. Finalmente, incrementar o decrecer una variable en uno se
puede escribir como i++ o i--, respectivamente.

Si la variable ocurre en una expresión, entonces esta es cambiada después


de ser usada. En cambio, cuando ponemos ++i o --i, la variable se
incrementa (o la hacemos decrecer) antes de ser usada. Con estas
convenciones, el programa anterior se puede reescribir:

archivo Suma.java
// Calculara la adicion de los primeros cinco números naturales

public class Suma {


public static void main(String args[])
{
int suma = 0;
int i = 1;
suma += i; // la suma vale 1
i++; // i vale 2
suma += i; // la suma vale 3
i++; // i vale 3
suma += i; // la suma vale 6
i++; // i vale 4
suma += i; // la suma vale 10
i++; // i vale 5
suma += i; // suma vale 15
System.out.println(sum);
}
}

7
Tipo de datos numéricos de punto flotante

Los números de punto flotante son aquellos que escribimos con decimales.
Aunque nosotros estamos acostumbrados a escribir los decimales después
de una coma, Java usa la convención de escribir los decimales después de
un punto (.). Por ejemplo, nosotros diríamos tres coma veinticinco; en Java
lo escribimos 3.25. Una notación muy usada para escribir números muy
grandes o muy pequeños es la notación científica: los números son
expresados de la forma a × 10n donde a es un decimal y n es un número
entero. Por ejemplo, la luz viaja en el vacío a una velocidad aproximada de
3,00 × 108 metros por segundo. Podemos escribir el número
12/10000000000 como 1,20 × 10−9.

La notación en Java para la cantidad de días que tarda la Tierra en dar una
vuelta alrededor del Sol es 365.2422 o 3.652422E2.

Java provee dos tipos para números decimales, el tipo float y el tipo
double. El tipo float tiene un rango que va desde −3,4028 × 1038 a 3,4028 ×
1038, mientras que en los de tipo doublé, el rango va desde −1,7977 ×
10308 a 1,7977 × 10308. Los números de tipo float permiten escribir
decimales con hasta 45 decimales (y algunos más). Los números de tipo
float deben tener una f o F al final. Los números de tipo double pueden
tener (es optativa) una d o D al final. Veamos algunos ejemplos de
declaraciones de este tipo de números en Java:

float velocidad = 3E8F // velocidad de la luz


float velocidad = 3E+8F // velocidad de la luz

float nanoseg = 0.000000001F o float nanoseg = 1.00E-9F


// 1/1000000000 partes de un segundo

double pi = 3.14159265358979323E0D
double DIASDELAÑO = 3.652422e+2

Por supuesto que en estos casos también contamos con los operadores
numéricos habituales: +, -, *, / (aquí / produce el cociente exacto).

Por supuesto que también podemos manejar números enteros dentro de


los tipos float o double, pero si estamos en esta situación y queremos
trabajar dentro del tipo int, Java nos provee un método llamado moldeado
o casting en inglés, para poder realizar esto. El casting permite convertir un
tipo en otro, su sintaxis general es:

8
( <tipo> ) <valor>

Los paréntesis angulosos se usan para remarcar un componente lógico y no


se usan en la declaración real. A continuación, se presenta una sucesión de
castings:

double r = 3.0E+2; // el valor de r (300) es declarado double float p;


int q;
q = (int)r; // es sin pérdida de información
p = (float)r; // r no es grande, luego no se pierde información

Java también hace moldeado automático, por ejemplo, si 3 es de tipo int y


hacemos 3 + 5.5, entonces el compilador convierte 3 a tipo double y realiza
la suma. Sin embargo, aunque la suma 3.5 + 5.5 de entera, Java no hace, en
este caso, moldeado automático.

Tipo de datos de caracteres.

Los tipos de dato char nos permiten representar los caracteres simples. Los
valores a, B, 3 y & son todos caracteres válidos. Los valores de los
caracteres siempre aparecerán entre los símbolos y. Luego, a se refiere a
un carácter, mientras que a se podría referir a una constante o una
variable.

El siguiente bloque de programa Java

har grade;
grade = ’A’;
System.out.println( grade );

imprimirá

Los caracteres simples no son en realidad demasiado útiles por sí mismos.


Las que son más útiles son las palabras o cadenas de caracteres. Veremos
esa clase de expresiones que serán de tipo string. Quizás lo más
interesante del tipo char es que es casi un sinónimo del tipo int. A cada
carácter se le asigna un entero, el 97 a la a, el 98 a la b y así sucesivamente
hasta la z. Luego seguimos con las mayúsculas en el orden alfabético. Todas
las operaciones que hemos definido para enteros también valen para el
tipo char. El fragmento de programa:

9
char firstLetter = ’a’;
System.out.println((int)firstLetter);
System.out.println(firstLetter);

genera como salida:

97
a

Este sencillo programa muestra que a es representado en la computadora


por el número 97.

Observemos que si queremos escribir con caracteres la palabra no,


debemos poner las instrucciones

System.out.print(’n’);
System.out.print(’o’);

Tipo de datos boolean

Hay veces en que es necesario, dentro de un programa de computación,


tomar una decisión. Estas decisiones dependen, por supuesto, del estado
de las variables en ese momento. Los lenguajes de alto nivel como Java
permiten hacer preguntas sobre los estados (variables) y obtener como
respuesta un verdadero o falso (true o false, respectivamente). Un caso
típico es cuando queremos repetir un bloque de instrucciones cierta
cantidad de veces, digamos, por ejemplo, cincuenta veces.

Cada vez que el programa termina de ejecutar el bloque, debe preguntar si


ya ha hecho la repetición cincuenta veces, y en base a la respuesta, tomar
la acción adecuada. Para lograr lo anterior, usualmente se define una
variable, digamos cuenta, que se inicializa en 1 y luego se ejecuta el bloque
repetidas veces. Cada vez que se termina de ejecutar el bloque, el
programa pregunta si cuenta < 50, si es así (es decir si el programa
devuelve true), se le suma uno a cuenta (cuenta = cuenta + 1) y se ejecuta
el bloque de nuevo. Cuando cuenta < 50 es false, el programa continúa con
las instrucciones que siguen al bloque.

Todos los tipos de datos primitivos Java pueden ser comparados usando el
test de igualdad (==) o el de desigualdad (!=). Los tipos numéricos o el tipo
carácter tiene un orden y pueden ser comparados usando relaciones de
orden: < (menor que), <= (menor igual que), > (mayor que), >= (mayor igual
que). Todas las condiciones anteriores devuelven true cuando el test se
verifica, y devuelven false en caso de que no se verifique. Una expresión

10
booleana es una expresión para la cual tiene sentido preguntar si es
verdadera o falsa (por ejemplo, contar < 50). Para declarar expresiones
booleanas, usamos la palabra reservada boolean. El operador unario !
invierte el valor de la expresión booleana, es decir !true es false y
viceversa.

Tabla 3: Resultado de las operaciones logicas con dos variables Boolean P


yQ

P Q !P P==Q P!=Q P||Q P&&Q

true true False true False true true

true false false false True true false

false true false false True true false

false false false true False false false

Fuente: elaboración propia.

Dadas las declaraciones

boolean result;
int a, b;

cada una de las siguientes expresiones booleanas hacen que result sea true

// las siguientes son verdaderas:


result = 42 == (41+1); // mismo valor: 42
result = 42 >= 42; // 42 y 42 son iguales
result = ’A’ < ’B’; // ’B’ esta después en el alfabeto
result = ’A’ == 65; // en ASCII el codigo de ’A’ es 65
result = Math.sqrt(4.0) == 2.0;
result = ((a/b)*b + (a%b)) == a;// siempre verdadero
result = a == a; // cualquier valor es igual a si mismo
result = (a != a) == false;
result = !false;
result = true == true; // true es igual a true

mientras que las siguientes hacen que result sea false

// las siguientes son falsas:


result = 42 != 42;
result = !(42 == 42);

11
result = ’a’ == ’A’; //minúscula y mayúscula son
//diferentes
result = !true;
result = true == false;

Hay una serie de operaciones que combinan expresiones booleanas para


obtener otras más complejas:

|| (o lógico) y && (y lógico). Estos operadores toman dos valores


booleanos y nos devuelven otro. El operador o devuelve true si alguna de
las dos expresiones es true. El operador y devuelve true solo si las dos
expresiones son true. Podemos ver, por ejemplo, si un valor se encuentre
entre 100 y 200, combinado dos test:

boolean entre = (100 < a) && (a < 200);

El resultado es true cuando a es más grande que 100 y más pequeño que
200. Podemos hacer una expresión cuyo valor es false de la siguiente
manera:

result = (100 > a) && (a > 200);

Esto no es posible, pues ningún valor puede ser menor que 100 y mayor
que 200. Una expresión que siempre es falsa es llamada una falacia. Una
expresión que siempre es verdadera es llamada una tautología.

La siguiente expresión es una tautología:

result = (100 < a) || (a < 200);

Esta expresión siempre es verdadera, pues cualquier entero es mayor que


100 o menor que 200. Debemos evitar incluir tautologías o falacias en los
programas, es mejor asignar el valor (true o false) directamente.

Un error muy común es tratar de escribir expresiones lógicas usando


abreviaturas de las expresiones matemáticas. Por ejemplo,

entre = 100 < a < 200; // queremos ver si 100 < a y a < 200

El compilador interpreta esta instrucción como

entre = ((100 < a) < 200);

La primera comparación genera un boolean, por lo tanto, la segunda


comparación no tiene sentido.

12
La forma correcta de escribir esto es la que fue explicada anteriormente.

Al escribir expresiones lógicas complicadas, debemos asegurarnos de


representar lo que queremos decir. Es bueno seguir el siguiente principio:

Use paréntesis para hacer explícito el orden de evaluación.

A menudo, una expresión booleana larga puede ser simplificada con poco
trabajo. Por ejemplo, es importante tener en cuenta que como true es el
elemento neutro del test de igualdad, una expresión del tipo a == true, se
puede reemplazar por a. Por otro lado, la expresión a == false, se puede
reemplazar por !a.

Conclusión:

En esta lectura estudiamos diferentes tipos de datos primitivos: enteros,


punto flotante, caracteres y booleanos.

Toda variable en Java está asociada a un tipo. Esta asociación es llamada


una declaración y ayuda al compilador a determinar el uso correcto de la
variable en el programa.

Los tipos de datos primitivos tienen un rango de valores predeterminado.


Cualquier intento de asignarle a una variable un valor fuera del rango
producirá un error de compilación.

Tipos diferentes tienen operaciones diferentes. Algunos operadores tienen


diferente significado cuando se aplican a variables de diferentes tipos. Por
ejemplo, / realiza la división entera en int o long y realiza la división exacta
en float o double.

Valores primitivos de un tipo se convierten automáticamente (si fuera


necesario) a un tipo de mayor precisión. Por ejemplo, una operación entre
un int y un double hace que el valor int se convierta a double y después se
realice la operación, dando por resultado un double. También, podemos
convertir datos de un tipo en otro usando casting.

13
Referencias
Beneke, T. (2015). A conversation with Mark Reinhold. Recuperado de
https://community.oracle.com/docs/DOC-921872

Programar ya. (2015). “Declaración y uso de constantes en Java. Uso del


final en Java, datos final”. Recuperado de http://goo.gl/guJouk

14
Ventajas de
la POO

Programación
Orientada a
Objetos

1
Ventajas de la POO
Las ventajas de la POO
Un paradigma como la POO es una ayuda en la búsqueda de la solución de
un problema. Esto es debido a que ofrece formas predefinidas de
organización de la tarea y modos de escritura que permiten acelerar el
trabajo en pos de construir la solución de software. Así podemos graficar la
obtención de una solución de Software para los problemas que se buscan
resolver:
La programación
orientada a objetos
presenta también
algunas desventajas Figura 1: Esquema del uso del paradigma POO
como pueden ser:
Cambio en la forma de
pensar de la
programación
tradicional a la
orientada a objetos.
La ejecución de
programas orientados
a objetos es más lenta.
La necesidad de
utilizar bibliotecas de
Fuente: Vivona, 2011, p. 26.
clases obliga a su
aprendizaje y
entrenamiento.
(Roldan A., 2016). Definimos las ventajas de la POO, en estas características:

Reusabilidad. Cuando hemos aplicado POO, diseñando


adecuadamente las clases, éstas se pueden usar en distintas
partes del programa y en numerosos proyectos.
Mantenibilidad. Debido a la sencillez en la abstracción del
problema, los programas orientados a objetos son más
sencillos de leer y comprender, pues nos permiten ocultar
detalles de implementación, dejando visibles sólo aquellos
detalles más relevantes.
Modificabilidad. La facilidad de añadir, suprimir o modificar
nuevos objetos nos permite hacer modificaciones de una
forma muy sencilla.
Fiabilidad. Al dividir el problema en partes más pequeñas
podemos probarlas de manera independiente y aislar mucho
más fácilmente los posibles errores que puedan surgir.
(Roldan, 2016).

2
Encontramos también el siguiente párrafo de uno de los autores mas
autorizados en la materia, Grady Booch:

La descomposición orientada a objetos tiene un número de


ventajas altamente significativas sobre la descomposición
orientada a procesos.
La descomposición orientada a objetos obtiene aplicaciones
más pequeñas debido a la reutilización de los mecanismos
comunes, proporcionando así una importante economía de
expresión.
La descomposición orientada a objetos reduce en gran
medida el riesgo de construir sistemas de software
complejos, ya que están diseñados para evolucionar
gradualmente desde los sistemas más pequeños en los que
ya se tiene confianza.
La descomposición orientada a objetos se dirige
directamente a la complejidad inherente de software,
ayudando a tomar decisiones inteligentes con respecto a la
separación de las capas en un contexto mayor.
Por todo lo anterior, los sistemas orientados a objetos son
más resistentes al cambio y por lo tanto más capaces de
evolucionar con el tiempo, debido a que su diseño se basa en
formas intermedias estables. (Booch, 1996, p. 35).

La POO domina el mercado desde hace unos años y no parece disminuir, sino
al contrario, si analizamos los nuevos lenguajes y aplicaciones que han
surgido recientemente.

En particular, Java, aunque no es el único lenguaje OO, se puede afirmar que


es el máximo referente de los lenguajes en cuanto a la cantidad de
plataformas abarcadas por su forma de funcionar. Es un requisito
indispensable para el programador de hoy conocer esta tecnología.

Este paradigma tiene como objetivo reflejar ideas, conceptos,


comportamientos que deben ser replicados por el software construido, para
cumplir los requerimientos. Además, lo hace acortando los tiempos de
programación, debido a que una de sus ideas centrales es resolver una vez
las tareas que deben realizarse, para no tener que escribir una y otra vez el
código necesario.

3
“La POO se basa en dos conceptos básicos:

 Hay objetos y
 Solamente se comunican a través de mensajes.

Un objeto es una entidad que agrupa datos y funcionalidad. En este


esquema los datos son otros objetos, que son referenciados a través de un
nombre, una etiqueta. Por ejemplo, un objeto Persona tiene como datos el
nombre y la edad, estas son etiquetas que apuntan a los objetos
correspondientes. Entendemos funcionalidad por lo que hace un objeto
cuando recibe un mensaje, determinando su comportamiento. Siguiendo
con el ejemplo de la persona, si se le envía el mensaje “correr”, esta empieza
a correr.” (Vivona, 2011, p. 15).

4
Referencias
Booch, G. (1996). Análisis y diseño orientado a objetos, con aplicaciones. Estados
Unidos: Addison-Wesley Iberoamericana.

RAE (2018) (a). Real Academia Española. Recuperado de:


http://dle.rae.es/?id=0CwVYCX Octubre 2018

RAE (2018) (b). Real Academia Española. Recuperado de:


http://dle.rae.es/?id=0CxZRfR Octubre 2018

Roldan, A. (2016). Ventajas de la Programación Orientada a Objetos. Recuperado


de http://www.ciberaula.com/articulo/ventajas_poo

Vivona, I. (2011). Programación Orientada a Objetos. En I. Vivona, Java (pp. 15-26).


Buenos Aires: Fox Andina.

También podría gustarte