Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Cuarta Unidad:
Programación
Orientada a Objetos
(POO)
Introducción
La Programación Orientada a Objetos (POO) es un enfoque conceptual específico para diseñar
programas, utilizando un lenguaje de programación orientado a objetos, en nuestro caso C++ o Java.
Las propiedades más importantes de la POO son:
• Abstracción.
• Encapsulamiento y ocultación de datos.
• Polimorfismo.
• Herencia.
• Reusabilidad o reutilización de código.
Este paradigma de programación viene a superar las limitaciones que soporta la programación
tradicional o "procedimental".
Los elementos fundamentales de la POO son las clases y objetos. En esencia, la POO se concentra en
el objeto tal como lo percibe el usuario, pensando en los datos que se necesitan para describir el
objeto y las operaciones que describirán la iteración del usuario con los datos. Después se desarrolla
una descripción de la interfaz externa y se decide cómo implementar la interfaz y el almacenamiento
de datos. Por último, se ponen juntos en un programa que utilice su nuevo dueño.
Modelado de objetos del mundo real
Una limitación de la programación estructurada reside en el hecho de que la separación de los
datos y las funciones que manipulan esos datos proporcionan un modelo muy pobre de las cosas
y objetos del mundo real. En el mundo real se trata con objetos tales como personas, casas o
motocicletas, y tienen a su vez incorporados atributos (datos) y comportamiento (funciones).
Los objetos —complejos o no complejos— del mundo real tienen atributos y comportamiento.
Los atributos o características son las propiedades de los objetos; por ejemplo, para las
personas, la estatura, el color del cabello y de los ojos, la edad, etc.; para un automóvil (coche o
carro), la marca, la potencia, el número de puertas, el precio, etc. Los atributos del mundo real
son equivalentes a los datos de un programa y tienen un valor determinado, 200 metros
cuadrados, 20.000 dólares, cinco puertas, etc.
El comportamiento es la acción que realizan los objetos del mundo real en respuesta a un
determinado estímulo. Por ejemplo, si se acelera un carro, aumenta su velocidad; si se frena un
carro se ralentiza o para. El comportamiento es similar a una función; la llamada a una función
para realizar una tarea determinada, por ejemplo dibujar un rectángulo o visualizar la nómina de
los empleados de una empresa.
Programación Orientada a Objetos
Al contrario que el enfoque procedimental que se basa en la interrogante ¿qué hace este
programa?, el enfoque orientado a objetos responde a otro interrogante ¿qué objetos del
mundo real puede modelar?
La POO (Programación Orientada a Objetos) se basa en el hecho de que se debe dividir el
programa, no en tareas, sino en modelos de objetos físicos o simulados. Aunque esta idea
parece abstracta a primera vista, se vuelve más clara cuando se consideran objetos físicos
en términos de sus clases, componentes, propiedades y comportamiento, y sus objetos
instanciados o creados de las clases.
Si se escribe un programa de computadora en un lenguaje orientado a objetos, se está
creando, en su computadora, un modelo de alguna parte del mundo. Las partes que el
modelo construye son los objetos que aparecen en el dominio del problema. Estos
objetos deben ser representados en el modelo que se está creando en la computadora.
Los objetos se pueden agrupar en categorías, y una clase describe —de un modo
abstracto— todos los objetos de un tipo o categoría determinada.
Programación Orientada a Objetos
La idea fundamental de la orientación a objetos y de los lenguajes que implementan este
paradigma de programación es combinar (encapsular) en una única unidad tanto los
datos como las funciones que operan (manipulan) sobre los datos. Esta característica
permite modelar los objetos del mundo real de un modo mucho más eficiente que con
funciones y datos. Esta unidad de programación se denomina objeto.
En un sistema orientado a objetos, un programa se organiza en un conjunto finito de
objetos que contienen datos y operaciones que se comunican entre sí mediante
mensajes.
.
Tipos de Datos Abstractos
(Clases)
Tipos de Datos Abstractos (Clases)
Un progreso importante en la historia de los lenguajes de programación se produjo cuando se
comenzó a combinar juntos diferentes elementos de datos y, por consiguiente, encapsular o
empaquetar diferentes propiedades en un tipo de dato. Estos tipos fueron las estructuras o registros
que permiten a una variable contener datos que pertenecen a las circunstancias representadas por
ellas.
Las estructuras representan un modo de abstracción con los programas, concretamente la
combinación (o composición) de partes diferentes o elementos (miembros). Así, por ejemplo, una
estructura coche constará de miembros tales como marca, motor, número de matrícula, año de
fabricación, etc.
Sin embargo, aunque en las estructuras y registros se pueden almacenar las propiedades individuales
de los objetos en los miembros, en la práctica cómo están organizados, no pueden representar qué se
puede hacer con ellos (moverse, acelerar, frenar, etc. en el caso de un coche/carro). Se necesita que
las operaciones que forman la interfaz de un objeto se incorporen también al objeto.
El tipo abstracto de datos (TAD) describe, no sólo los atributos de un objeto sino también su
comportamiento (operaciones o funciones) y, en consecuencia, se puede incluir una descripción de
los estados que puede tener el objeto.
Instancias
Una clase describe un objeto, en la práctica múltiples objetos. En conceptos de
programación, una clase es, realmente, un tipo de dato, y se pueden crear, en
consecuencia, variables de ese tipo. En programación orientada a objetos, a estas
variables, se las denomina instancias (“instances”), y también por sus sinónimos
ejemplares, casos, etcétera.
Las instancias son la implementación de los objetos descritos en una clase. Estas
instancias constan de los datos o atributos descritos en la clase y se pueden
manipular con las operaciones definidas en la propia clase.
En un lenguaje de programación OO, objeto e instancia son términos sinónimos.
Así, cuando se declara una variable de tipo Auto, se crea un objeto Auto (una
instancia de la clase Auto).
Clases
Una clase es una plantilla para la creación de objetos de datos según un modelo predefinido. Las
clases se utilizan para representar entidades o conceptos, como los sustantivos en el lenguaje. Cada
clase es un modelo que define un conjunto de variables -el estado, y métodos apropiados para operar
con dichos datos -el comportamiento. Cada objeto creado a partir de la clase se denomina instancia
de la clase. Permiten abstraer los datos y sus operaciones asociadas al modo de una caja negra.
• atributos: almacenan el estado de la clase por medio de variables, estructuras de datos e incluso
otras clases.
• ciertos lenguajes permiten un tercer tipo de miembro: las «propiedades», a medio camino entre
los campos y los métodos.
Utilizando un símil con el lenguaje, si las clases representan sustantivos, los campos de datos pueden
ser sustantivos o adjetivos, y los métodos son los verbos.
Método
Algoritmo asociado a un objeto (o a una clase de objetos), cuya ejecución se
desencadena tras la recepción de un "mensaje". Desde el punto de vista del
comportamiento, es lo que el objeto puede hacer. Un método puede producir un
cambio en las propiedades del objeto, o la generación de un "evento" con un nuevo
mensaje para otro objeto del sistema.
La diferencia entre un procedimiento (generalmente llamado función si devuelve
un valor) y un método es que este último, al estar asociado con un objeto o clase en
particular, puede acceder y modificar los datos privados del objeto correspondiente
de forma tal que sea consistente con el comportamiento deseado para el mismo.
Así, es recomendable entender a un método no como una secuencia de
instrucciones sino como la forma en que el objeto es útil (el método para hacer su
trabajo). Por lo tanto, podemos considerar al método como el pedido a un objeto
para que realice una tarea determinada o como la vía para enviar un mensaje al
objeto y que éste reaccione acorde a dicho mensaje
Atributos y Propiedades
Atributos
Los Atributos se utilizan para contener datos que reflejan el estado de la clase. Los
datos pueden estar almacenados en variables, o estructuras más complejas, como
arreglos e incluso otras clases.
Habitualmente, las variables miembro son privadas al objeto (siguiendo las
directrices de diseño del Principio de ocultación) y su acceso se realiza mediante
propiedades o métodos que realizan comprobaciones adicionales.
Propiedades
Las propiedades son los atributos de la computadora. Debido a que suele ser común
que las variables miembro sean privadas para controlar el acceso y mantener la
coherencia, surge la necesidad de permitir consultar o modificar su valor mediante
pares de métodos: GetVariable y SetVariable.
Objetos
Un objeto es una unidad dentro de un programa de computadores que consta de un
estado y de un comportamiento, que a su vez constan respectivamente de datos
almacenados y de tareas realizables durante el tiempo de ejecución. Un objeto
puede ser creado instanciando una clase.
Estos objetos interactúan unos con otros, en contraposición a la visión tradicional
en la cual un programa es una colección de subrutinas (funciones o
procedimientos), o simplemente una lista de instrucciones para el computador.
Cada objeto es capaz de recibir mensajes, procesar datos y enviar mensajes a otros
objetos de manera similar a un servicio.
Mensaje
Una comunicación dirigida a un objeto, que le ordena que ejecute uno de sus
métodos con ciertos parámetros asociados al evento que lo generó.
El paso de mensajes es una técnica que se usa para, desde un proceso, invocar de
forma abstracta un comportamiento concreto por parte de otro actor (Por ejemplo,
ejecutar una función o un programa). El emisor envía un mensaje solicitando una
acción abstracta al destinatario, y es el destinatario el que, al recibir el mensaje,
decidirá la acción que debe ejecutar para cumplir la petición.
Evento
Es un suceso en el sistema (tal como una interacción del usuario con la máquina, o
un mensaje enviado por un objeto). El sistema maneja el evento enviando el
mensaje adecuado al objeto pertinente. También se puede definir como evento la
reacción que puede desencadenar un objeto; es decir, la acción que genera.
Ejemplo
Nuestro primer ejemplo consiste en dos clases: Tiempo1 y PruebaTiempo1. La clase
Tiempo1 representa la hora del día. La clase PruebaTiempo1 es una clase de
aplicación en la que el método main crea un objeto de la clase Tiempo1 e invoca a
sus métodos. Estas clases se deben declarar en filas separadas ya que ambas son de
tipo public.
La clase Tiempo1 contiene tres variables de instancia private de tipo int (líneas 6 a
8): hora, minuto y segundo, que representan la hora en formato de tiempo universal
(formato de reloj de 24 horas, en el cual las horas se encuentran en el rango de 0 a
23). La clase Tiempo1 contiene los métodos public establecerTiempo (líneas 12 a
17), aStringUniversal (líneas 20 a 23) y toString (líneas 26 a 31). A estos métodos
también se les llama servicios public o la interfaz public que proporciona la clase a
sus clientes.
Ejemplo
Ejemplo
En este ejemplo, la clase Tiempo1 no declara un constructor, por lo que tiene un constructor predeterminado que
le suministra el compilador. Cada variable de instancia recibe en forma implícita el valor predeterminado 0 para
un int. Observe que las variables de instancia también pueden inicializarse cuando se declaran en el cuerpo de la
clase, usando la misma sintaxis de inicialización que la de una variable local.
En un sistema orientado a objetos los programas se organizan en conjuntos finitos que contienen
atributos (datos) y operaciones (funciones) y que se comunican entre sí mediante mensajes. Los pasos
típicos en el modelado de un sistema orientado a objetos son:
1. Identificar los objetos que forman parte del modelo.
2. Agrupar en clases todos aquellos objetos que tengan características y comportamientos comunes.
3. Identificar los atributos y las operaciones de cada clase.
4. Identificar las relaciones existentes entre las clases.
Propiedades POO
Composición
Una clase puede tener referencias a objetos de otras clases como miembros. A dicha capacidad se le
conoce como composición y algunas veces como relación “tiene un”. Por ejemplo, un objeto de la
clase RelojAlarma necesita saber la hora actual y la hora en la que se supone sonará su alarma, por lo
que es razonable incluir dos referencias a objetos Tiempo como miembros del objeto RelojAlarma.
Nuestro ejemplo de composición contiene tres clases: Fecha, Empleado y PruebaEmpleado. La clase
Fecha declara las variables de instancia mes, dia y anio (líneas 6 a 8) para representar una fecha. El
constructor recibe tres parámetros int. La línea 14 invoca el método utilitario comprobarMes (líneas
23 a 33) para validar el mes; un valor fuera de rango se establece en 1 para mantener un estado
consistente. La línea 15 asume que el valor de anio es correcto y no lo valida. La línea 16 invoca al
método utilitario comprobarDia (líneas 36 a 52) para validar el valor de dia con base en el mes y
anio actuales. Las líneas 42 y 43 determinan si el día es correcto, con base en el número de días en el
mes específico. Si el día no es correcto, las líneas 46 y 47 determinan si el mes es Febrero, el día 29 y
el anio un año bisiesto. Si las líneas 42 a 48 no devuelven un valor correcto para dia, la línea 51
devuelve 1 para mantener la Fecha en un estado consistente. Observe que las líneas 18 y 19 en el
constructor muestran en pantalla la referencia this como un objeto String. Como this es una
referencia al objeto Fecha actual, se hace una llamada implícita al método toString (líneas 55 a 58)
para obtener la representación String del objeto.
Composición
Composición
La clase PruebaEmpleado crea dos objetos Fecha (líneas 8 y 9) para representar la fecha
de nacimiento y de contratación de un Empleado, respectivamente. La línea 10 crea un
Empleado e inicializa sus variables de instancia, pasando al constructor dos objetos
String (que representan el nombre y el apellido del Empleado) y dos objetos Fecha (que
representan la fecha de nacimiento y de contratación). La línea 12 invoca en forma
implícita el método toString de Empleado para mostrar en pantalla los valores de sus
variables de instancia y demostrar que el objeto se inicializó en forma apropiada.
Fecha Empleado
-int mes -String primerNombre
-int dia -String apellidoPaterno
-int anio -Fecha fechaNacimiento
-Fecha(int elMes, int elDia, int elAnio) -Fecha fechaContratacion
-int comprobarMes(int mesPrueba) -Empleado(String nombre, String
-int comprobarDia(int diaPrueba) apellido, Fecha fechaDeNacimiento,
-String toString() Fecha fechaDeContratacion)
-String toString()
Abstracción
Denota las características esenciales de un objeto, donde se capturan sus
comportamientos. Cada objeto en el sistema sirve como modelo de un "agente"
abstracto que puede realizar trabajo, informar y cambiar su estado, y "comunicarse"
con otros objetos en el sistema sin revelar cómo se implementan estas
características. Los procesos, las funciones o los métodos pueden también ser
abstraídos, y, cuando lo están, una variedad de técnicas son requeridas para
ampliar una abstracción. El proceso de abstracción permite seleccionar las
características relevantes dentro de un conjunto e identificar comportamientos
comunes para definir nuevos tipos de entidades en el mundo real. La abstracción es
clave en el proceso de análisis y diseño orientado a objetos, ya que mediante ella
podemos llegar a armar un conjunto de clases que permitan modelar la realidad o el
problema que se quiere atacar.
Abstracción
Por ejemplo las pilas pueden implementarse mediante arreglos y con otras
estructuras de datos, como las listas enlazadas. El cliente de una clase pila no
necesita preocuparse por la implementación de la pila. El cliente sólo sabe que
cuando se colocan elementos de datos en la pila, éstos se recuperarán en el orden
del último en entrar, primero en salir. El cliente se preocupa acerca de qué
funcionalidad ofrece una pila, pero no acerca de cómo se implementa esa
funcionalidad. A este concepto se le conoce como abstracción de datos. Aunque
los programadores pudieran conocer los detalles de la implementación de una clase,
no deben escribir código que dependa de esos detalles. Esto permite que una clase
en particular (como una que implemente a una pila y sus operaciones: meter y
sacar) se reemplace con otra versión, sin afectar al resto del sistema. Mientras que
los servicios public de la clase no cambien (es decir, que cada método original tenga
aún el mismo nombre, tipo de valor de retorno y lista de parámetros en la
declaración de la nueva clase), el resto del sistema no se ve afectado.
Encapsulamiento
Significa reunir todos los elementos que pueden considerarse pertenecientes a una
misma entidad, al mismo nivel de abstracción. Esto permite aumentar la cohesión
de los componentes del sistema.
Cada objeto está aislado del exterior. El aislamiento protege a los datos asociados
de un objeto contra su modificación por quien no tenga derecho a acceder a ellos,
eliminando efectos secundarios e interacciones.
Encapsulamiento
Encapsulamiento
Herencia
La herencia, que es una forma de reutilización de software en la que se crea una nueva
clase absorbiendo los miembros de una clase existente, y se mejoran con nuevas
capacidades, o con modificaciones en las capacidades ya existentes. Con la herencia, los
programadores ahorran tiempo durante el desarrollo, al reutilizar software probado y
depurado de alta calidad. Esto también aumenta la probabilidad de que un sistema se
implemente con efectividad.
Al crear una clase, en vez de declarar miembros completamente nuevos, el programador
puede designar que la nueva clase herede los miembros de una clase existente. Esta clase
existente se conoce como superclase, y la nueva clase se conoce como subclase. Cada
subclase puede convertirse en la superclase de futuras subclases.
Una subclase generalmente agrega sus propios campos y métodos. Por lo tanto, una
subclase es más específica que su superclase y representa a un grupo más especializado de
objetos. Generalmente, la subclase exhibe los comportamientos de su superclase junto con
comportamientos adicionales específicos de esta subclase. Es por ello que a la herencia se
le conoce algunas veces como especialización.
Herencia
La superclase directa es la superclase a partir de la cual la subclase hereda en forma
explícita. Una superclase indirecta es cualquier clase arriba de la superclase directa
en la jerarquía de clases, la cual define las relaciones de herencia entre las clases. En
Java, la jerarquía de clases empieza con la clase Object (en el paquete java.lang), a
partir de la cual se extienden (o “heredan”) todas las clases en Java, ya sea en forma
directa o indirecta.
Es necesario hacer una diferencia entre la relación “es un” y la relación “tiene un”.
La relación “es un” representa a la herencia. En este tipo de relación, un objeto de
una subclase puede tratarse también como un objeto de su superclase. Por ejemplo,
un automóvil es un vehículo. En contraste, la relación “tiene un” identifica a la
composición. En este tipo de relación, un objeto contiene referencias a objetos
como miembros. Por ejemplo, un automóvil tiene un volante de dirección (y un
objeto automóvil tiene una referencia a un objeto volante de dirección).
Herencia
Como todo objeto de una subclase “es un” objeto de su superclase, y como una
superclase puede tener muchas subclases, el conjunto de objetos representados por
una superclase generalmente es más grande que el conjunto de objetos
representado por cualquiera de sus subclases. Por ejemplo, la superclase Vehiculo
representa a todos los vehículos, incluyendo automóviles, camiones, barcos,
bicicletas, etcétera. En contraste, la subclase Auto representa a un subconjunto más
pequeño y específico de los vehículos.
Las relaciones de herencia forman estructuras jerárquicas en forma de árbol. Una
superclase existe en una relación jerárquica con sus subclases. Cuando las clases
participan en relaciones de herencia, se “afilian” con otras clases. Una clase se
convierte ya sea en una superclase, proporcionando miembros a otras clases, o en
una subclase, heredando sus miembros de otras clases. En algunos casos, una clase
es tanto superclase como subclase.
Creación de Subclases (Herencia)
Se ha visto la creación de una clase Employee. Suponga ahora que desea crear una
clase Manager.
Creación de Subclases (Herencia)
Creación de Subclases (Herencia)
Creación de Subclases (Herencia)
Usaremos una jerarquía de herencia que contiene tipos de empleados en la
aplicación de nómina de una compañía, para hablar sobre la relación entre una
superclase y su subclase. En esta compañía, a los empleados por comisión (que se
representarán como objetos de una superclase) se les paga un porcentaje de sus
ventas, mientras que los empleados por comisión con salario base (que se
representarán como objetos de una subclase) reciben un salario base, más un
porcentaje de sus ventas.
Dividiremos nuestra discusión sobre la relación entre los empleados por comisión y
los empleados por comisión con salario base en cinco ejemplos. El primero declara
la clase EmpleadoPorComision, la cual hereda directamente de la clase Object y
declara como variables de instancia private el primer nombre, el apellido paterno, el
número de seguro social, la tarifa de comisión y el monto de ventas en bruto (es
decir, total).
Creación de Subclases (Herencia)
El segundo ejemplo declara la clase EmpleadoBaseMasComision, la cual también
hereda directamente de la clase Object y declara como variables de instancia private
el primer nombre, el apellido paterno, el número de seguro social, la tarifa de
comisión, el monto de ventas en bruto y el salario base. Para crear esta última clase,
escribiremos cada línea de código que ésta requiera; pronto veremos que es mucho
más eficiente crear esta clase haciendo que herede de la clase
EmpleadoPorComision.
El tercer ejemplo declara una clase EmpleadoBaseMasComision2 separada, la cual
extiende a la clase EmpleadoPorComision (es decir, un
EmpleadoBasePorComision2 es un EmpleadoPorComision que también tiene un
salario base) y trata de acceder a los miembros private de la clase
EmpleadoPorComision; esto produce errores de compilación, ya que la subclase no
puede acceder a las variables de instancia private de la superclase.
Creación de Subclases (Herencia)
El cuarto ejemplo muestra que si las variables de instancia de EmpleadoPorComision se
declaran como protected, una clase EmpleadoBaseMasComision3 que extiende a la
clase EmpleadoPorComision2 puede acceder a los datos de manera directa. Para este
fin, declaramos la clase EmpleadoPorComision2 con variables de instancia protected.
Todas las clases EmpleadoBaseMasComision contienen una funcionalidad idéntica,
pero le mostraremos que la clase EmpleadoBaseMasComision3 es más fácil de crear y
de manipular.
Una vez que hablemos sobre la conveniencia de utilizar variables de instancia protected,
crearemos el quinto ejemplo, el cual establece las variables de instancia de
EmpleadoPorComision de vuelta a private en la clase EmpleadoPorComision3, para
hacer cumplir la buena ingeniería de software. Después le mostraremos cómo una clase
EmpleadoBaseMasComision4 separada, que extiende a la clase
EmpleadoPorComision3, puede utilizar los métodos public de EmpleadoPorComision3
para manipular las variables de instancia private de EmpleadoPorComision3.
Creación de Subclases (Herencia)
Creación de Subclases (Herencia)
Creación y uso de una clase EmpleadoPorComision
Creación de Subclases (Herencia)
Creación y uso de una clase EmpleadoPorComision
Creación de Subclases (Herencia)
Creación y uso de una clase EmpleadoPorComision
Creación de Subclases (Herencia)
Creación de una clase EmpleadoBaseMasComision sin usar la herencia
Ahora reexaminaremos nuestra jerarquía una vez más, pero ahora utilizaremos las mejores
prácticas de ingeniería de software. La clase EmpleadoPorComision3 declara las variables de
instancia primerNombre, apellidoPaterno, numeroSeguroSocial, ventasBrutas y
tarifaComision como private (líneas 6 a 10) y proporciona los métodos public
establecerPrimerNombre, obtenerPrimerNombre, establecerApellidoPaterno,
obtenerApellidoPaterno, establecerNumeroSeguroSocial, obtenerNumeroSeguroSocial,
establecerVentasBrutas, obtenerVentasBrutas, establecerTarifaComision,
obtenerTarifaComision, ingresos y toString para manipular estos valores. Observe que los
métodos ingresos (líneas 85 a 88) y toString (líneas 91 a 98) utilizan los métodos obtener de
la clase para obtener los valores de sus variables de instancia. Si decidimos modificar los
nombres de las variables de instancia, no habrá que modificar las declaraciones de ingresos y
de toString; sólo habrá que modificar los cuerpos de los métodos obtener y establecer que
manipulan directamente estas variables de instancia. Observe que estos cambios ocurren sólo
dentro de la superclase; no se necesitan cambios en la subclase. La localización de los efectos
de los cambios como éste es una buena práctica de ingeniería de software. La subclase
EmpleadoBaseMasComision4 hereda los miembros no private de EmpleadoPorComision3 y
puede acceder a los miembros private de su superclase, a través de esos métodos.
Creación de Subclases (Herencia)
La jerarquía de herencia EmpleadoPorComision-EmpleadoBaseMasComision
mediante el uso de variables de instancia private
Creación de Subclases (Herencia)
La jerarquía de herencia EmpleadoPorComision-EmpleadoBaseMasComision
mediante el uso de variables de instancia private
Creación de Subclases (Herencia)
La jerarquía de herencia EmpleadoPorComision-EmpleadoBaseMasComision
mediante el uso de variables de instancia private
Creación de Subclases (Herencia)
La jerarquía de herencia EmpleadoPorComision-EmpleadoBaseMasComision
mediante el uso de variables de instancia private
Los constructores no se heredan
Cada una de las subclases hereda los métodos y los campos no privados de su
principal (superclase). Sin embargo, la subclase no hereda el constructor de su
principal.
Las declaraciones de constructores no son miembros. Nunca se heredan y, por
tanto, no están sujetas a ocultación o sustitución.
Uso de super
Para crear una instancia de una subclase, normalmente resulta mas fácil llamar al
constructor de la clase principal.
• En su constructor, Manager llama al constructor de Employee.
• Es equivalente a:
• La clase raíz contiene varios métodos que no son finales, pero hay tres que son
importantes para pensar en la sustitución:
• toString, equals y hashCode
Método Object toString
Al método toString se le llama siempre que se transfiera una instancia de la clase a
un método que tome un objeto String, como println:
• Este enfoque para obtener detalles sobre la clase es mejor que crear su propio
método getDetails.
Método Object equals
El método Object equals solo compara referencia de objetos.
• Si hay dos objetos x e y en cualquier clase, x es igual a y si y solo si x e y hacen
referencia al mismo objeto.
• Se suelen usar en lugar de los constructores para realizar tareas relacionadas con
la inicialización de objetos.
• No pueden acceder a miembros no estáticos de la misma clase.
• Se pueden ocultar en subclases, pero no se pueden sustituir.
• Sin llamada al método virtual.
Implantación de métodos estáticos
Llamada a métodos estáticos
• Evitar el uso de una referencia de objeto para acceder a una variable estática.
Métodos finales
Un método se puede declarar como final. Los métodos finales no se pueden
sobrescribir.
Clases finales
Una clase se puede declarar como final. Las clases finales no se pueden ampliar.
Variables finales
El modificador final se puede aplicar a las variables. Las variables finales no pueden
cambiar sus valores una vez inicializadas. Las variables finales pueden ser:
• Campos de clase
• Los campos finales con expresiones de constantes de tiempo de compilación son
variables de constantes.
• Los campos estáticos se pueden combinar con los finales para crear una variable
siempre disponible y que nunca cambia.
Nota: las referencias finales siempre deben hacer referencia al mismo objeto, pero
el contenido de ese objeto se puede modificar.
Variables finales
Cuándo evitar las constantes
Las variables public, static y final pueden ser muy útiles, pero hay un patrón de uso
concreto que se debería evitar. Las constantes pueden proporcionar una falsa
sensación de validación de los datos introducidos o de comprobación del rango de
valores.
• Piense en un método que solo deba recibir uno de los tres valores posibles:
• Un Almacén posee Clientes y Cuentas (los rombos van en el objeto que posee las
referencias).
• Cuando se destruye el Objeto Almacén también son destruidos los objetos Cuenta
asociados, en cambio no son afectados los objetos Cliente asociados.
• La composición (por Valor) se destaca por un rombo relleno.
• La agregación (por Referencia) se destaca por un rombo transparente.
Asociación
La relación entre clases conocida como Asociación, permite asociar objetos que
colaboran entre si. Cabe destacar que no es una relación fuerte, es decir, el tiempo
de vida de un objeto no depende del otro.
Un cliente puede tener asociadas muchas Ordenes de Compra, en cambio una orden
de compra solo puede tener asociado un cliente.
Dependencia o Instanciación
Representa un tipo de relación muy particular, en la que una clase es instanciada
(su instanciación es dependiente de otro objeto/clase). Se denota por una flecha
punteada.
El uso más particular de este tipo de relación es para denotar la dependencia que
tiene una clase de otra, como por ejemplo una aplicación grafica que instancia una
ventana (la creación del Objeto Ventana esta condicionado a la instanciación
proveniente desde el objeto Aplicación):
Ejemplo
Se quiere desarrollar un sistema de información para la Universidad de Oriente según la
descripción siguiente.
• La Universidad se caracteriza mediante su nombre y la ciudad donde se sitúa.
• En la Universidad están vinculados dos tipos de Persona: Trabajadores, que
la Universidad emplea, y Estudiantes, que estudian en la Universidad.
• Cada Persona tiene una CI (Código de identificación) y un nombre.
• Los Trabajadores pertenecen a dos grupos: PDI (Personal docente) y PAS (Personal
administrativo).
• Cada Trabajador tiene asociada una fecha de inicio de su contrato.
• Cada miembro del PDI también tiene una categoría, mientras que cada miembro
del PAS tiene un puesto.
• Los miembros del PDI pueden o no ser Doctores. Las actividades que desarrolla el PDI son
investigar y enseñar, mientras que la actividad que desarrolla el PAS es administrar.
Ejemplo
• La Universidad se compone de un conjunto de Departamentos, cada uno de los cuales tiene
un nombre y un conjunto de Trabajadores adscrito.
• Un Trabajador no puede estar adscrito a más de un Departamento.
• Un PDI está adscrito obligatoriamente a un Departamento, mientras que un PAS, no.
• Cada Departamento está dirigido por un Doctor.
• Un Estudiante puede ser bien Estudiante de grado, de una determinada titulación, o bien
Estudiante de Doctorado, de un determinado programa de Doctorado.
• Un Estudiante de grado puede también colaborar con un Departamento como becario.
• Un Estudiante de Doctorado realiza una tesis dirigida por un Doctor.
• Puede suponer que un Estudiante no puede estudiar en más de una Universidad y que
un Trabajador no puede ser empleado por más de una Universidad.
• Una Persona puede ser a la vez Trabajador y Estudiante, Un Estudiante no puede ser a la
vez Estudiante de grado y Estudiante de Doctorado, los únicos tipos de Trabajador que
existen son PDI y PAS, un Trabajador no puede ser a la vez PDI y PAS.
Ejemplo
Ejercicio