Programacion Orientada A Objetos Java
Programacion Orientada A Objetos Java
Orientada A
Objetos-Java
Introducción
Hello world!
Hello world!
¿Qué es Java?
Antes de comenzar...
Tarea
Primeros pasos
Primeros pasos
Elementos de un programa
Separadores
Operadores
Comentarios
Constantes y variables
Ámbito
Cadenas
Arrays
Control de flujo
Funciones condicionales
Bucles
Funciones
Excepciones
Convenios de escritura
Tarea
Introducción a la POO
Introducción a la POO
Objetos
Clases
Atributos
Constructores
Métodos
Static
Creando objetos
Herencia
Polimorfismo
Sobreescritura de métodos
Control de acceso
Encapsulamiento
Tarea
Terminando
Terminando
Jerarquía de clases
Codificación
Pintemos en Java
Bibliografía recomendada
Tarea
Créditos
Introducción
System.out.println("Hello world!");
No podíamos empezar un curso de programación sin la célebre frase Hello world!, en la línea
superior tenemos la sintaxis que en Java nos permite mostrar por pantalla este mensaje.
A lo largo de este curso de 4 módulos vamos a tratar de familiarizarnos con el lenguaje Java y tener
una introducción a la programación orientada a objetos (POO).
Hello world!
En este primer módulo vamos a conocer que es Java y sus características principales. Además
vamos a crear nuestro primer programa (lo cual derivará en otras necesidades que veremos
entonces) y vamos a conocer donde obtener mas información sobre Java para complementar este
curso.
En el siguiente esquema elaborado por el CATEDU podemos ubicar el lenguaje Java como un
lenguaje ideal para abarcar el curriculo relativo a programación en alumnado a partir de 15-16
años.
Hello world!
¿Qué es Java?
Java es un lenguaje de programación multiplataforma, de propósito general y orientado a objetos.
Lenguaje de programación
Multiplataforma
Propósito general
Orientado a objetos
Vamos a recurrir a la wikipedia para obtener una definición de estos conceptos y tener así una
primera aproximación a los mismos
https://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n
https://es.wikipedia.org/wiki/Multiplataforma
Los lenguajes de propósito general, son lenguajes que pueden ser usados para
varios propósitos, acceso a bases de datos, comunicación entre computadoras,
comunicación entre dispositivos, captura de datos, cálculos matemáticos, diseño
de imágenes o páginas.
https://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_de_prop%C3%B
3sito_general
Con todo lo que hemos visto hasta el momento tenemos que quedarnos con la idea de que
Java es un lenguaje de programación que va a permitirnos trabajar en distintas plataformas
(Windows, Linux, Android,...), con distintas intenciones (hacer un programa que calcule factoriales,
acceder a bases de datos, interactuar con el hardware de nuestros dispositivos,...) y además nos
va a permitir trabajar con objetos en lugar de hacer uso de la tradicional programación
estructurada (que también podremos usar en Java).
Hello world!
Una vez se ejecute nuestro primer programa únicamente va a saludarnos por pantalla pero nos va
a servir para hablar de cuestiones que hasta el momento hemos obviado y a su vez nos va a servir
para configurar nuestro entorno de trabajo.
Hello world!
Antes de comenzar...
Anteriormente hemos comentado que Java es multiplataforma, es decir, un mismo programa puede
ser ejecutado en varias arquitecturas o sistemas operativos sin mayor problema. Para conseguir
esto es necesario aclarar algunas cuestiones:
Cuando trabajamos con código java los ficheros que contienen este código tienen la
extensión .java Estos ficheros se llaman ficheros fuente y contienen texto plano, es decir,
podemos abrirlos con cualquier editor de texto y ver su contenido.
Cuando un fichero .java es compilado se obtiene un fichero .class del mismo nombre. Si
nuestro fichero fuente se llama Saluda.java su versión compilada se llamará Saluda.class
y si tratamos de abrirlo con un editor de texto veremos que su contenido nos resulta
ilegible
Resumiendo, si yo tengo un fichero fuente ¿qué debo hacer? compilarlo, y para ello necesitarás el
kit de desarrollo java (JDK) que incluye el programa javac que te permite compilar código. Y
entonces, cuando ejecutamos un programa escrito en Java ¿qué estamos ejecutando? estamos
ejecutando la versión compilada, es decir, el fichero .class ¿y qué programa interpreta estos
ficheros? Lo interpreta un programa llamado java que está contenido dentro de la máquina virtual
java (JRE) (y que no hay que confundir con las máquinas virtuales que creamos con Virtual Box o
similares)
Pregunta Verdadero-Falso
Si quiero poder compilar un fichero .class debo instalar en mi equipo el kit de desarrollo java (JDK)
VerdaderoFalsoLos ficheros que se compilan son los ficheros .java y se compilarían con el
programa javac contenido dentro del JDK
Si quiero ejecutar un programa Java del cual me han facilitado su fichero .class en la máquina en la
que quiero ejecutarlo deberé tener instalada la máquina virtual java (JRE)
VerdaderoFalso
Si quiero ejecutar un programa Java del cual me han facilitado su fichero .class en la máquina en la
que quiero ejecutarlo deberé tener instalada la máquina virtual java (JRE)
VerdaderoFalsoLo que se ejecuta son ficheros .class y se hace con el programa java que está
dentro del JRE
Como trabajar en consola con comandos resulta tedioso lo que nosotros vamos a hacer para
facilitarnos la vida va a ser trabajar con un entorno de desarrollo integrado (IDE) que nos va a
aportar soporte para el lenguaje java evitándonos tener que hacer uso de la consola y
facilitándonos el aprendizaje al reseñarnos los errores sintácticos que cometamos.
Para ello he elegido trabajar con el IDE Netbeans que es libre, gratuito y tiene una gran comunidad
de gente detrás desarrollándolo y utilizándolo. Entre otras opciones tendríamos el trabajar con
Eclipse o IntelliJ IDEA, además de utilizar un editor de texto plano como bloc de notas, notepad++
Netbeans puede ser ejecutado en equipos con sistemas operativos Windows, Linux o Mac OS en
sus diferentes arquitecturas de 32 o 64 bits. Para ahorrarnos el descargar por un lado JDK y por
otro lado netbeans vamos a descargar e instalar una versión en la que ya viene todo. Para ello nos
dirigiremos a http://www.oracle.com/technetwork/articles/javase/jdk-netbeans-jsp-142931.html y
descargaremos e instalaremos la versión que se corresponda a nuestro sistema operativo. A
continuación he realizado 2 videotutoriales en los que muestro como proceder en Windows 7 y
Ubuntu 16.04 LTS.
https://www.youtube.com/embed/DldsDzidscg?list=PL1ubUMkNBAR_98ka0Q393l3fpzSjo3FGq
https://www.youtube.com/embed/gm2ICqWz4P8?list=PL1ubUMkNBAR_98ka0Q393l3fpzSjo3FGq
Si queremos prescindir del uso de un entorno de desarrollo integrado podemos hacerlo, aunque yo
no lo haría con mi alumnado excepto que trabajase con ellos en FP de la familia de Informática y
comunicaciones. En el siguiente enlace tenemos un pequeño manual en el cual nos explican como
hacer la compilación y ejecución a través del terminal (previamente habrá que haber instalado el
JDK). No obstante a lo largo del curso haré uso de NetBeans en mis explicaciones y vídeos con el
fin de facilitar la tarea a docentes y alumnado.
Hello world!
https://www.youtube.com/embed/plwtjTiiXwo
Voy a extraer el código del programa realizado en el vídeo para comentarlo con mayor detalle. Voy
a quitar los comentarios con el fin de facilitar la lectura del código y centrarnos en lo relevante en
este momento.
La primera línea hace referencia al paquete al que pertenece nuestro fichero. Hablaremos de la
organización del código en capítulos posteriores.
En la tercera línea creo un método llamado main que pertenece a la clase Modulo1HolaMundo. En
java para definir un método debemos definir el tipo que devuelve, el nombre y los argumentos que
requiere. Posteriormente abrimos una llave { que cerramos en la línea 5 }, todo lo que se
encuentra dentro de ambas llaves pertenece al método main En este caso el tipo que devolvemos
es void (nada), el nombre de la función es main y tenemos un argumento llamado args de tipo
String[]. Los modificadores public y static los dejamos para capítulos posteriores. El método main
es un método especial, es el que se ejecutará en nuestro programa cuando iniciemos este. En
caso de que nuestro proyecto tenga mas de un método main para configurar cual queremos que se
ejecute al iniciar el proyecto deberemos dirigirnos a las propiedades del proyecto (properties),
seleccionar ejecución (Run) y allí establecer la clase principal (Main Class) que queremos que se
ejecute.
En la cuarta línea hago una llamada al sistema y le digo que escriba por pantalla en una línea la
frase Hola mundo. Es muy común al principio olvidar el ; del final de la línea.
Hello world!
En este apartado el objetivo es realizar una pequeña recopilación de todos aquellos recursos que
puedan resultarnos de utilidad y ampliación a curso. NO es necesario descargar ni instalar
nada de este listado si has seguido mis instrucciones hasta la fecha.
downloads-2133155.html
downloads-2133151.html
Tutoriales Java: http://docs.oracle.com/javase/tutorial/
Aprendiendo el lenguaje: http://docs.oracle.com/javase/tutorial/java/index.html
Creación de una nterface gráfica:
http://docs.oracle.com/javase/tutorial/uiswing/index.html
Hello world!
En los siguientes capítulos haremos haciendo uso de estas útiles funciones que procuraré ir
introduciendo poco a poco pero me ha parecido interesante mostrar un pequeño adelanto.
Hello world!
Tarea
Tu tarea una vez acabado este primer módulo consiste en:
Primeros pasos
Hasta el momento hemos realizado una introducción a Java indicando como instalarlo y
configurarlo. En este segundo módulo se pretende profundizar en el lenguaje Java y empezar a
realizar unos primeros algoritmos que nos permitan introducirnos de lleno en la programación
orientada a objetos en el capítulo 3.
Primeros pasos
Elementos de un programa
En el módulo 1 ya hemos realizado un programa y hemos visto algunas palabras clave y hablado
de clases y paquetes pero es ahora cuando vamos a profundizar en las posibilidades del lenguaje
Java
Primeros pasos
Separadores
En Java utilizaremos los siguientes separadores:
Con anterioridad ya hemos utilizado todos ellos y conforme avancemos en el curso vamos a ir
viendo mas ejemplos de su uso. Vamos a ver un pequeño recordatorio de donde los hemos
utilizado:
Cuando definimos una variable llamada args que era un vector de Strings utilizamos los
corchetes: String[]__ args.
Cuando definimos la clase Modulo1HolaMundo ya utilizamos las llaves para definir el
alcance de la clase: public class Modulo1HolaMundo { (...) }.
Creando creamos el método main hicimos uso para los paréntesis para indicar el
comienzo y fin de los parámetros: public static void main(String[] args) {.
Al finalizar la sentencia System.out.println("Hola mundo"); hicimos uso del punto y
coma para delimitar el fin de la misma.
En la misma sentencia que en el caso anterior System.out.println("Hola mundo"); hicimos
uso del punto para acceder a una clase y sus objetos. En este apartado entraremos en
mayor profundidad mas adelante.
El caracter coma aún no lo hemos utilizado, pero podríamos darle uso en el siguiente
ejemplo: void nombreFuncion(int param1, int param2); Aquí la función de la coma no es
otra mas que separar los parámetros param1 y para2 del método nombreFuncion.
Pregunta Verdadero-Falso
Para delimitar el contenido de una clase haré uso de los corchetes []
VerdaderoFalsoPara delimitar el contenido de una clase se hace uso de las llaves {} Ocurre lo
mismo con los métodos.
En Java al final de cada línea debo colocar un punto y coma.
VerdaderoFalsoEl punto y coma solo debe colocarse al final de las sentencias. Cuando declaramos
una clase o método no hay que hacerlo.
Para crear un vector haré uso de los corchetes []
Operadores
Se hace necesario poder realizar cálculos o tomar decisiones con los datos que manejamos, es por
ello que nos surge la necesidad de disponer de operadores que nos permitan hacerlo. A
continuación procedo a enumerar los operadores mas habituales:
En Java existen mas operadores que los aquí indicados pero creo que con los aquí señalados es
mas que suficiente para cubrir los objetivos de este curso. A lo largo del curso se procurará utilizar
todos los operadores aquí indicados para así aclarar cualquier posible duda que pudiera existir con
ellos.
Primeros pasos
Comentarios
Los comentarios los introduciremos en nuestro código fuente para facilitar la lectura y comprensión
posterior del código. La redacción de estos comentarios también van a facilitar en la posterior
elaboración de la documentación del código.
de línea: Todo lo que, en una línea, esté detrás del símbolo // se considerará un
comentario y ni el compilador ni el intérprete lo tendrán en cuenta.
de bloque: Todo lo que esté comprendido entre el símbolo / y el símbolo / se considerá un
comentario y ni el compilador ni el intérprete lo tendrán en cuenta.
de documentación: Todo lo que esté comprendido entre el símbolo /* y el símbolo / se
considerará un comentario de documentación y en la generación de documentación y en
la autoayuda del IDE netbeans nos proporcionará información extra.
Entre las líneas 230 y 242 tenemos un comentario de documentación. En este tipo de comentarios,
además de explicar para que sirve una función se puede detallar información adicional a través de
anotaciones como @param @return o @throws que sirven respectivamente para indicar los
parámetros de la función, lo que devuelve la función y el tipo de excepción o excepciones que
lanza la función.
Constantes y variables
Una [variable](https://es.wikipedia.org/wiki/Variable_(programaci%C3%B3n) es un lugar
en memoria donde almacenaremos un dato que podrá cambiar o no a lo largo de la ejecución de
nuestros programas. Todas las variables tienen que ser de un determinado tipo y tener un nombre.
Por convenio las variables tienen al menos el primer caracter de su nombre en minúsculas. Una
[constante](https://es.wikipedia.org/wiki/Constante_(inform%C3%A1tica) es un lugar en
memoria en el cual almacenaremos un dato con el fin único de leerlo y sin posibilidad de
modificación. Las constante deben tener un determinado tipo y deben tener un nombre. Por
convenio el nombre de las constantes se escribe en mayúsculas. En java para definir una constante
lo haremos exactamente igual que si definieramos una variable pero las constantes deben ser
precedidas por la palabra reservada final.
Anteriormente hemos indicado que tanto las constantes como las variables deben ser de un
determinado tipo, a continuación vamos a hablar de ellos.
En java existen 2 tipos de variables: los tipos básicos (también llamados tipos primitivos) y
los objetos. De los objetos nos ocuparemos en el módulo 3 por lo que a continuación paso a
enumerar los tipos primitivos mas habituales.
Números enteros:
byte: utiliza 8 bits en memoria. Su rango va de -27 a 27-1
short: utiliza 16 bits en memoria. Su rango va de -215 a 215-1
int: utiliza 32 bits en memoria. Su rango va de -231 a 231-1
long: utiliza 64 bits en memoria. Su rango va de -263 a 263-1
Números decimales:
float: utiliza 32 bits.
double: utiliza 64 bits.
Booleanos:
boolean: utiliza 1 bit. Solo puede valer true (verdadero) o false (falso)
Cadenas:
char: utiliza 16 bits.
int operando1 = 4; // Declaramos una variable llamada operando1 de tipo int y le asignamos el
valor 4
final char CARACTER = 'a';// Declaramos una costante de tipo char y nombre CARACTER. Le
Aunque lo veremos en el siguiente módulo del curso a continuación vamos a crear unas variables
que harán referencias a objetos. Del código que aparece a continuación me interesa que nos
fijemos en que declaremos tipos primitivos u objetos la sintaxis es prácticamente la
misma:
Integer operando1 = new Integer(4); // Declaramos una variable llamada operando1 de tipo
final Double PI = new Double(3.1416); // Declaramos una constante de tipo Double. El nombre de
Boolean esMayor = new Boolean(false); // Declaramos una variable de tipo Boolean, con nombre
final String CADENA = "a";// Declaramos una constante de tipo String y nombre CADENA y le
asignamos el valor "a". Fíjate en que son comillas dobles. Además aquí es el único lugar donde
no hemos escrito new String("a") pero de esto ya hablaremos mas adelante aunque no es trivial
Como podemos intuir en base a estos ejemplos cada tipo básico tiene asociado un objeto
equivalente. Pero como vemos a continuación (y profundizaremos en el módulo 3) también
podemos crear variables del tipo de Objetos que hayamos creado.
Coche miCoche = new Coche(); //Declaramos una variable de tipo Coche con el nombre miCoche y
Moto moto1 = null; //Declaramos una variable de tipo Moto con el nombre moto1 y le asignamos
el valor null
Si eres observador/a te habrás dado cuenta de que los tipos básicos empiezan en minúscula
mientras que los objetos comienzan en mayúsculas. Es probable que también te hayas percatado
de que el nombre que asigno a las variables siempre comienza en minúsculas y el nombre que
asigno a las constantes está completamente en mayúsculas, esto son convenios de escritura del
lenguaje Java y tu puedes seguir tu propio estilo de código pero es interesante hacer uso del
convenio porque facilita la lectura y comprensión del código yen caso de trabajar con otras
personas se es mas productivo. En este módulo, un poco mas adelante, hablaremos en mayor
profundidad de esta cuestión.
Primeros pasos
Ámbito
Las variables y constantes tienen asociado un ámbito. Simplificando, el ámbito indica donde
existen y por tanto pueden utilizarse. A continuación voy a tratar de explicarlo con un extracto de
código.
Pregunta Verdadero-Falso
En el ejemplo de código anterior, podría sustituir la línea 10 por System.out.println(variableClase);
ya que la variable variableClase es accesible desde la línea 10
VerdaderoFalsovariableBucle solo está accesible dentro del bucle que está entre las líneas 12 y 17
por lo que no es accesible en la línea 6 y obtendríamos un error de compilación.
Primeros pasos
Cadenas
Hasta el momento hemos trabajado con cadenas (String) en alguna ocasión. Hemos mostrado por
pantalla una cadena:
System.out.println("Hello world!");
final String CADENA = "a";// Declaramos una constante de tipo String y nombre CADENA y le
String texto = "Hola mundo";// Declaramos una variablede tipo String y nombre textoy le
String no es un tipo primitivo, String es una clase por lo que cada vez que hacemos uso de ella
estamos creando un objeto.
En un entorno profesional no se usaría la clase String sino que se usarían las clases StringBuffer o
StringBuilder (en función de las necesidades específicas). En el curso utilizaremos la clase String
pero por curiosidad vamos a ver un ejemplo de código con estas clases:
Primeros pasos
Arrays
En Java existen un tipo de variables llamadas * que nos permiten crear *vectores de un mismo
elemento. Es importante indicar que un Array es un objeto.
int[] array1 = new int[4]; // Creamos una variable llamada array1 que tendrá 4 posiciones
int array2[] = new int[4]; // Creamos una variable llamada array2 que tendrá 4 posiciones
int[] array3 = {1, 2, 3}; // Creamos una variable llamada array3 que en su posición 0 tendrá
Cuando creamos un Array como es el caso de array1 y array2 y lo inicializamos pero no definimos
el valor de sus posiciones estas toman el valor por defecto de la variable, en nuestro caso 0.
De un modo análogo al anterior podemos crear de Arrayx (matrices). A continuación podemos ver
un ejemplo:
int[][] matriz = new int[10][10];// Creamos una variable llamada matriz que es una matriz de
enteros de 10x10
System.out.println(array4[0]);
System.out.println(array4[1]);
System.out.println(array4[2]);
false
true
false
Control de flujo
Además de poder operar con los datos tenemos la necesidad de que ocurran cosas distintas en
función de los mismos. Para cubrir estas necesidades dispondremos de funciones condiciones y
bucles.
if/else if/else
switch
for
while
do while
En los nodo inferiores voy a tratar de explicarlos y veremos algunos ejemplos con código.
Primeros pasos
Funciones condicionales
Existen 2 funciones condicionales: if/else if/else y switch.
Vamos a comenzar por la estructura if/else if/else. En esta estructura la sintaxis es la siguiente:
if(condicion){
sentencias;
}else if(condicion){
sentencias;
}else{
sentencias;
De la estructura anterior es obligatorio que exista siempre el if. else if puede haber 0 o varios. else
puede haber 1 o 0. Y el funcionamiento es el siguiente. Cuando el compilador llega a la condición
del if y la evalúa, si la condición es verdadera ejecutará las sentencias ubicadas dentro del if y
habrá terminado con la estructura if/else if/else, ya no ejecutará sentencias de otros bloques
aunque estas sean verdad. Si la condición del if es falsa se evalúa la condición del else if y si es
verdadera se ejecutan las sentencias ubicadas dentro, en caso de ser falsa se evalúa el siguiente
else if si lo hubiera. Si la condición de algún else if fuese verdadera se ejecutarían las sentencias de
su interior y ya no se evaluarían ni ejecutarían mas condiciones de toda la estructura if/else if/else.
En caso de que ninguna condición del if o los else if fuese verdadera y hubiese un bloque else se
ejecutarían las sentencias contenidas dentro del bloque else.
Vamos a ver a continuación un ejemplo de 2 estructuras if/else if/else ya que es mas sencillo
comprender esta estructura leyendo el código que tratando de explicarlo.
Cuando el programa llega al if de la línea 8 se comprueba si la variable calificacion es mayor o
igual a 0 (lo es) y que la variable calificacion sea menor a 5 (no lo es). Como el resultado de true
&& false es false no entramos dentro de sus llaves y se pasa a evaluar la condición de la línea 11.
En la línea 11 se evalúa si la variable calificacion es menor a 7 (no lo es), al ser falsa se pasa a
evaluar la condición de la línea 13. En la línea 13 se evalúa si la variable calificacion es menor a 9
(lo es), al ser verdad se ejecutan todas las sentencias ubicadas dentro de sus llaves, en ese caso
solo hay 1 sentencia y se escribe Notable en consola. Como la condición de la línea 13 es verdad
ya no se comprueban las condiciones de las líneas 15, 17 o 19 y se salta directamente a la línea
22.
En la línea 22 tenemos otra condición así que se evalúa si la variable avisarFamilia es true (no lo
es), al ser falso no se ejecuta el código de su interior y al no haber ningún else if ni else se da por
terminado este if.
condicion?valorSiCondicionVerdadera:valorSiCondicionFalsa;
Vamos a ver un ejemplo que sustituiría al código comprendido entre las líneas 22 a 24 de la
imagen anterior
Se va a escribir algo por pantalla ¿el qué? dependerá del resultado que produzca la variable
avisarFamilia, si la variable avisarFamilia es verdadero se devolverá "Avisar a la familia" y será eso
lo que se escriba. Si la variable avisarFamilia es falso se devolverá lo que está tras los 2 puntos, es
decir, "" y se escribirá una línea vacía.
Una vez vista la estructura if/else if/else vamos a continuar con la estructura switch. Su sintaxis es
la siguiente:
switch(expresión){
case valor1:
Sentencias;
break;
case valor2:
Sentencias;
break;
default:
Sentencias;
De la sintaxis anterior es obligatorio utilizar la primera línea y la última y debe haber al menos 1
case con sus sentencias y un break tras las sentencias. El elemento default es opcional. Como
quizás resulte algo complejo de explicar teóricamente vamos a ver un ejemplo:
En la línea 7 indicamos a nuestro switch que la variable de referencia es cadena. En la línea 8
comprobamos si "Hola" es igual a cadena y como no lo es pasamos al siguiente case, al de la línea
11. En la línea 11 se evalúa si la variable cadena es igual a "Adios" y como lo es entramos a
ejecutar todas las sentencias ubicadas dentro de nuestro case, en este caso la de la línea 12.
Luego llegamos a la línea 13, donde nos encontramos un break, este break nos lanza fuera del
switch, a la línea 16. Si olvidásemos añadir el break de la línea 13 se ejecutaría la sentencia de la
línea 12 y luego la sentencia de la línea 15 por ello hay que finalizar cada case con break.
Bucles
Ha llegado el momento de hablar de los bucles y de sus distintas formas en Java.
https://es.wikipedia.org/wiki/Bucle_(programaci%C3%B3n)
Ahora que sabemos lo que es vamos a ver los distintos bucles existentes en Java. Vamos a
comenzar con el bucle for. Su sintaxis es la siguiente:
sentencias;
En iniciacion deberemos establecer el valor inicial que queremos dar a nuestra variable de control.
En condicionFin deberá haber alguna condición lógica y en accionSobreIniciacion deberemos
establecer que queremos que pase tras cada iteracción. En sentencias estableceremos las
sentencias de código que necesitemos. No se considera una buena práctica modificar la variable
de iniciación en las sentencias. Una vez mas, vamos a reforzar la explicación con un ejemplo que
incluya código con el fin de facilitar la compresión.
Vamos a analizar esta pieza de código. En la línea 6 creamos un array de 4 posiciones (tal como
vimos en el apartado Arrays). En la línea 7 tenemos un bucle for y en el nos encontramos int i = 0,
esto hace que solo la primera vez que se accede al bucle se cree una variable llamada i que valga
0. Posteriormente se evalúa la condición array1.length (nos devuelve la longitud del array) y como
es verdad (0 es menor que 4) se procede a ejecutar las sentencias del interior del for. En este caso
se trata de una única sentencia que lo que hace es establecer un valor en la posición del array.
Una vez se han ejecutado todas las sentencias de dentro de bucle for se ejecuta i++ y se reevalúa
la condición, si esta es cierta se vuelven a ejecutar las sentencias del bucle y así hasta el momento
en que la condición sea falsa, momento en el cual se sale del bucle. En la línea 10 escribimos por
pantalla un corchete y posteriormente, en el bucle, recorremos las posiciones del array mostrando
su valor y además en caso de que no se trate de la última posición del array añadimos una coma.
Cuando termina el bucle se añade el cirre del corchete antes escrito. Voy a escribir lo que ocurre
en el primer bucle for de un modo menos prosaico a continuación:
2º Se comprueba que la variable i (que vale 0) sea menor a array1.length (que vale 4). Es verdad.
8º Se comprueba que la variable i (que vale 2) sea menor a array1.length (que vale 4). Es verdad.
11º Se comprueba que la variable i (que vale 3) sea menor a array1.length (que vale 4). Es verdad.
12º Ejecuto array1[i] = 10 * i; es decir, en la posición 3 del array1 pongo el resultado de multiplicar
10 * 3.
14º Se comprueba que la variable i (que vale 4) sea menor a array1.length (que vale 4). Es falso,
se sale del bucle.
En Java existe otra manera de trabajar con bucles for, vamos a ver la sintaxis a continuación pero
veremos ejemplos en el apartado de estructuras de almacenamiento de datos.
Una vez hemos visto las posibilidades que nos ofrece el bucle for vamos a ver los bucles while.
Los bucles while tienen la siguiente sintaxis:
while(condicion){
sentencias;
En un bucle while las sentencias de su interior se van a estar ejecutando siempre mientras la
condición del while sea verdadera. Por ello, salvo que queramos hacer un bucle infinito, en las
sentencias actuaremos sobre la variable o variables que participen en la condición. Vamos a ver un
ejemplo:
Lo que ocurre en el código de la imagen es lo siguiente. En la línea 6 creamos una variable de tipo
entero con valor 10. En la línea 7 se evalúa que la variable antes creada sea mayor o igual a 0. Si
es verdad, se ejecutan las sentencias de las líneas 8 y 9. Si es falso, se sale del bucle while.
En último lugar vamos a hablar de los bucles do-while. Estos bucles tienen la siguiente sintaxis:
do{
sentencias;
}while(condicion);
Los bucles do-while son prácticamente iguales a los bucles while con la salvedad de que en un
bucle do-while las sentencias contenidas dentro del mismo se van a ejecutar siempre 1 vez y luego
se seguirán ejecutando mientras la condición sea verdadera. Al igual que en el caso anterior, salvo
que queramos hacer un bucle infinito, en las sentencias deberemos actuar sobre la variable o
variables que participen en la condición.
Vamos a analizar que sucede en este código. En la línea 6 creamos una variable de tipo String con
el valor a. En la línea 7 mostramos en una línea el valor de nuestra variable cadena. Entre las
líneas 8 y 10 nos encontramos un bucle do-while, procedemos ejecutando todo lo que está dentro
del bucle por lo que a nuestra variable cadena le añadimos una e al final, ahora evaluamos la
condición. Si la condición es cierta volvemos a ejecutar todas las sentencias contenidas dentro del
do-while. Si la condición es falsa hemos terminado con el do-while. En la línea 11 mostramos en
una línea el valor de nuestra variable cadena. Entre las líneas 12 y 14 nos encontramos otro bucle
do-while, así que antes de nada ejecutamos las sentencias de su interior, en este caso a nuestra
variable cadena le añadimos una i al final y una vez hemos ejecutado las sentencias procedemos a
evaluar la condición.Si la condición es cierta volvemos a ejecutar todas las sentencias contenidas
dentro del do-while. Si la condición es falsa hemos terminado con el do-while. En la línea 15
mostramos en una línea el valor de nuestra variable cadena.
Funciones
En este apartado vamos a hablar de las funciones, también llamadas procedimientos, y vamos a
nombrar los métodos pero estos últimos los veremos en mayor profundidad en el módulo 3.
Una función es un trozo de código definido por un nombre a la cual se le pueden pasar parámetros
o no y que puede o no devolver un valor.
Como primera aproximación a los métodos vamos a indicar que son algo muy parecido a una
función pero ligado a un objeto. En el siguiente módulo profundizaremos en los métodos.
Código
Image notcon ejemplo
found de cálculo
or type unknown de medias
Código
Image notcon ejemplo
found de cálculo
or type unknown de medias con funciones
Y vamos a ver que hacemos y porqué. Lo primero es indicar que ambos códigos hacen lo mismo
como podemos ver en la salida del programa sin embargo en la 2ª imagen entre las líneas 6 y 8
creamos una función que devuelve un float, tiene por nombre hazMedia y necesita 2 parámetros
de tipo float. Esta función realiza la media de ambos datos y la retorna. En el segundo programa,
en las líneas 13 y 17, vemos que para llamar a esta función es suficiente con indicar a que variable
vamos a asignarle el valor devuelto y facilitar las variables con las que queremos que se haga el
cálculo. Este ejemplo es trivial, pero si pensásemos en funciones mas complejas veríamos que al
sacar factor común del código repetido este queda mucho mas simple y legible, además, si
utilizamos una función estamos siguiendo el principio DRY (Don't Repeat Yourself, no te respitas)
que nos va a permitir el que en caso de tener que realizar un cambio en el algoritmo únicamente
haya que hacerlo en la función y no en todos los sitios donde aparezca el código no llevado a la
función.
Codigo
Image notcon ejemplo
found de uso
or type unknown de funciones y procedimientos
Ejemplo
Image de código
not found con función
or type unknown recursiva
Primeros pasos
Estructuras de
almacenamiento de datos
Antes de comenzar vamos a conocer la definición que de estructura de datos ofrece la
wikipedia:
https://es.wikipedia.org/wiki/Estructura_de_datos
En capítulos anteriores ya hemos trabajado con una estructura de datos, los Arrays (los cuales nos
permitían almacenar datos en vectores).
Trabajar con Arrays puede ser suficiente para nuestras prácticas de aula pero conviene conocer las
interfaces List, Map y Set. En el siguiente módulo del curso veremos que es una interface pero
ahora nos interesan conocer algunas implementaciones de las interfaces antes mencionadas.
ArrayList, HashMap y HashSet son, respectivamente, algunas de las implementaciones de estas
interfaces.
Vamos a ver para que usar cada una de estas estructuras de datos:
Arrays (vectores): Es la forma mas eficiente de almacenar objetos pero una vez defines
el tamaño del vector no puedes ampliarlo o reducirlo. Además no puedes guardar
variables de distinto tipo
List: Almacena las variables en el orden en que se insertan. Nos permite tener valores
duplicados en la lista. Nos permite tener variables de distinto tipo (al declararla no
pondremos como en nuestro ejemplo)
Map: No almacena el orden en que se insertan los datos (algunas de sus
implementaciones si lo hacen). Para almacenar los datos se hacen usando el par clave-
valor. No permite valores de clave repetidos pero si valores de valor repetidos. Nos
permite tener variables de distinto tipo.
Set: No almacena el orden en que se insertan los datos (algunas de sus
implementaciones si lo hacen). No permite valores duplicados. Nos permite tener
variables de distinto tipo. Es lo que debemos elegir si no queremos tener elementos
repetidos en nuestra estructura de datos.
En este capítulos vamos a centrarnos en la clase ArrayList, vamos a ver un ejemplo:
Lo primero que vemos en la línea 1 es que para trabajar con la clase ArrayList hay que importarla.
Entre las líneas 7 y 13 tenemos un ejemplo de como trabajar con Arrays (ya lo vimos con
anterioridad). En la línea 14 nos encontramos con la creación de una variable llamada
listadeStrings que es de tipo ArrayList y además le añadimos lo cual significa que en este ArrayList
solo vamos a poder almacenar variables de tipo String. La primera diferencia con respecto a los
Arrays es que aquí no definimos el tamaño del ArrayList. Esto es porque los ArrayList, a diferencia
de los Arrays, son dinámicos. Podemos variar su tamaño en tiempo de ejecución según nuestras
necesidades. En la línea 16 vemos como añadir un elemento a nuestro ArrayList. En la línea 18
vemos que para obtener el tamaño de un ArrayList utilizamos el método size. Y en la línea 19
vemos que para obtener una determinada posición de un ArrayList utilizamos el método get. Al
igual que los en los Array, en los ArrayList se comienza a contar por 0. Hemos comentado
anteriormente que los ArrayList son dinámicos por lo que en el ejemplo anterior podríamos añadir
un tercer elemento a la lista sin necesidad de crear otra variable nueva, sin embargo, no
podríamos hacerlo con el Array.
A continuación vamos a ver como quedaría el ejemplo anterior eliminando la parte relativa a los
arrays y utilizando for mejorados para recorrer el ArrayList:
Lo relevante del código anterior lo encontramos en la línea 11 donde hacemos uso del método
remove que nos permite borrar el elemento de la lista que nos interese. En la línea 12 y 17 nos
encontramos con unos bucles for distintos a los que habíamos utilizado hasta la fecha. En estos
bucles for lo que decimos es que extraiga cada vez el siguiente elemento de la lista y lo guarde en
una variable llamada elemento de tipo String.
Primeros pasos
Excepciones
En Java, las excepciones son una clase (documentación) que se lanza cuando ocurre un error en
tiempo de ejecución. Es decir, no son errores de compilación de algo que hemos escrito mal y el
compilador no comprende sino que son errores que ocurren mientras nuestro programa está
siendo usado. Java nos ofrece la posibilidad de controlar estos errores y recuperarnos de ellos sin
abortar la ejecución de nuestro programa.
Ejemplo de código
Image not found con excepciones
or type unknown
Lo que vemos aquí es que el programa compila y se ejecuta sin mayor problema pero durante su
ejecución se intenta realizar una división por 0 y se lanza una excepción (ArithmeticException) con
el error, nos indica en que línea de nuestro código ocurre (línea 7) y se detiene la ejecución del
programa. En un entorno real no sería tolerable que aunque una de las muchas cosas que pueden
fallar el programa se detenga, por ello lo que hay que hacer es controlar la excepción y que el
programa continúe su ejecución. Vamos a ver como contener el error:
Ejemplo
Image de código
not found con excepción
or type unknown controlada
Lo que hacemos aquí es crear un bloque try-catch-finally. Dentro del try le decimos lo que
queremos que haga y si hay algún error de tipo Exception lo capturamos y hacemos lo que está
dentro del catch. El bloque finally es opcional y es un trozo de código que se ejecutará siempre
falle o no la ejecución en el bloque try. Todas las excepciones, como ArithmeticException, derivan
de Exception por eso si en un bloque catch capturamos Exception capturaremos cualquier
excepción. Es muy cómodo capturar cualquier excepción en un bloque catch pero lo idea es poner
un bloque catch para cada excepción y así saber que falla concretamente. Vamos a ver un
ejemplo:
Ejemplo de código
Image not found con excepción controlada en varios catch
or type unknown
En el código anterior aparecen 2 bloques catch, en el primero de ellos (línea 11) controlo las
excepciones que pudiesen ocurrir de tipo aritmético y en el segundo bloque (línea 14) capturo
cualquier otro tipo de excepción.
En ocasiones puede resultarnos útil lanzar nosotros mismos un error bien de tiempo genérico
(Exception) o bien extendiendo la clase Exception para crearnos nuestro error personalizado. Dado
que aún no hemos visto como extender una clase vamos a ver a continuación un trozo de código
donde lancemos una excepción genérica:
Ejemplo
Image de código
not found lanzando
or type unknown excepciones
En la imagen anterior vemos que creamos una función en la línea 6 que realiza la división de 2
parámetros. En la línea 7 comprobamos que el dividendo no sea 0 ya que no se puede dividir por 0.
En caso de que el dividendo sea 0 en la línea 8 lanzamos una excepción (realmente un objeto
realmente que inicializamos con su constructor, veremos estos conceptos en el siguiente módulo)
con un mensaje personalizado. Como dentro de nuestra función lanzamos una excepción tenemos
que indicar de algún modo que este módulo lanza excepciones de tipo Excepcion, por ello en la
línea 6 añadimos a nuestra función throws Exception. En el mail lo único que hago es mostrar por
pantalla el resultado de llamar a esta función. En el primer caso vemos que entra al catch (línea
15) mientras que en el segundo caso al no lanzarse ninguna excepción no se ejecuta el código
contenido en el catch. Ninguno de estos try-catch incluye el bloque finally que como dijimos
anteriormente es opcional.
Primeros pasos
Convenios de escritura
Cuando os hablé de "Constanes y variables" ya comenté algo sobre los convenios de escritura en
Java. Vamos a recordarlo:
Si eres observador/a te habrás dado cuenta de que los tipos básicos empiezan en
minúscula mientras que los objetos comienzan en mayúsculas. Es probable que
también te hayas percatado de que el nombre que asigno a las variables siempre
comienza en minúsculas y el nombre que asigno a las constantes está
completamente en mayúsculas, esto son convenios de escritura del lenguaje
Java y tu puedes seguir tu propio estilo de código pero es interesante hacer uso
del convenio porque facilita la lectura y comprensión del código yen caso de
trabajar con otras personas se es mas productivo. En este módulo, un poco mas
adelante, hablaremos en mayor profundidad de esta cuestión.
Hay que dejar claro que un convenio no es mas que eso, un convenio. No estamos obligados a
seguirlo pero si va a facilitarnos la labor a la hora de entender código de otras personas. Además,
si acostumbramos a nuestro alumnado a seguirlo nos facilitará enormemente la tarea de
corrección y detección de errores en su código. Voy a elaborar una pequeña tabla donde recoger
algunas generalidades al respecto:
No me cansaré de insistir en que el compilador no comprueba que sigamos ningún convenio (ni
que la lógica del programa sea correcta). El compilador únicamente va a comprobar que
sintácticamente el código está escrito del modo adecuado.
Primeros pasos
Algoritmos y estructuras de
resolución de problemas
sencillos
Para dar solución a este apartado he preferido crear un proyecto completo con Netbeans de modo
que en él dé solución a distintas cuestiones como:
Sería demasiado largo y farragoso comentar en este apartado todo el código de este proyecto no
obstante he procurado que el código sea muy claro.
Para hacer más sencilla la lectura he dividido el código en 3 clases main. Para ejecutar una u otra
basta con que en Netbeans, en las propiedades del proyecto, selecciones que clase main quieres
ejecutar en cada momento. También puedes colocarte encima de la clase que contenga main que
quieras ejecutar y pulsando sobre ella con el click derecho elegir run.
Tarea
Tu tarea una vez acabado el segundo módulo consiste en:
Introducción a la POO
Por fin tenemos la suficiente base como para comenzar a trabajar con Programación Orientada a
Objetos (POO) mas allá de las pequeñas pinceladas que hemos introducido.
En este tercer módulo del curso vamos familiarizarnos con los principales conceptos de la POO
como son la herencia, el polimorfismo y el encapsulamiento.
Introducción a la POO
Objetos
Una vez que hemos hablado de las clases el siguiente paso es hablar de los objetos. Los objetos
son la clave para entender la programación orientada a objetos. Todo a nuestro alrededor puede
ser considerado un objeto.
Consideramos que los objetos de nuestro alrededor tienen 2 características comunes: el estado y
el comportamiento. El estado hace referencia al estado actual de una característica del objeto,
pensando en un coche su color, velocidad, marcha,... Mientras que el comportamiento hace
referencia a las acciones que el objeto puede llevar a cabo, continuando con el coche: acelerar,
frenar, cambiar de marcha,... En ocasiones un objeto puede estar compuesto por otros objetos. Los
objetos guardan su estado en campos y exponen su comportamiento a través de métodos. Los
métodos son quienes operan con el estado de los objetos con lo que son los encargados de
proporcionar la comunicación con el objeto. Al hacer que se acceda a los campos/atributos a través
métodos garantizados que en los campos únicamente haya valores que nos interese (lo trataremos
en el apartado encapsulación).
Desde un punto de vista técnico, un objeto es una instancia de una clase, pero ¿qué significa
esto?
Cuando creamos una instancia estamos reservando una zona de memoria dedicada para el objeto
en cuestión y, en Java, esa zona va a permanecer ahí mientras la variable en cuestión (u otra) la
referencie. Tras leer lo anterior podemos pensar en un objeto como que un puntero a la zona de
memoria que ocupa pero en POO no suele hablarse siguiendo esa terminología.
https://es.wikipedia.org/wiki/Objeto_(programaci%C3%B3n)
Introducción a la POO
Clases
Lo primero que vamos a hacer va a ser ver la definición que nos ofrece la wikipedia sobre lo que
es una clase:
https://es.wikipedia.org/wiki/Clase_(inform%C3%A1tica)
Ahora que tenemos una definición de lo que es una clase vamos a ver cual es la sintaxis de la
misma.
NombreClase{
Cuando he definido la sintaxis de una clase he indicado que en su interior existen las sentencias
del cuerpo de la clase, ahora voy a afinar mas. En Java las clases, generalmente, están
formadas por una serie de atributos, constructores y métodos:
Atributos: En caso de existir atributos (variables o constantes) estos pueden ser de tipo
primitivo (int, float,...) o puede ser otro objeto (String, Coche, Integer,...).
Constructores: Son métodos especiales que nos van a permitir crear la instancia de
nuestra clase. Todas las clases tienen sin excepción al menos 1 constructor, aunque no
esté escrito en el programa.
Métodos: Es lo mismo que una función (las veíamos en el módulo 2) pero en este caso
reciben este nombre cuando hablamos de objetos.
Como ya indicamos en el módulo anterior, el convenio establece que la primera letra de una
clase debe ser una letra mayúscula. Personalmente, cuando creo una clase lo hago en el orden
que he indicado en la lista anterior. Primero escribo los atributos, a continuación los constructores
y después los métodos.
Hasta aquí fácil, ¿verdad? Pues bien, a esta sintaxis básica (que ya habíamos utilizado) le iremos
añadiendo una serie de modificadores como public, final, extend y/o implements para ir poco a
poco avanzando en nuestros programas.
En Java existe una jerarquía de clases en la que todas las clases derivan de una clase
llamada Object. Si miramos la documentación de cualquier clase veremos que todas, sin
excepción, derivan de ella. Cuando una clase extiende a otra hereda todas las variables y
métodos de la superclase (clase de la que hereda).
A continuación voy a poner una imagen de la jerarquía de clases de la clase ArrayList según
obtenemos de la propia documentación:
Explicación
Image not foundde
or la documentación
type unknown
En caso de no poder distinguir los colores, la explicación sigue el orden de los recuadros. Es decir,
el primer recuadro es el rojo, el segundo el amarillo,...
Para terminar con este apartado voy a enumerar los distintos tipos de clases existentes.
Públicas.
Abstractas.
Finales.
Existe una cuarta opción que es la de no poner modificar a la clase.
Atributos
Anteriormente hemos indicado que una clase puede contener o no atributos (también llamados
campos o variables miembro) y que estos atributos podían ser de tipo primitivo o bien otras clases.
Ejemplo
Image de código
not found con atributos
or type unknown
En la clase Clase existe var1 (línea 7) que es un atributo variable de tipo int (tipo primitivo). Existe
VAR_2 (línea 8) que es un atributo constante de tipo int (tipo primitivo). Existe var3 (línea 10) que
es un atributo variable de la clase Integer y, por último, existe VAR_4 (línea 11) que es un atributo
constante de la clase Integer. Aquí he utilizado la clase Integer perteneciente al API de Java, pero si
tuviese creadas varias clases podría crear variables de la clase que me interesase. Vamos a ver
otro ejemplo:
Ejemplo de código
Image not found con atributos y composición
or type unknown
En la imagen anterior vemos 2 clases. La clase Motor, que tiene 3 atributos, y la clase Coche, con
otros 3 atributos. Si nos fijamos en la línea 7 de la clase Coche veremos que uno de sus atributos
es de tipo Motor. En este caso se dice que la clase Coche está compuesta por la clase Motor, no
confundir con la herencia (la tratamos mas adelante)
Las clases pueden contener atributos estáticos, para ello antes del tipo utilizaremos la palabra
reservada static, pero de esto hablaremos mas adelante.
Introducción a la POO
Constructores
Vamos a ver que definición de constructor encontramos en la wikipedia:
https://es.wikipedia.org/wiki/Constructor_(inform%C3%A1tica)
Es decir, el constructor nos va a permitir crear una instancia de una clase (un objeto). Un
constructor es un método especial. Vamos a ver su sintaxis:
modificadorDeAcceso NombreDeLaClase(OpcionalmenteParámetros){
sentencias;
Ejemplo
Image de código
not found con constructores
or type unknown
En la imagen anterior la clase Coche tiene 2 constructores. Un constructor vacío entre las líneas 9 y
11 y un constructor con todos sus parámetros entre las líneas 13 y 17. Por lo que podremos crear
objetos de cualquiera de los 2 modos que vemos a continuación:
Cuando una clase no tiene escrito ningún constructor el compilador asume que la clase
en cuestión tiene el constructor vacío. Es decir, si en el ejemplo anterior suprimimos las líneas
9 a 17 sería equivalente a dejar las líneas 9 a 11 y podríamos crear objetos únicamente así:
Sin embargo, si en el ejemplo anterior suprimimos las líneas 9 a 11 el único constructor que tendrá
la clase será el que obliga a dar valor a todos sus atributos, es decir, sólo podríamos utilizar el
siguiente modo para crear objetos:
Coche coche4 = new Coche( "Ford", "Fiesta", new Motor() );
Antes comenté que eran métodos especiales porque si te fijas la sintaxis es igual a la de los
métodos con la salvedad de que no se indica el tipo de dato que devuelve y esto es así porque un
constructor siempre devuelve como tipo de dato una instancia de la propia clase.
En las líneas 14 a 16 hago uso de la palabra reservada this. Cuando en la línea 14 escribo
this.marca me estoy refiriendo a la variable marca de la clase y no al parámetro marca. Es decir,
cuando escribo this.marca = marca; estoy diciendo que la variable marca de la clase pase a valer
lo que valga el parámetro marca. Además de this, en un constructor podemos encontrarnos la
palabra reservada super, pero el uso de esta lo veremos cuando hablemos de herencia.
En este curso siempre vamos a utilizar el modificador de acceso public para los constructores. Si
quieres ver cuando podría tener sentido tener un constructor de acceso privado (private) puedes
leer acerca del patrón de diseño Singleton.
Introducción a la POO
Métodos
En el módulo 2 de este curso estuvimos hablando de las funciones. Un método es básicamente lo
mismo que una función pero asociado a un objeto. Cuando en el siguiente apartado de este
módulo hablemos de la palabra reservada static espero aclarar mejor esta diferenciación.
En el ejemplo anterior aparece un método entre las líneas 19 y 22. El método es de acceso público
(public), no devuelve nada (void), se llama escribirInformacion y no tiene parámetros. El método
tiene una única sentencia que ocupa las líneas 20 y 21 y que muestra por pantalla un texto. Fíjate
que puedes acceder a los atributos de la clase con o sin this.
En Java, dentro de una clase puedes tener 2 métodos que se llamen igual siempre y
cuando el número de parámetros que utilicen o el tipo varíe. A continuación tenemos un
ejemplo:
En el ejemplo anterior vemos que dentro de la misma clase tenemos 2 métodos que se llaman
igual (escribirInformacion. Podemos tenerlos porque en la línea 9 definimos uno de ellos sin
parámetros y en la línea 14 definimos otro con un solo parámetro de tipo boolean. Podríamos tener
otro mas de un solo parámetro siempre y cuando este no fuera de tipo boolean.
Si eres observador/a te habrás dado cuenta de que cuando creo un método no uso la palabra
reservada static como hacía con las funciones, en el siguiente capítulo voy a tratar de explicarte el
porqué.
Introducción a la POO
Static
Tenemos la posibilidad de crear variables de clase y métodos de clase haciendo uso de la
palabra reservada static. Para ello haremos uso de la siguiente sintaxis para las variables de clase:
sentencias;
En ocasiones nos puede interesar que una variable no esté asociada a un objeto sino que esté
asociada a la clase, en ese momento es cuando nos interesa crear una variable de clase.
Análogamente puede ocurrir con un método. Si en un momento dado nos interesa que el método
esté asociado a la clase y no al objeto entonces debemos hacerlo estático, debemos hacer un
método de clase.
NombreDeLaClase.nombreVariable;
NombreDeLaClase.nombreMetodo(parámetros);
Creando objetos
Cuando queremos acceder a un atributo de una determinada clase debemos hacerlo utilizando
la siguiente sintáxis:
nombreObjeto.nombreAtributo;
Del mismo modo procederemos cuando a lo que queramos acceder sea al método de un objeto:
nombreObjeto.nombreMetodo(parámetros);
Lo anterior estará permitido siempre y cuando tengamos el control de acceso adecuado para el
atributo o método o cuestión. Sobre el control de acceso os hablaré un poco mas adelante en este
módulo, de momento vamos a considerar que no existen estas limitaciones.
¿Y si sobre el ejemplo anterior quisiésemos acceder al nombre del primer perro de la cliente
Vanesa? Pues haríamos lo siguiente:
La sentencia anterior es un poco peligrosa y evitaremos utilizarla si antes no hacemos una serie de
comprobaciones o incluimos la misma en un bloque try-catch para controlar las excepciones.
En Lanzador.java vamos a decir que ahora la variable patos valga nulo. Con ella está claro que
pasará a valer nulo, pero ¿qué pasará con vanesa.patos que hemos dicho que valga lo que vale esa
variable?
Lo que ocurre en la línea 29 es que al atributo patos del objeto vanesa le decimos que pase a
apuntar a la misma zona de memoria que apunta la variable patos. Posteriormente decimos en la
línea 31 que la variable patos que apuntaba a una determinada zona de memoria pase a no
apuntar a ningún sitio (null) pero eso no afecta en que el atributo patos del objeto vanesa cambie
su valor. Lo podemos ver en el resultado que aparece en consola ([Pato@15db9742] es la dirección
de memoria que la JRE le asigna al objeto)
Otra duda, si creo 2 objetos cuyos atributos tengan exactamente los mismos valores, ¿qué pasará?
Lo que ocurre es que gemelo1 y gemelo2 apuntan a zonas de memoria distintas por eso el
compilador nos dice que los objetos son distintos.
En Java para comparar objetos utilizaremos el método equals. Todos los objetos tienen
dicho método puesto que en Java todas las clases derivan de la clase Object y la clase Object tiene
este método. Ahora bien, para que equals funcione del modo esperado deberemos sobreescribir el
método en nuestra Clase, lo veremos en el apartado de herencia.
Herencia
Una de las características de un lenguaje de programación orientado a objetos es la herencia. En
algún capíutlo anterior a este ya hemos visto alguna funcionalidad de la herencia, pero de aquí en
adelante vamos a profundizar en ella.
En POO, la herencia es un mecanismo que nos permite extender las funcionalidades de una clase
ya existente. De este modo vamos a favorecer la reutilización de nuestro código.
Hay que indica que solo podemos heredar de una clase a la vez. Llamaremos superclase a la
clase padre y subclase a la clase que hereda.
¿Qué ocurre cuando una clase hereda de otra? Pues que la subclase tiene acceso (en función del
control de acceso que veremos mas adelante) a los métodos y atributos de la superclase. Vamos a
ver un ejemplo a continuación:
Código
Image notcon ejemplo
found de herencia
or type unknown
Lo que vemos en el código anterior son 4 clases públicas (Abuelo, Padre, Hijo y Modulo3Clases. La
clase Abuelo la definimos en la línea 4 de su código y al no usar la palabra reservada extends
no hereda nada mas que de la clase Object. En la clase Abuelo definimos una variable y un
método. En la línea 5 de la clase Padre indicamos que esta clase extiende a Abuelo con lo que
hereda de dicha clase y puede hacer uso de las variables y médotos de Abuelo además de
los suyos propios. La clase Hijo hereda de Padre (que a su vez heredaba de Abuelo) por lo que en la
clase Hijo tendremos acceso tanto a las variables y métodos de Padre como los de Abuelo. En la
clase Padre ya hacemos uso de una variable de Abuelo en su línea 8. En la clase Hijo hacemos uso
de una varible de Abuelo en la línea 8 y un método de la clase Padre en la línea 9. Por último,
tenemos la clase Modulo3Clases que contiene el método main. En las líneas 8 a 10 creamos los
objetos de tipo Abuelo, Padre e Hijo. Estos objetos son los que nos dan acceso al código asociado a
la clase. En la línea 12 y 13 vemos como desde el objeto padre tenemos acceso a métodos de la
clase Abuelo y de la propia clase Padre. Lo mismo ocurre con el objeto hijo en las líneas 18 a 20.
El ejemplo anterior símplemente pretende ilustrar la herencia de atributos y métodos pero ahora
vamos a ir un poco mas allá. Vamos a pensar en perros, patos, gatos y vamos a tratar de
abstraernos sobre lo que son. Todos ellos son mamíferos y tienen una determinada cantidad de
patas. Probablemente todos ellos realicen las mismas acciones. Por ello voy a crear una clase
llamada Mamifero con los atributos y métodos comunes y luego crearé una clase para cada animal
que contenga sus peculiaridades. Vamos allá:
Código
Image notcon ejemplos
found de herencia
or type unknown
En el ejemplo anterior hay que recordar que el hecho de que una clase no indique explícitamente
que hereda de ninguna otra implica que dicha clase hereda de Object. Es decir, en el ejemplo
anterior Mamifero hereda de Object. Como Perro hereda de Mamifero y Mamifero hereda de Object
la clase Perro tendrá acceso a sus propios atributos y métodos y a los de Mamifero y Object.
Vamos a llevar nuestro ejemplo un poco mas allá. Vamos a pensar que quisiésemos organizar un
concurso de animales en el cual pudiesen apuntarse un máximo de 100 animales siendo que solo
pueden participar perros, patos y gatos ¿haríamos una lista para cada animal? Vamos a ver en el
siguiente capítulo como el polimorfismo puede ayudarnos.
Introducción a la POO
Polimorfismo
El polimorfismo es la capacidad que nos proporciona un lenguaje de programación orientado a
objetos para tratar un objeto como si fuera un objeto de otra clase.
Existen lenguajes de programación donde una variable puede contener prácticamente cualquier
tipo de dato, es el caso de los lenguajes PHP, Python y Javascript (recuerda, Javascript no es Java,
son lenguajes distintos), mientras que existen otros lenguajes de programación en los que una
variable definida de un modo solo pude contener variables de dicho tipo, es el caso de Java. Java es
un lenguaje fuertemente tipado.
Debido a este fuerte tipado en ocasiones nos encontramos con que tenemos que moldear un
determinado objeto de modo que quepa en el molde de otro, para ello utilizaremos el llamado
casting o typecasting.
Ejemplo
Image de código
not found con polimorfismo
or type unknown
El ejemplo anterior no cambia en nada las clases Perro, Pato y Gato utilizadas en el ejemplo visto
en el apartado Herencia. Todos los cambios ocurren en la clase Lanzador. Si nos fijamos en ella
vemos que en la línea 12 creamos un ArrayList en la cual indicamos que vamos a añadir objetos de
la clase Mamifero sin embargo en las líneas 13 y 14 vemos que añadimos 2 objetos de tipo Perro,
en la línea 15 un objeto de tipo Pato y en la línea 16 añadimos un objeto de tipo Gato. En este caso
el compilador realiza un casting implícito ya que todos los tipos anteriores son descendientes de
Mamifero. Si en lugar de crear un ArrayList huviesemos creado un ArrayList entonces no habríamos
podido insertar al pato ni al gato. Prosigamos, en la línea 18 nos encontramos con un bucle for
mejorado que recorreraá todos los elementos del array y los guardará en una variable llamada
animal de tipo Mamifero. Vemos que en las líneas 19, 21 y 23 usamos una palabra reservada
nueva (instanceof), esta palabra lo que hace es devolver verdadero en caso de que la variable
animal sea una instancia de Perro, Pato o Gato respectivamente. Cuando la condición es cierta
entramos dentro del if y se realiza un casting explícito, es decir, le decimos que comportamiento
queremos que tenga ese objeto para que así podamos acceder a sus métodos y atributos. En la
línea 20 nos encontramos ((Perro) animal).saluda(); aquí lo que ocurre es que se realiza el cast
sobre animal para que se comporte como si fuera de tipo Perro y una vez que se ha realizado el
cast y ya no es de tipo animal sino que es de tipo Perro, entonces es cuando tenemos acceso al
método saludar y no antes. Ocurre lo mismo en las líneas 22 y 24.
En nuestro ejemplo de herencia y polimorfismo hemos creado una clase (Mamifero) que queríamos
sirviese de base para otras (Perro, Pato y Gato) pero que no hemos llegado a utilizar. En el capítulo
Clases abstractas e interfaces veremos cual habría sido la forma mas adecuada de diseñar esta
jerarquía de clases.
Pregunta Verdadero-Falso
Java y Javascript son el mismo lenguaje de programación. Nos referimos a Javascript como Java
para tener un lenguaje mas fluido.
Sobreescritura de métodos
Otra característica asociada a la herencia es la sobreescritura de métodos. La wikipedia se
refiere a ella como [redefinición de
métodos](https://es.wikipedia.org/wiki/Herencia_(inform%C3%A1tica) pero yo nunca la he visto
denominada de ese modo con anterioridad.
Cuando dentro del apartado Clases estuvimos hablando de los métodos nombramos por primera
vez la sobreescritura de métodos. No hay que confundir la sobreescritura de métodos con que un
mismo método pueda ser definido de modos distintos.
La sobreescritura de métodos nos permite redifinir un método que heredamos para que este
funcione de acuerdo a nuestras necesidades y no a lo definido en la superclase. Cuando en un
objeto llamamos a un método el compilador comprueba si el método existe en nuestro objeto, si
existe lo usa y si no existe en nuestro objeto entonces lo busca en la superclase. Esto ocurre así
hasta que el compilador encuentra el método definido. El compilador busca el método de abajo a
arriba.
Cuando redefinimos un métodos podemos hacer uso del propio método que estamos redefiniendo,
para ello haremos uso de la palabra reservada super. Voy a modificar el código del ejemplo
anterior para que podamos verlo:
En el extracto anterior vemos que he añadido super.toString() para decirle a mi método toString
que llame al método toString de la superclase. Debajo del código aparece el resultado que se
produce al ejecutar el programa tras el cambio.
Introducción a la POO
Control de acceso
Hasta el momento hemos visto que desde cualquier clase se puede acceder a cualquier otra clase
y a cualquier atributo o método sin ningún control. Esto lo hemos hecho de este modo para facilitar
la comprensión de los distintos conceptos tratados a lo largo del curso y de este modo no
distraernos con cuestiones de control de acceso pero a partir de este momento vamos a hablar del
control de acceso en clases, atributos, constructores y métodos para así empezar a desarrollar
nuestros programas de un modo mas adecuado.
a clases
Cuando definimos una clase podemos hacerlo con la palabra reservada public, abstract, final o
ninguna de los anteriores. Existe alguna otra posibilidad pero no entraremos en ella.
|Clase|Descripción| |:--|:--| |public|Una clase pública es accesible desde cualquier clase. Para ser
utilizada desde otro paquete debe ser importada.| |abstract|Una clase abstracta es una clase
destinada a que se herede de ella. No puede ser instanciada. Debe tener al menos un método
abstracto.| |final|Una clase final es aquella que no permite que se herede de ella.|
class Ejemplo2{
En las 6 líneas anteriores tenemos todas las combinaciones con las que vamos a trabajar en el
curso.
La clase Ejemplo1 es una clase pública por lo que será accesible desde cualquier paquete y se
podrán crear instancias de ella y usarla como superclase.
La clase Ejemplo2 será accesible únicamente desde el paquete en que sea definida y se podrán
crear instancias de ella y usarla como superclase.
La clase Ejemplo3 es una clase pública por lo que será accesible desde cualquier paquete y al ser
abstracta no se podrán crear instancias de ella, deberá contener al menos un método abstracto y
se podrá usar como superclase.
La clase Ejemplo4 será accesible únicamente desde el paquete en que sea definida y al ser
abstracta no se podrán crear instancias de ella, deberá contener al menos un método abstracto y
se podrá usar como superclase.
La clase Ejemplo5 es una clase pública por lo que será accesible desde cualquier paquete pudiendo
ser instanciada pero no usada como superclase.
La clase ejemplo6 será accesible únicamente desde el paquete en que sea definida pudiendo ser
instanciada pero no usada como superclase.
a atributos
Existen las siguientes palabras clave cuando queremos controla el acceso a las variables miembro
de nuestras clases. Vamos a verlas:
|Atributo|Descripción| |:--|:--| |public|El campo es accesible desde todas las clases| |private|El
campo es accesible únicamente desde la propia clase| |final|El campo no puede ser modificado y al
definirse debe establecerse su valor.|
String ejemplo2;
ejemplo2 sería accesible únicamente desde las clases que pertenezcan al mismo paquete y
cualquiera de ellas podría modificarla.
ejemplo3 sería accesible únicamente desde la clase en que se ha definido y podría ser modificada.
ejemplo5 sería accesible únicamente desde las clases que pertenezcan al mismo paquete. No se
podría modificar su valor.
ejemplo6 sería accesible únicamente desde la clase en que se ha definido. No se podría modificar
su valor.
Es común que los campos se definan como privados para así sacar todo el potencial de la
encapsulación (la veremos en el siguiente capítulo).
a constructores
|Constructor|Descripción| |:--|:--| |public|Cualquier clase puede crear instancias de la clase que
contenga un constructor público.| |protected|Solamente las subclases de la clase que contiene un
constructor protegido pueden crear instancias de la clase.| |private|Ninguna clase puede crear
instancias de una clase que tiene un constructor privado excepto la propia clase a través de alguno
de sus métodos públicos.|
El patrón de diseño singleton es un ejemplo a través del cual ver la utilidad de definir un
constructor privado.
a métodos
A la hora de establecer el control de acceso a un método en el curso vamos a trabajar con public,
private, protected, abstract y final.
|Método|Descripción| |:--|:--| |public|El método es accesible desde la propia clase, el paquete al que
pertenezca la clase, las subclases y el resto del mundo.| |protected|El método es accesible desde la
propia clase, el paquete al que pertenezca la clase y las subclases.| |private|El método es accesible
desde la propia clase.| |abstract|El método no está definido en esta clase sino que será definido en
la clase que herede de la clase que contenga este método.| |final|El método no puede ser
sobreescrito.|
Cuando un método es abstracto no se pone el bloque de código que va entre las llaves ({}) ni las
propias llaves, esto tiene sentido porque el método en cuestión debe definirse en la clase que
herede la clase que contenga el método abstracto.
void ejemplo3(){
En los 11 ejemplos anteriores no hay valor de retorno (void) y como puede apreciarse no existe la
combinación private abstract ya que no tendría sentido. Existe alguna otra palabra reservada que
da lugar a mas combinaciones pero estas son suficientes para el objetivo del curso.
En la documentación oficial de Java sobre el control de acceso podemos encontrar mas información
(en inglés).
Introducción a la POO
Encapsulamiento
La encapsulación es un principio fundamental de la programación orientada a objetos y consiste en
ocultar el estado interno del objeto y obligar a que toda interacción se realice a través de los
métodos del objeto.
En el código que hemos desarrollado hasta el momento hemos dado libre acceso a los atributos de
nuestros objetos lo cual presenta riesgos ya que no tenemos ningún tipo de control sobre lo que
puede o no hacerse con ellos. Nos va a interesar que a nuestros atributos solo se pueda acceder a
través de los métodos, de modo que obtengamos control sobre lo que puede hacerse con los
atributos.
Para ello, el acceso a los atributos se establece como privado y se crean 2 métodos por cada
atributo, un getter y un setter. El getter de un atributo se llamará getNombreAtributo mientras
que el setter de un atributo se llamará setNombreAtributo. Vamos a ver un ejemplo para entender
esto mejor:
Código
Image notcon ejemplo
found de encapsulamiento
or type unknown
Si nos fijamos en Mesa.java veremos que es una clase con 1 atributo privado llamado color y 2
métodos que se llaman getColor y setColor. Los métodos anteriores serían, respectivamente, el
getter y setter de del atributo color. Ahora que ya conocemos el control de acceso que sobre
clases, atributos, constructores y métodos puede realizarse sabemos que no puede accederse
directamente al atributo ni para obtener su valor ni para establecer su valor, siempre que quieran
realizarse esas acciones habrá que pasar respectivamente por el getter y el setter y en ellos
podremos programar aquello que nos interese. Si nos fijamos en Principal.java veremos que si
ahora queremos acceder directamente al atributo para modificar u obtener su valor no podemos
(he dejado comentado el código que falla) y que para hacerlo estamos obligados a utilizar los
getter y setters que hemos creado antes.
Si bien es cierto que podríamos llamar a los getters y setters de cualquier otro modo por
convenio se utiliza la sintaxis que hemos visto con anterioridad. Hacer uso de este
convenio nos facilitará trabajar con el resto del mundo y nos permitirá ampliar las capacidades de
nuestro código utilizando frameworks existentes que hacen uso del convenio y que si no seguimos
no podremos utilizar.
Interfaces y clases
abstractas
Ya hemos hablado con anterioridad de las clases abstractas (capítulo polimorfismo), en este
capítulo profundizaremos un poco mas sobre ellas y además hablaremos por primera vez de las
interfaces.
Interfaces
Cuando alguien te pregunta que es una interface suele decirse que es un contrato, una forma de
asegurarse que todo el mundo que implemente una interface va a hacer algo. No nos importa
como vayan a hacerlo pero estamos seguros que si una clase implemente una interface entonces
va a tener que cumplir el contrato e implementar lo acordado.
sentencias;
sentencias;
Una clase puede implementar 0 o varias interfaces al mismo tiempo. En caso de implementar
varias interfaces separaremos sus nombres por comas. El hecho de poder implementar varias
interfaces al mismo tiempo nos sirve para esquivar la limitación de que una clase solo pueda
heredar de una única clase. En caso de que una clase extendise a otra clase y a la vez
implementase 1 o varias interfaces la sintaxis sería la siguiente:
sentencias;
}
Las interfaces pueden ser públicas (accesibles desde cualquier lugar) o sin modificador de acceso
(accesibles desde el paquete de la interface).
Una interface no puede ser instanciada (si se podría pero es demasiado avanzado para el curso).
Una interface puede contener métodos abstractos y métodos estáticos, ambos se considerarán
públicos (aunque no se indique). También pueden añadir métodos por defecto (con el modificador
default) pero no los vamos a ver en este curso.
Una interface puede contener atributos que a todos los efectos será una constante, estaremos
obligados a darle valor. Los atributos que creemos se considerarán públicos, estáticos y finales por
lo que podemos omitir los modificadores.
Una interface puede extender otras inferfaces, lo hará con la siguiente sintaxis
sentencias;
Clases abstractas
La sintaxis necesaria para crear una clase abstracta es la siguiente
sentencias;
Las clases abstractas pueden incluir o no métodos abstractos. Las clases abstractas no pueden
ser instanciadas pero si pueden ser usadas como subclases.
Un método abstracto es un método que está declarado pero no está implementado. En su sintaxis
se suprimen las llaves ({}) y tras cerrar el paántesis que contiene los parámentros se pone un
punto y coma.
Si una clase contiene un método abstracto tiene que ser obligatoriamente una clase abstracta.
Cuando una clase hereda de una clase abstracta y la superclase contiene un método abstracto
estamos obligados a implementarlo.
En las clases abstractas puedes disponer de atributos sin que estos sean constantes (como ocurre
en las interfaces) y además puedes crear métodos públicos, protegidos o privados (en las
interfaces todos eran públicos).
Solo puedes extender una clase (abstracta o no) mientas que puedes implementar cualquier
número de interfaces.
En el apartado "código utilizado en los ejemplos" dejo un proyecto en el cual hago uso de
interfaces y clases abstractas.
Introducción a la POO
El convenio dice que los paquetes deben nombrarse en minúsculas y cuando se necesitan usar
varias palabras separarlas por un guión bajo. Además, suele utilizarse el dominio de nuestra
empresa invertido, de este modo, podemos diferenciar clases que compartan nombre.
Para indicar que una clase pertenece a un determinado paquete debemos indicarlo usando
package nombreDelPaquete y ubicando la clase dentro de dicha ruta de carpetas. Vamos a ver un
ejemplo:
Cuando en nuestros programas queremos usar una clase que no pertenece a nuestro paquete (y
tenemos permiso para ello) existen 2 posibilidades:
El proyecto de la imagen está formado por 80 clases agrupadas en 9 paquetes distintos en función
de las funcionalidades que cada clase tiene.
Java nos proporciona una cantidad de paquetes enormes lista para utilizar en nuestros paquetes,
esta librería recibe el nombre de API (Application Programming Interface) La especificación
completa del API de Java 8 para su edición estándar está accesible aquí.
Introducción a la POO
Tarea
Tu tarea una vez acabado el tercer módulo consiste en:
Terminando
El objetivo de este último módulo es facilitarte mas recursos. Por ello voy a realizar 1 ejemplo
completo desde su fase de análisis hasta su fase de codificación tratando de explicarte aquellas
partes mas relevantes. También voy a ver unas pinceladas sobre como crear una interfaz gráfica
de usuario, facilitarte algo de bibliografía y, como siempre, dejarte todo el código completo y una
tarea.
Terminando
Ahora que tenemos definido nuestro programa es el momento de ponernos a pensar antes de
empezar a codificar. Para ello en los siguientes capítulos empezaremos por definir las clases que
hemos detectado y las relaciones existentes entre ellas. Una vez que tengamos definido lo anterior
será el momento de empezar a escribir el código fuente.
Terminando
Una vez hemos identificado las clases y sus atributos lo ideal sería utilizar algún modo estandar de
representarlo. Yo he optado por utilizar un lenguaje unificado de modelado (UML) para esta tarea y
concretamente lo relativo a los diagramas de clases que es la tarea que nos ocupa. Con UML cada
clase estará contenida en un recuadro que dividiré horizontalmente en 3 recuadros. En el recuadro
superior escribiré el nombre de la clase, en el recuadro inferior los atributos de la clase y en el
recuadro inferior los métodos de la clase. Vamos a ver como quedarían nuestras clases dibujadas
de este modo.
En la imagen superior vemos el modo en que dibujaríamos las clases de nuestros problema. El
campo para los métodos de momento lo he dejado vacío. En los atributos, antes de su nombre, he
puesto el símbolo - para indicar que se trata de un atributo privado y cumplir así los criterios de
encapsulación cuando cree los getters y setters correspondientes.
software/
En el siguiente apartado vamos a redefinir este diagrama para ver si de algún modo existe
herencia y las distintas relaciones entre las clases.
Terminando
Jerarquía de clases
Si analizamos el diagrama de clases que hemos realizado en el apartado anterior observamos que
los clientes y los propietarios comparten parte de sus atributos por lo que podríamos crear una
abstracción que llamásemos Persona que tuviese estos campos y que posteriormente Propietario y
Cliente heredasen de ella. Vamos a ver como quedaría.
Fíjate que en la imagen anterior la clase Persona, al considerarla abstracta, escribimos su nombre
con letra cursiva. Consideramos la clase Persona abstracta porque no vamos a tener que crear en
ningún momento instancias de de ella.
De modo análogo ocurre con Vehículo, Coche y Moto. A fin de cuentas comparten una serie de
atributos, podemos "sacar factor común" haciendo que Coche y Moto herenden de Vehículo tal y
como vemos en la imagen posterior.
Igual que antes Vehículo es una clase abstracta y como tal escribimos su nombre en cursiva. Coche
y Moto extenderán a Vehículo.
Si comparamos nuestro esquema actual con nuestro primer esquema observaremos que nos falta
la clase Taller así que vamos a añadirla a nuestro esquema.
Casi hemos terminado. De algún modo tenemos que expresar la composición entre clases y la
cardinalidad existente. Es decir, si nos fijamos en la clase Cliente vemos que está compuesta por
una lista de Vehículos, tenemos que expresarlo de algún modo, además, cada cliente deberá tener
al menos 1 vehículo. Si nos fijamos en Taller vemos que está compuesto tanto por Propietario
(cada taller tiene 1 único propietario) como por una lista de clientes que serán 0 o mas. Vamos a
ver como representar esta composición y cardinalidad.
Con esto tendríamos terminado nuestro esquema de clases donde podemos observar la jerarquía
de clases existente y las relaciones que existen entre ellas. Faltaría añadir en cada clase los
métodos que tiene donde pone Métodos. Únicamente los he añadido en las clases Identificacion,
Vehículo y Moto.
Con esto únicamente nos quedaría codificar nuestro esquema, pero esto lo haremos en el siguiente
capítulo.
Terminando
Codificación
Una vez que tenemos esquematizada la solución de nuestro programa es el momento de
codificarla. En esta sección voy a añadir imágenes de las partes que considero mas relevantes para
solucionar nuestro problema. En el apartado "Código utilizado en los ejemplos" podréis descargar
el código completo del proyecto.
Vamos a contnuar con la clase abstracta Persona que implementa la interface anterior.
Como vemos en esta clase indicamos que es una clase pública y abstracta que implementa la
interface Identificacion. En esta clase tenemos 3 atributos que siguen los principios de la
encapsulación y en la imagen vemos que la clase tiene un único constructor que obliga a definir
una Persona a través de 3 argumentos. Como ya sabemos, al tratarse de una clase abstracta no
podremos crear objetos de esta clase. La clase Vehículo sería similar a esta clase que acabamos de
analizar.
Vamos a continuar con el código de la clase Propietario que hereda de la clase anterior y se verá
obligada a implementar el método de la interface Identificacion.
Vemos en la línea 6 que se trata de una clase pública que extiende a la clase Persona (que a su vez
implementaba a Identificacion). Al heredar de Persona dispondremos de acceso a aquellos
atributos y métodos no privados. Si nos fijamos en el constructor vemos que hemos de llamar a
super (línea 10) para que se llame al constructor de la superclase de Propietario (Persona).
Observamos también en las líneas 28 a 32 la implementación del método de la interface. Del
mismo modo que construimos la clase Propietario procederíamos con la clase Cliente.
Una vez hemos creado todas nuestras clases únicamente necesitaríamos disponer de una clase
con un método main que nos permitiese interactuar con las clases que hemos definido para poder
crear objetos a partir de ellas. En el apartado "Código utilizado en los ejemplos" he añadido 2
clases que nos permiten lanzar la aplicación, la clase Inicio.java contiene una interfaz de tipo texto
y la clase igu contiene una interfaz gráfica de usuario limitada. El código se encuentra
documentado para facilitar su comprensión.
En el siguiente apartado vamos a ver como crear esta interfaz gráfica de usuario a la que hago
referencia en el párrafo anterior.
Terminando
usuario (IGU, GUI en inglés) con la que nosotros interactuemos y de ese modo introduzcamos u
obtengamos datos. Por ello he preparado el siguiente videotutorial en el que muestro como crear
una IGU básica por si queremos incorporarla a nuestros programas.
https://www.youtube.com/embed/jQwbk5A3Lxc?list=PL1ubUMkNBAR_98ka0Q393l3fpzSjo3FGq
Terminando
https://www.youtube.com/embed/9xKSFonCYB8?list=PL1ubUMkNBAR_98ka0Q393l3fpzSjo3FGq
Terminando
Pintemos en Java
En este vídeo vamos a trabajar con las características de la POO (clases abstractas, herencia,
polimorfimo) y vamos a hacerlo a través de una interfaz gráfica de usuario. Además, en esta
interfaz gráfica de usuario, vamos a dibujar los objetos con los que vamos a trabajar. El enunciado
de nuestro problema dice:
https://www.youtube.com/embed/o330-623xrI
Terminando
Bibliografía recomendada
Soy consciente de que quizás el curso no haya resuelto todas tus dudas acerca de la programación
orientada a objetos y el lenguaje de programación Java puesto que se pretende que el mismo sea
una introducción, por ello no querría dejar pasar la ocasión de recomendarte un par de libros que
creo pueden resultarte de utilidad además de la gran cantidad de información existente en
internet.
El primero de los libros se titula "Piensa en Java" escrito por Bruce Eckel. Aunque la última edición
data de 2006 sigue siendo un libro de referencia para quienes quieren iniciarse en la programación
orientada a objetos y el lenguaje de programación Java. En su página oficial (inglés) podemos
encontrar mas información sobre el mismo.
Tarea
La cooperativa de ebanistas de CATEDU nos ha indicado que necesita una aplicación informática
para la gestión de su ebanistería. En esta ebanistería fabrican muebles. De los muebles quieren
guardarse sus dimensiones (ancho, alto y profundo) en centímetros como números enteros. Los
tipos de muebles que fabrican son mesas de oficina, mesas de taller y estanterías. De todas las
mesas se quiere conocer si tienen cajonera o no pero de las mesas de oficina se quiere conocer el
material con el que están hechas mientras que de las mesas de taller se quiere almacenar su
grado de resistencia (un número del 1 al 10). De las estanterías se quiere guardar el número de
baldas.
Crear un diagrama de clases en el que se reflejen las clases de nuestro problema así
como los atributos de las mismas y las relaciones de herencia y composición existentes
en caso de haberlas
Implementar con Java el diagrama que has realizado
Terminando
Hecho con
Image not Padlet
found or type unknown
Terminando
Créditos
Autoría
{{ book.author }}
Los contenidos se distribuyen bajo licencia Creative Commons tipo BY-NC-SA excepto en los
párrafos que se indique lo contrario.