Objetivos Definir los conceptos de Herencia y Polimorfismo. Conocer la implementación de clases abstractas e interfaces en Java. Definir el concepto de clase interna, tipos de declaración y utilidad. Entender la importancia del Polimorfismo en la creación de software extensible. Describir la forma de creación y utilidad del tipo Enum.
Herencia Es una metodología que permite la definición de una clase a partir de la definición de otra ya existente. Permite relacionar un conjunto de clase bajo las mismas características, de manera que puedan ser consideradas y manejas colectivamente. Permite el refinamiento o especialización de una clase existente sin modificar a esta. Se puede definir, ocultar y añadir nuevos miembros. Es una forma de especialización en la que las clases hijas son refinadas para tener el comportamiento y atributos adecuados para la aplicación que se trate. Al poder las clases derivadas añadir y ocultar miembros, la herencia se convierte en reusabilidad programable.
Herencia en Java Sintaxis: public class NombreSubClase extends NombreSuperClase { cuerpo_de_la_clase } En Java hay una clase que es la clase padre de todas las demás: java.lang.Object, por tanto heredan siempre los siguientes métodos: El modificador final Si se aplica a clases se fuerza que la clase no pueda iniciar una jerarquía de herencia (no puede ser superclase de otra clase). Si un método se declara como final, no podrá ser sobrescrito por las subclases.
Herencia y Polimorfismo El polimorfismo es una habilidad de tener varias formas; por ejemplo, la clase AvionComercial tiene acceso a los métodos de la clase Avion. Un objeto tiene sólo un forma. Una variable tiene muchas formas, puede apuntar a un objeto de diferentes maneras. Java permite apuntar a un objeto con una variable definida como tipo de clase padre. Avion miavion = new AvionMilitar( ) ; Sólo se puede acceder a las partes del objeto que pertenecen a la clase Avion; las partes específicas de la clase AvionMilitar no se ven. Este efecto se consigue porque, para el compilador, miavion es sólo una variable de tipo Avion, no AvionMilitar.
Ligadura (binding) Conectar la invocación a un método con el cuerpo del método, se llama binding. Si el binding, se hace en compilación, se llama Early Binding y si se hace en ejecución Late Binding o Dynamic Binding. Early Binding Java usa Early Binding para métodos declarados final o static (los declarados private son implícitamente final) Dynamic Binding La resolución de las invocaciones a métodos, se resuelve en ejecución, basándose en el tipo del objeto receptor.
Práctica 5: Utilizando herencia y polimorfismo en Java Objetivo Implementar una aplicación que use la técnica de la herencia para definir métodos polimórficos Ejercicio: Se desea realizar una aplicación para gestionar las operaciones de un banco. Se conocen las siguientes reglas de negocio de un banco: El banco tiene cuentas corrientes, cuentas de ahorro y clientes. Un cliente tiene al menos una cuenta, aunque puede tener varias cuentas de cualquiera de los dos tipos. Cada cuenta pertenece a un único cliente. La cuenta corriente te da la alternativa de realizar depósitos que te permiten ordenar el manejo de tu dinero y realizar múltiples transacciones de pago. Como ingresos, retiros y consultas de estados de cuenta. La cuenta de ahorro es un tipo de cuenta corriente que puede ganar intereses. Cada cuenta se identifica por un código de cuenta interbancaria (CCI), formado por el identificador del banco, de la sucursal y el nº de la cuenta (dentro de dicha sucursal), se asigna a un titular del cual se conoce los nombres, apellidos y la edad. Las cuentas se crean especificando el titular (cliente), número de cuenta y saldo inicial, por tanto no pueden crearse ningún tipo de cuenta si no se conoce el titular. Las cuentas deben ser capaces de compararse entre sí por su número de cuenta. Los clientes tiene un nombre, una dirección y se identifican por su código. Los clientes del banco son personas reales u organizaciones. Las personas tienen nombres, apellidos fecha de nacimiento y sexo; en cambio las organizaciones tienen un tipo de organización (empresa, institución pública, etc.), un representante y un nº de empleados. Cada sucursal se identifica por su número. Además tiene una dirección, un código postal y una ciudad, en la cual se pueden abrir un número indeterminado de cuentas. Los empleados del banco se identifican por un código asignado por el Banco o por su DNI. También interesa conocer sus apellidos y nombres, fecha de nacimiento, sexo y la sucursal en la que trabajan. El movimiento de las cuentas se identifican por un número de transacción, del cual se sabe la Cuenta, fecha, el tipo (debito o abono) y el monto. a) Identificar las Clases que conforman la aplicación. b) Implementar las clases en Java c) Cree una aplicación Test que defina los métodos: - mostrarDatosCliente , que permita mostrar en consola la información de cualquier tipo de cliente. - debitar , que dado una cuenta permita retirar cierta cantidad de dinero. - abonar , que dado una cuenta permita incrementar en saldo de la cuenta. - estadoDeCuenta , que dado una cuenta lista sus movimientos y el saldo actual. d) ¿Cómo se usa el polimorfismo en el caso? Nota: Para el desarrollo de la aplicación suponga que existen un banco con 2 sucursales, cada una de ellas con 2 y 3 clientes respectivamente. Cada cliente tiene una sola cuenta.
Clase abstracta En Java puedes definir que tengan un alto nivel de abstracción de objetos del mundo real. Está compuesta de uno o más métodos abstractos, los que son declarados pero no implementados: No tienen cuerpo, pues las implementaciones se encuentran en (son responsabilidad de) las subclases. Puede tener también métodos no abstractos, cuyas implementaciones serian comunes para sus subclases. Bastara que una clase contenga un método abstracto, para que tenga que ser declarada también abstracta. Generalmente se requiere por conveniencia en el diseño de aplicaciones. Los métodos abstractos no pueden especificarse estáticos. Los métodos privados no pueden especificarse como abstractos.
Clases abstractas en Java Tanto la clase como los métodos abstractos, deben anteponerse el modificador abstract en su declaración. Figura es una clase abstracta (nombre en cursiva en UML), por que no tiene sentido calcular su área, pero si la de un Cuadrado o un Círculo. Si una subclase de figura no redefine area() deberá declararse también como clase abstracta.
Interface Una interface es usada para establecer un protocolo entre clases: cualquier código que usa una interface sabe qué métodos pueden ser invocados sobre dicha interface particular. Una interface permite interactuar a objetos no relacionados por la cadena de herencia. Una interface puede extender múltiples interfaces. Por lo tanto, se tiene herencia múltiple de interfaces. No existe una interface de la cuál todas las interfaces son extensiones (no hay un análogo a la clase Object). Una clase que implementa una interface hereda las constantes y debe implementar cada uno de los métodos declarados en la interface. Una clase puede implementar más de una interface y de esta manera provee un mecanismo similar a la herencia múltiple. Una interface hereda todas las constantes y métodos de sus SuperInterfaces .
Interfaces en Java En Java las interfaces se declaran con la palabra reservada interface , de manera similar a como se declaran las clases abstractas. En la declaración de una interface, lo único que puede aparecer son declaraciones de métodos (su nombre y asignatura sin su implementación) y definiciones de constantes simbólicas. Una interface no encapsula datos, sólo define cuales son los métodos que han de implementar los objetos de aquellas clases que implementan la interface. En Java para indicar que clase implementa una interface se utiliza la palabra reservada implements . La clase entonces debe implementar todos los métodos definidos por la interface o declararse, a su vez, como una clase abstracta (lo que no suele ser especialmente útil). Herencia múltiple en Java Técnicamente en Java no existe la herencia multiple, un objeto sólo puede tener un solo Padre, sin embargo puede implementar muchas interfaces. Cuando un objeto implementa una interface (especificación) adquiere las capacidades que especifica la interface, esto es, hereda todo su comportamiento.
Clase Interna La clase interna se define dentro de una clase, como si fuera un atributo o un método adicional de la clase externa. Por esta razón la clase interna puede acceder a las variables de instancia (atributos) y métodos declarados en la clase externa que la contiene. La relación de una clase interna respecto a la clase externa que la contiene es: La clase interna “pertenece a” la clase externa. Las clases internas permiten agrupar clases que tienen una pertenencia lógica y controlar la visibilidad de las clases definiéndolas adentro de otras. Es posible crear clases que ayudan a resolver problemas complejos, pero que no se quiere que estén disponibles públicamente. Un objeto de una clase interna tiene acceso ilimitado a la implementación del objeto que de la clase externa , inclusive aquellos declarados private . Las clases internas pueden declararse private o protected, a diferencia de las no-internas que solo pueden ser public o tener accesibilidad de default o package. Una especial extensión “new” a sido agregado al lenguaje para soportar este enlace, por ejemplo: Externa miObjetoExterno = new Externa( ) ; Externa.Interna miObjetoInterno = miObjetoExterno.new Interna( ) ;
Clase Interna. Miembro La clase Interna miembro tiene acceso a la implementación de la clase Externa (variables de instancia, de clase y métodos) como si fuesen propios. Un objeto de una clase Interna miembro tiene una referencia implícita al objeto de la clase que lo instanció (clase externa). A través de esta referencia tiene acceso al estado total del objeto, inclusive a los datos privados. Por lo tanto, las clases internas tienen más privilegios de acceso que las clases no-internas. El compilador es el que agrega ésta referencia implícita en el constructor de la clase interna.
Clase Interna. Estática (anidada) Cuando se declara una clase interna static, a diferencia de las clases internas estándares, la clase interna no tiene la referencia al objeto de la clase externa que lo creó. No se necesita el objeto de la clase externa para crear un objeto de una clase anidada. No se puede acceder al objeto de la clase externa desde una clase anidada. Las clases internas estándares no pueden tener atributos static, métodos static, ni clases anidadas.
Clase Interna. Local Las clases internas locales, se declaran sin especificador de acceso, ya que su alcance está restringido al bloque de código donde se definió, no forman parte de la clase externa. La clase Interna local, a pesar de ser local a el método donde se declaró, se compila con el resto de la clase (es un .class separado). La clase Interna local no está disponible afuera del método, está fuera de alcance (no se pueden crear objeto del tipo de clase Interna local afuera del método donde se declaró), es un nombre inválido.
Clase Interna. Anónima Las clases internas anónimas, son clases internas locales, pero que no tienen nombre, se crean extendiendo una clase o implementando una interface. Son utilizadas mayormente en clases que implementen la especificación de una interface o una clase abstracta para la construcción de adaptadores de éstas. Es una manera en base a interfaces, sin utilizar la palabra reservada implements. Se caracteriza por: No puede declara un constructor debido a que la clase anónima no tiene un nombre asignado. El cuerpo de la clase interna debe ser pequeño. Considerar que toda clase interna anónima que implemente una interface, extiende de la clase Object por defecto. Las clases internas locales (las anónimas incluídas) tienen acceso a las variables locales del bloque de código donde están declaradas.
Práctica 6: Implementación de aplicaciones extensibles Objetivo Hacer uso de abstracciones para definir servicios genéricos que pueden ser implementados de una manera distinta en algún caso concreto. Ejercicio Se desea implementar una aplicación ( Sort ) que sea capaz de ordenar cualquier tipo objeto en el mundo. Considerar la siguiente especificación: a) Implemente el algoritmo de ordenamiento para la clase Test dentro del método ordenar . b) Cree una clase Alumno (código, apellidos, nombres y carrera) que implemente la interfaz Comparable . c) Cree una clase Test que cree 5 alumnos y luego sean ordenados por código por la clase Sort d) Cree una clase Celular (marca) que implemente la interfaz Comparable , luego añade el código necesario en el main de la clase Test para probar el ordenamiento de Celulares por marca.
Enumerated Types (enums) Un enumerated type es un tipo de dato que contiene un conjunto de valores constantes. JDK 5 incluye soporte lingüístico para los tipos de datos enumerados. Las características avanzadas de la OO incluyen la capacidad de agregar los métodos y campos a los enums. Esto es más ordenado, más seguro y más potente que las alternativas existentes. ¿Cuando debería usar Enums? Tipos de enumerados naturales: días de la semana, fases de la luna, estaciones, meses del año. Otros conjuntos donde sepamos todos los valores posibles: opciones de un menú, etc. Como reemplazo de los flags (EnumSet)
Práctica 7: Definir constantes usando Enum Objetivo Entender el uso del tipo Enum para la definición de constantes Ejercicio Tomando como referencia la práctica anterior, modificar la definición de la interface Comparable que defina el retorno de el método CompareTo del tipo de clase enumerada Comparacion. Tomar como referencia la siguiente especificación: