El Ejemplo Racional muestra una posible implementación de ADT racional definido en la entrada Tipos de Datos Abstractos (ADT).
Las líneas 7 y 8 definen los atributos de un número racional (p / q). Los detalles relacionados con los métodos de tipo set y get (líneas 25-41), ya han sido comentados en la sección Métodos y atributos de la entrada POO (mensajes y métodos) y no se repetirán aquí.
Por otro lado, los constructores definidos (líneas 10-23) requieren de una ampliación en su explicación, ya que difieren un poco de lo hasta ahora comentado para los constructores.
El constructor principal o base es el definido en las líneas 18-23. Observe que dicho constructor recibe dos argumentos, mismos que representan el numerador (n) y el denominador (d) del número racional que se desea inicializar. En la línea 19, el constructor realiza una verificación del denominador (cláusula de condición), de tal forma que si éste es cero, se crea (new) y lanza (throw) una excepción (consulte la sección de Excepciones de la entrada Ejemplos selectos de transición) para indicar el error a través de la clase ArithmeticException. Note también que el mismo comportamiento es considerado en las líneas 30 y 31 para el método estableceDenominador. Una posible salida del programa al presentarse la situación anteriormente planteada, se muestra en la siguiente figura:
Las líneas 7 y 8 definen los atributos de un número racional (p / q). Los detalles relacionados con los métodos de tipo set y get (líneas 25-41), ya han sido comentados en la sección Métodos y atributos de la entrada POO (mensajes y métodos) y no se repetirán aquí.
Por otro lado, los constructores definidos (líneas 10-23) requieren de una ampliación en su explicación, ya que difieren un poco de lo hasta ahora comentado para los constructores.
El constructor principal o base es el definido en las líneas 18-23. Observe que dicho constructor recibe dos argumentos, mismos que representan el numerador (n) y el denominador (d) del número racional que se desea inicializar. En la línea 19, el constructor realiza una verificación del denominador (cláusula de condición), de tal forma que si éste es cero, se crea (new) y lanza (throw) una excepción (consulte la sección de Excepciones de la entrada Ejemplos selectos de transición) para indicar el error a través de la clase ArithmeticException. Note también que el mismo comportamiento es considerado en las líneas 30 y 31 para el método estableceDenominador. Una posible salida del programa al presentarse la situación anteriormente planteada, se muestra en la siguiente figura:
Una salida de la excepción generada en el Ejemplo PruebaRacional al intentar crear un número racional cuyo denominador sea cero. |
Los constructores de las líneas 10-12 y 14-16 se
apoyan del constructor base de las líneas 18-23 para realizar la
inicialización del objeto a través del uso de la cláusula this. La cláusula this
es una referencia que tienen todos los objetos hacia sí mismos, por lo
que en el contexto de los constructores invoca al constructor sobre
cargado que corresponda con el tipo y número de argumentos que envía,
que para el caso de las líneas 11 y 15 corresponden con el constructor
base de las líneas 18-23.
La implementación de las operaciones de suma y producto aparecen en las líneas 43-50 y 52-59 respectivamente (la implementación de las operaciones resta y división se dejan como ejercicio para el lector). Observe que en las líneas 46 y 47 (55 y 56) se accede directamente a los atributos p y q a través del operador punto (.), es decir, sin hacer uso de los métodos de acceso set y get; ésto es así debido a que el objeto s (m) es de la misma clase que define al método suma (multiplica), por lo que el acceso es concedido sin ningún tipo de inconveniente (recuerde lo planteado en el Ejercicio 2 de la entrada Ejercicios selectos (POO) y analice la diferencia).
Por otro lado, note también que para el objeto (this) que recibe el mensaje suma (multiplica), los atributos p y q de las líneas 46 y 47 (55 y 56) son accedidos sin ningún tipo de operador ni mensaje, es decir, son accedidos por contexto, ya que el objeto que recibe el mensaje conoce cuáles son sus propios atributos y métodos por lo que dentro del método la expresión:
La implementación de las operaciones de suma y producto aparecen en las líneas 43-50 y 52-59 respectivamente (la implementación de las operaciones resta y división se dejan como ejercicio para el lector). Observe que en las líneas 46 y 47 (55 y 56) se accede directamente a los atributos p y q a través del operador punto (.), es decir, sin hacer uso de los métodos de acceso set y get; ésto es así debido a que el objeto s (m) es de la misma clase que define al método suma (multiplica), por lo que el acceso es concedido sin ningún tipo de inconveniente (recuerde lo planteado en el Ejercicio 2 de la entrada Ejercicios selectos (POO) y analice la diferencia).
Por otro lado, note también que para el objeto (this) que recibe el mensaje suma (multiplica), los atributos p y q de las líneas 46 y 47 (55 y 56) son accedidos sin ningún tipo de operador ni mensaje, es decir, son accedidos por contexto, ya que el objeto que recibe el mensaje conoce cuáles son sus propios atributos y métodos por lo que dentro del método la expresión:
p * r.obtenDenominador( )
es equivalente a la expresión:
this.p * r.obtenDenominador( )
Por último en lo que respecta a los método suma y multiplica, es importante resaltar que ambos métodos utilizan un objeto local al método (s y m
respectivamente) para almacenar el resultado que generan y poder
regresarlo como valor de retorno del método, por lo que es posible
deducir que si un método requiere de variables u objetos para realizar
su labor, éstos pueden declarase locales al método. En este sentido,
sería un error respecto al paradigma declarar dichas variables u objetos
como atributos de la clase, ya que no describen alguna propiedad o
característica inherente a los objetos que deriven de la clase, sino que
son sólo elementos necesarios para el almacenamiento del resultado y la
realización del cálculo correspondiente a la responsabilidad
(comportamiento) del método. Lo anterior se aplica aún cuando se
utilizara una sola variable para almacenar el resultado de cualquiera de
las cuatro operaciones aritméticas.
Finalmente el método toString (líneas 61-63) requiere una mención aparte, ya que este método sobre escribe (razón por la cual se preservó el nombre del método) y en consecuencia re define el comportamiento previamente establecido en el método la clase Object del API de Java. Dicho método tiene como responsabilidad el regresar una representación en cadena del objeto que recibe el mensaje.
La clase de prueba del Ejemplo Racional es la del Ejemplo PruebaRacional. Una posible salida corresponde a la mostrada en la siguiente figura:
Finalmente el método toString (líneas 61-63) requiere una mención aparte, ya que este método sobre escribe (razón por la cual se preservó el nombre del método) y en consecuencia re define el comportamiento previamente establecido en el método la clase Object del API de Java. Dicho método tiene como responsabilidad el regresar una representación en cadena del objeto que recibe el mensaje.
La clase de prueba del Ejemplo Racional es la del Ejemplo PruebaRacional. Una posible salida corresponde a la mostrada en la siguiente figura:
Por último, aunque el Ejemplo PruebaRacional se explica a sí mismo, se resaltarán los siguientes aspectos:
- Las líneas 8 y 9 crean los números racionales r1 y r2, donde r1 = 1 / 3 y r2 = 2 / 5.
- Las líneas 13 y 14 envían los mensajes suma y multiplica respectivamente al objeto r1. Note que el argumento de ambos métodos es r2 y que al valor de retorno de dichos métodos (un número racional), le es enviado de manera implícita el mensaje toString para obtener la representación en cadena de los resultados correspondientes. Esto último sucede también con las líneas 11 y 12 pero para los objetos r1 y r2 respectivamente.
No hay comentarios.:
Publicar un comentario