Вы находитесь на странице: 1из 14

Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

Gestión de referencias y otros elementos de Java


Abstract: Alcances del Principio de Ocultamiento: acceso a miembros públicos y privados de una clase. Diagramas de
clases en UML: relaciones de uso y convenciones gráficas de BlueJ (modelado rápido). Variables referencia
en Java: manejadores de objetos. Asignación de referencias y la constante null. Objetos des-referenciados:
el recolector automático de residuos de Java (garbage collector). Desarrollo de ejercicios y problemas con
POO.

1.) Profundización del Principio de Ocultamiento.

Vimos en la Ficha anterior que la POO busca identificar actores o entidades en el dominio de un
problema, que sean capaces de ejecutar ciertas acciones. Los lenguajes orientados a objetos usan
clases para describir la forma y el comportamiento general de estos actores (que se llaman
genéricamente objetos). Una clase contiene definiciones de atributos (o variables o también campos)
que indican la forma de cada objeto. Y una clase también contiene métodos (o procesos) que indican el
comportamiento que puede desplegar cada objeto de esa clase.

La propiedad de la POO que permite que una clase agrupe atributos y métodos se llama
encapsulamiento, debido a que mediante esa agrupación una clase se asemeja a una cápsula de
software que permitirá crear objetos provistos cada uno de todos los elementos de datos y procesos
que necesitarán para desenvolverse en un programa.

El encapsulamiento da lugar al ya citado Principio de Ocultamiento: sólo los métodos de una


clase deberían tener acceso directo a los atributos de esa clase, para impedir que un atributo sea
modificado en forma insegura, o no controlada por la propia clase. El Principio de Ocultamiento es la
causa por la cual en general los atributos se declaran como privados (private), y los métodos se
definen públicos (public). Los calificadores private y public (así como protected, que se verá más
adelante) tienen efecto a nivel de compilación: si un atributo de una clase es privado, y se intenta
acceder a él desde un método de otra clase, se producirá en error de compilación:

public class Cuenta


{
private int numero;

public void setNumero(int num)


{
numero = num;
}
}

public class Principal


{
public static void main ( String args[] )
{
Cuenta a = new Cuenta();
a.numero = 201; // error de compilación: numero es privado
a.setNumero(201); // ok...
}
}

En el ejemplo anterior, se crea un objeto de la clase Cuenta en el método main() que está en la
clase Principal. Por lo tanto, main() no tiene acceso libre al atributo numero del objeto a: la
instrucción a.numero = 201; no compilará. Note que si el atributo numero se hubiera declarado public
en la clase Cuenta, entonces no se produciría el error: un elemento público es accesible desde
cualquier método de cualquier clase.
Ing. Valerio Frittelli - 1
Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

Debe entenderse un detalle: el Principio de Ocultamiento es una convención y no una regla. En


general es buena idea hacer que los atributos sólo sean accesibles desde métodos de la misma clase,
pero eso no es obligatorio. Pueden darse situaciones en las que el programador decida que un atibuto
sea público, o que un método sea privado (si esto es así, ese método sólo puede ser invocado por otros
métodos de la misma clase y no desde métodos externos a la clase). Sin embargo, y hasta que se logre
experiencia y mayores conocimientos en el tema, mantendremos la idea de declarar privados a los
atributos y públicos a los métodos.

2.) Diagramas de clases.

Así como un diagrama de flujo es una herramienta gráfica muy útil cuando un programador
quiere concentrarse en la lógica de un algoritmo sin entrar en los detalles formales de un lenguaje de
programación, existen otros modelos gráficos que permiten concentrarse en las relaciones que existen
entre las diversas clases de un proyecto y permitir que el programador tenga una visión general amplia
del proyecto, sin entrar en la complejidad de la programación profunda de cada clase. Esos dieños
gráficos se construyen en base a reglas y simbologías propias de un lenguaje de modelado llamado
Lenguaje Unificado de Modelado (o UML por sus iniciales en inglés: Unified Modeling Language)
muy usado en el diseño de sistemas orientados a objetos.

Uno de los más conocidos de estos diagramas es el diagrama de clases. En un diagrama de


clases cada clase se representa con un rectángulo en cuyo ángulo superior izquierdo se escribe el
nombre de la clase. Si existe alguna relación entre dos clases, habrá alguna forma de línea que una a
esas clases. BlueJ construye un gráfico de clases simplificado a medida que el programador crea
nuevas clases, y automáticamente muestra las relaciones entre esas clases.

Decimos que el gráfico creado por Bluej es simplificado, pues en UML el rectángulo que
representa una clase contiene una lista de sus atributos y una lista de sus métodos más relevantes
(además del nombre de la clase). Y el conjunto de tipos de relaciones manejadas por UML en general,
es más amplio que el manejado por BlueJ. Podemos decir que BlueJ aplica un subconjunto de
elementos de UML para facilitar la tarea del programador (se dice que BlueJ aplica técnicas de
Modelado Rápido).

Por ejemplo, tomando la clase Cuenta y la clase Principal que hemos usado como modelo
hasta aquí, podemos notar que la clase Principal (a través de declaraciones hechas en el método
main()) usa un objeto de la clase Cuenta. Esto marca lo que se conoce en UML como una relación de
uso o relación de dependencia: si los objetos de una clase A usan objetos de la clase B, hay una
relación de uso entre A y B y se grafica con una línea de rayas discontinua terminada en punta de
flecha abierta, originada en la clase A y terminada en la clase B:

Ing. Valerio Frittelli - 2


Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

Por lo tanto, la relación entre Principal y Cuenta es del mismo tipo:

3.) Manejo de referencias. El Garbage Collector.

Vimos en la Ficha anterior que en Java un objeto se crea usando el operador new, el cual
reserva memoria para el objeto creado, invoca a un constructor de la clase para iniciar sus atributos, y
finalmente retorna la dirección de memoria del objeto creado. Esa dirección se almacena en una
variable que recibe el nombre genérico de variable referencia:

Cuenta a; // declara una variable referencia...


a = new Cuenta( ); // …crea un objeto y guarda su dirección en la variable referencia...

En el fragmento anterior, la primera linea declara una variable a de tipo Cuenta. Esa variable
no es un objeto de la clase Cuenta, sino que puede contener la dirección de un objeto de la clase
Cuenta. Hasta que ese objeto se cree, podemos asumir en general que la variable a contiene lo que se
conoce como la dirección nula (null):

a null

La segunda linea es la que usando new crea un objeto de la clase Cuenta, y lo inicializa
invocando al constructor sin parámetros de la clase. Si suponemos que el objeto quedó guardado en
memoria en la dirección 52C4, entonces new retornaría ese valor y lo asignaría en la referencia a,
quedando así la memoria:

a 52C4 la referencia contiene la dirección del objeto

52C4
0 numero
0 saldo un objeto de la clase Cuenta

‘C’ tipo
dirección de memoria del
objeto creado por new

Ing. Valerio Frittelli - 3


Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

Como se ve, una cosa es la referencia y otra cosa es el objeto creado con new. Sin embargo,
una vez que la referencia contiene la dirección del objeto, se usa esa referencia para manejar al objeto
(se dice que la referencia es un manejador del objeto). En un gráfico es común que en lugar de mostrar
el número que representa la dirección, se muestre simplemente una flecha indicando que la referencia
apunta al objeto (y esto quiere decir lo que ya dijimos: la referencia contiene la dirección del objeto).
El gráfico siguiente equivale conceptualmente al anterior:

0 numero
0 saldo
‘C’ tipo

Cuando decimos que una referencia que apunta a un objeto se usa como un manejador para ese
objeto, queremos decir que a partir de allí la referencia se usa como si ella fuera el objeto, y a través
de ella se invocan los métodos públicos del objeto (mediante el operador punto colocado entre la
referencia y el nombre del método):

a.setNumero(200);
a.setSaldo(3000);
a.setTipo(‘C’);

Notar que si una variable referencia vale null, la misma no puede usarse para acceder a los
miembros del objeto, simplemente porque el objeto no existe. El intento de hacerlo provocará una
excepción de puntero nulo (NullPointerException) al ejecutar el programa, y el programa se
interrumpirá:

Cuenta a = null;
a.setNumero( 2034 ); // lanza una NullPointerException y el programa se interrumpe

A partir de aquí, el programador debe tener cuidado de entender bien lo que hace cuando opera
con referencias: supongamos que dos referencias a y b apuntan a dos objetos diferentes, creados
ambos con new. El gráfico de memoria se vería así:

Cuenta a = new Cuenta();


Cuenta b = new Cuenta(10, 2000, ’I’);

b
a

0 numero 10 numero
0 saldo 2000 saldo
‘C’ tipo ‘I’ tipo

Ing. Valerio Frittelli - 4


Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

Si luego se hace una asignación como la siguiente:

a = b;

entonces ambas referencias pasarán a apuntar al mismo objeto (el que originalmente era apuntado por
b). Por lo tanto, si se invoca un método desde la referencia a, tal como a.setNumero(20) para cambiar
el contenido de algún atributo de a, se estará modificando también el objeto referido por b. La
asignación a=b; NO COPIA los contenidos del objeto apuntado por b hacia el objeto apuntado por a.
Lo que copia es la dirección de b en la variable a:

b
a

0 numero 10 numero
objeto des-referenciado 0 saldo 2000 saldo
‘C’ tipo ‘I’ tipo

El objeto apuntado originalmente por a queda des-referenciado. En Java eso no es


necesariamente un error (como lo sería en C++), pues en Java existe un sistema de recolección de
residuos de memoria que se encarga de chequear la memoria en busca de objetos "perdidos" en tiempo
de ejecución. Cuando un programa se ejecuta, en otro hilo de ejecución paralelo corre también un
proceso llamado garbage collector, que se encarga de los objetos des-referenciados.

Técnicamente, el garbage collector liberará la memoria ocupada por esos objetos cuando
determine que se está próximo a una situación de out of memory (una situación en la que la memoria
está a punto de agotarse). De otro modo, aún cuando existan objetos perdidos, el garbage collector
posiblemente no llegue a activarse. El programador puede confiar en que el garbage collector no
afectará el rendimiento de su aplicación, pero también debe saber que no podrá intervenir en el
esquema de trabajo del mismo. A los sumo, el programador puede requerir que el garbage collector
considere intervenir y revisar la memoria en un momento dado, invocando al método System.gc().
Pero incluso en este caso, si el garbage collector determina que no hay peligro de out of memory, no
liberará la memoria ocupada por objetos perdidos:

Cuenta a, b, c;

// creamos tres objetos...


a = new Cuenta();
b = new Cuenta(10, 2000, ‘C’);
c = new Cuenta(20);

// des-referenciamos los objetos manejados por a y b...


a = null;
b = null;

// pedimos intervención al garbage collector…


// ... los objetos des-referenciados podrían ser eliminados ahora de la memoria...
// ... pero eso lo decide el garbage collector!!!
System.gc( );

Ing. Valerio Frittelli - 5


Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

4.) Ejemplos de programas desarrollados con POO. (Referencia:


proyectos Areas y Terrenos)

Para finalizar, mostraremos el desarrollo de algunos ejercicios en base a la POO en Java.


Comenzaremos con un modelo simple, que ya se resolvió con técnicas tradicionales en una ficha
anterior. El enunciado era el siguiente:

i.) Se conocen dos números distintos. Calcular la superficie de un cuadrado, suponiendo como
lado del mismo al mayor de los números dados y la superficie de un círculo suponiendo como radio del
mismo al menor de los números dados.

La lógica de la solución no cambiará en nada: simplemente cambiará la estrategia general de


trabajo. Ahora, en lugar de identificar los procesos principales (que eran los subproblemas de buscar el
mayor y el menor; y de calcular las áreas) lo que buscamos es identificar los objetos que deberían
hacerse cargo del trabajo, e intentar describir en forma amplia las clases de esos objetos.

En un primer análisis, lo que hacemos es buscar sustantivos en el enunciado, como candidatos


a ser las clases del problema. Podemos ver rápidamente unos cuantos: cuadrado, círculo, lado, radio,
superficie... Sin embargo, también podemos ver que algunos sustantivos representan en realidad
atributos de las clases que realmente nos importan: lado y superficie son atributos de un cuadrado, y
radio y superficie son atributos de un círculo... En general, el programador deberá esforzarse por notar
la diferencia entre sustantivos que serán claramente clases en el modelo final, y sustantivos que serán
características o propiedades de esas clases (atributos...)

Proponemos el siguiente modelo simple, desarrollado con BlueJ. Contaremos con dos clases
Cuadrado y Circulo, cada una de las cuales calculará el área de esas figuras. La primera tendrá un
atributo lado y la segunda un atributo radio. La clase Principal contendrá el main(), y se encargará de
la responsabilidad de determinar cuál de los dos números cargados es el mayor y cual es el menor.
Observe que el método toString() de cada una de las clases Cuadrado y Circulo invoca al método
superficie() de cada clase, y retorna una cadena que contiene ese valor (por ese motivo, main() no
tiene necesidad de pedirle al objeto cuadrado y al objeto circulo que calculen la superficie: al mostrar
los datos de ambos, aparecerán las superficies)

El esquema propuesto podría basarse en otras clases adicionales: por ejemplo, se podría contar
con una clase Ordenador que se encargue de representar dos números y ordenarlos de menor a mayor
(el método ordenar() podría estar en esta clase en lugar de estar en la clase Principal). Por el momento
nuestra solución quedará como se propuso incialmente:

Ing. Valerio Frittelli - 6


Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

Y el programa completo quedaría así (se listan una por una todas las clases, salvo la clase
Consola):

// *******************Clase Cuadrado*************************
public class Cuadrado
{
private float lado;

public Cuadrado()
{
lado = 0;
}

public Cuadrado(float lad)


{
lado = lad;
}

public float getLado()


{
return lado;
}

public void setLado(float lad)


{
lado = lad;
}

public float superficie()


{
return lado * lado;
}

public String toString()


{
return "Cuadrado - Lado: " + lado + "\tArea: " + superficie();
}
}

// *******************Clase Circulo*************************
public class Circulo
{
private float radio;

public Circulo()
{
radio = 0;
}

public Circulo(float r)
{
radio = r;
}

public float getRadio()


{
return radio;
}
Ing. Valerio Frittelli - 7
Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

public void setRadio(float r)


{
radio = r;
}

public float superficie()


{
return 3.14f * radio * radio;
}

public String toString()


{
return "Circulo - Radio: " + radio + "\tArea: " + superficie();
}
}

// *******************Clase Principal*************************
public class Principal
{
private static float a, b, men, may;

public static void main (String args[])


{
System.out.print("Primer número: ");
a = (float)Consola.readDouble();
System.out.print("Segundo número: ");
b = (float)Consola.readDouble();

ordenar();
Cuadrado cuad = new Cuadrado(may);
Circulo circ = new Circulo (men);

System.out.println(cuad.toString());
System.out.print(circ.toString());
}

public static void ordenar()


{
if ( a < b )
{
may = a;
men = b;
}
else
{
may = b;
men = a;
}
}
}

Ahora bien: ¿cuál es la ventaja de semejante cambio? En este modelo de solución hemos
tenido que programar considerablemente más líneas de código que en las soluciones originales de
Ing. Valerio Frittelli - 8
Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

programación estructurada que dimos en la ficha en que apareció el problema por primera vez... y eso
sin considerar otras posibles clases que podrían haberse usado (como se sugirió con la clase
Ordenador...) El programa hace básicamente lo mismo que antes, pero ahora aparecen (sólo...) cuatro
clases en lugar de dos, y muchísimos métodos que a priori el simple enunciado del problema no
pedía...

La POO tiene un objetivo a horizonte más largo que la programación estructurada...


Recordemos que la POO aparece como una forma de aportar claridad y mayor control en sistemas
verdaderamente grandes, brindando herramientas y principios que favorecen la re-usabilidad de código
o el planteo de procesos genéricos... Puede que ahora este simple ejemplo no muestre la potencia del
paradigma, pero a medida que el estudiante avance, notará que su productividad como programador
aumenta, cada vez más, hasta que en algún momento podrá llegar a plantear programas en los que
simplemente deberá combinar objetos de clases que ya tenía preparadas en otros sistemas, o provistas
por el propio Java... y entonces entenderá.

Como ejemplo del poder del reuso de código, supongamos ahora que se nos pide desarrollar
un programa nuevo. El pedido podría ser el siguiente (basado en un problema que se dejó a modo de
ejercicio en una ficha anterior):

ii.) Se desea cargar por teclado un conjunto de números que representan los valores de los lados
de un conjunto de terrenos a la venta en un loteo. Cada terreno es un cuadrado, por lo que basta con saber
el valor de un lado para definir su superficie. El programa debe mostrar la superficie de cada terreno en el
cual se cumpla que el valor de cada lado es mayor a 20 metros.

Podemos ver que en este enunciado vuelve a aparecer la necesidad de trabajar con objetos de la
clase Cuadrado, y posiblemente con objetos de otras clases (¿una clase Loteo o Inmobiliaria que se
encargue del proceso de chequear lo pedido en el enunciado?)

Y bien: aparecen nuevas clases, pero al menos una ya está diseñada, programada y lista para
entrar a operar nuevamente: nuestra clase Cuadrado encaja perfectamente con este requerimiento. Y
ahora vemos que no fue una mala idea dotar a esa clase de tantos métodos de soporte como fuera
necesario: en el primer problema no se requirió de los servicios del método getLado(), pero se incluyó
de todos modos. Y ahora ese método será valioso para chequear si el lado es mayor a 20 o no. El
problema podría haber hablado del perímetro del cuadrado: eso no estaba previsto en nuestra clase
original, pero con poco trabajo podría incluirse ahora...

Podemos ver que si nos esforzamos en identificar clases pequeñas pero funcionalmente
completas, que sepan hacer bien un trabajo específico, tendremos muchas probabilidades de volver a
usar esa clase en otros proyectos, más adelante. O podría ocurrir que otros programadores de nuestro
equipo noten que nuestras clases les serían útiles en sus propios desarrollos... Al fin y al cabo, piense
lo que hizo por Usted la clase JOptionPane... esa clase propia de Java tiene programados muchos
métodos que no siempre se usan todos en un mismo programa, pero la clase está preparada para
responder si un programador la necesita... Y más modestamente, lo mismo vale para nuestra vieja
clase Consola...

El segundo problema podría resolverse así:

Ing. Valerio Frittelli - 9


Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

La clase Cuadrado es exactamente la misma que usamos en el problema anterior


(simplemente, se agregó al proyecto como normalmente agregamos la clase Consola...) La clase Loteo
contiene el método procesar() que lleva adelante el proceso pedido por el enunciado. Técnicamente,
ese método usa un ciclo para cargar los lados de los terrenos por teclado. El ciclo sigue mientras el
lado no sea cero ni negativo, y en cada vuelta crea un Cuadrado (representando a un terreno). Se toma
el lado de ese cuadrado (con getLado()) y se chequea si su valor es mayor a 20. Si así fuera, se calcula
la superficie del terreno (con el método superficie() de la clase Cuadrado) y se muestra por pantalla.

Listamos sólo la clase Principal (que ahora tiene muy poco trabajo...) y la clase Loteo. La
clase Cuadrado ya se listó en el ejemplo anterior, y la clase Consola se usa como clase de soporte:

// ***************Clase Loteo********************
public class Loteo
{
private String nombre;
private Cuadrado terreno;

public Loteo()
{
nombre = "Remate Judicial";
}

public Loteo(String nom)


{
nombre = nom;
}

public String getNombre()


{
return nombre;
}

public void setNombre(String nom)


{
nombre = nom;
}

public String toString()


{
Ing. Valerio Frittelli - 10
Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

return "Nombre: " + nombre;


}

public void procesar()


{
float lado;
System.out.print("Cargue lado (menor o igual a cero termina): ");
lado = (float)Consola.readDouble();
while(lado > 0)
{
Cuadrado terreno = new Cuadrado(lado);
if(terreno.getLado() > 20)
{
float sup = terreno.superficie();
System.out.println("Superficie del lote: " + sup);
}
System.out.print("Cargue lado (menor o igual a cero termina): ");
lado = (float)Consola.readDouble();
}
}
}

//*************Clase Principal****************
public class Principal
{
public static void main (String args[])
{
Loteo loteo = new Loteo("El Cuadrado");
System.out.println("Loteo: " + loteo.getNombre());

loteo.procesar();
}
}

Ing. Valerio Frittelli - 11


Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

Ejercicios: Se plantean ahora una serie de ejercicios que servirán para que los alumnos pongan en
práctica los temas vistos hasta aquí. La idea es que para todos los ejercicios que siguen plantee un
proyecto Java e incluya clases en la forma más completa que le sea posible. Luego plantee un método
main() en una clase Principal para resolver el problema usando objetos de las clases que haya creado.
Trate de no incluir en esa clase Principal los métodos que específicamente resuelven el problema:
esfuércese para tratar de diseñar clases separadas que cuenten con esos métodos, y luego invóquelos
desde un método main(). También esté atento a la posibilidad de reusar clases que ya haya diseñado y
creado para otros programas, o que hayan sido creadas por sus profesores en algún ejemplo.

Como siempre, recomendamos encarecidamente que cada estudiante haga el esfuerzo de desarrollar
todos los ejercicios pedidos, o al menos que haga el intento. En clase, consulte las dudas que pudieran
haberle surgido. No se quede sin preguntar. Use también el foro del aula virtual si necesita trasladar
una duda a sus compañeros o a sus docentes mientras intenta plantear los ejercicios. Durante el
transcurso de las semanas siguientes, se publicarán en el aula virtual las soluciones sugeridas por los
docentes a cada uno de estos ejercicios. No lo olvide... nunca lo olvide: a programar, se
aprende programando.

a.) Se ingresa por teclado un conjunto de números, uno a uno. Contar cuantas veces se
presenta el valor 10, el 20, el 30 y el 40; y cuantos números distintos a esos se presentan. Cortar el
proceso cuando el número ingresado sea igual a -1.

b.) Se lee un conjunto de n valores enteros. Se desea saber si la suma de todos ellos, es
igual, mayor o menor que cero.

c.) Escribir un programa que lea n números enteros y calcule la suma de los valores
ingresados que sean mayores a 10.

d.) Escribir un programa que lea n números enteros y calcule y muestre su suma y su
promedio. Indique también si ese promedio es mayor o menor que 100.

e.) Desarrolle un programa que permita cargar por teclado las edades de un conjunto
personas, una a una por doble lectura. Considere que la carga de datos termina cuando aparezca una
edad negativa. Determine cuántas de esas edades eran menores a 18, cuántas eran mayores o iguales a
18 pero menores a 21, y cuántas eran mayores o iguales a 21. Determine también la edad promedio del
grupo.

f.) Se tiene un conjunto de rectángulos y por cada uno se carga por teclado su base y
su altura. Se pide mostrar el valor del área, la base y la altura, sólo de aquellos rectángulos cuyo
perímetro sea menor que un número p dado (o sea, ingresado como dato). Continuar hasta que la base
ingresada sea igual a cero.

a.) Desarrolle un programa que permita cargar por teclado un número a y otro número
b. El programa debe validar que a sea menor que b, y luego mostrar todos los múltiplos de 3 que estén
en el intervalo [a, b].

b.) Determinar y mostrar los números impares comprendidos entre a y b, siendo a y b


datos ingresados por teclado.

Ing. Valerio Frittelli - 12


Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

c.) Generar y mostrar los primeros n múltiplos de tres que no sean múltiplos de cuatro,
siendo n un dato que se carga por teclado.

d.) Cargue por teclado un número entero n, validando que n no sea negativo ni cero. El
programa debe determinar si el número es primo o no.

e.) Una fábrica de piezas metálicas circulares para automóviles necesita un programa
para procesar ciertos datos acerca de su producción en un período dado. Se requiere cargar por teclado
los datos del radio de cada tipo de pieza producida (cortar cuando el radio sea cero o negativo), y
realizar lo siguiente:
1.) Determinar cuántas piezas tienen una longitud de circunsferencia
(perímetro... o sea: 2*pi*radio) mayor a cierto valor x cargado por
teclado.
2.) Determinar la superficie promedio de todas las piezas cargadas.

f.) Escribir un programa que pida ingresar coordenadas (x, y) de un conjunto de puntos
(para x e y distintos de 0(cero)) e informe la cantidad de puntos que hay en cada cuadrante. El proceso
debe terminar al ingresar el par (0, 0).

g.) Un punto en un plano puede representarse como un objeto con dos atributos que
almacenen sus coordenadas (de hecho, posiblemente eso fue lo que Usted hizo en el ejercicio anterior...)
Desarrolle un programa con menú de opciones, que permita ingresar dos puntos a y b, representados
como objetos, y que contenga opciones para:

1.) Cargar los dos puntos por teclado.


2.) Mostrar los puntos en forma de par ordenado.
3.) Calcular la distancia de cada uno al origen de coordenadas (se
aplica el teorema de Pitágoras...)
4.) Calcular y mostrar la longitud del segmento de recta que los une:
lr = sqrt ( (b.x - a.x)2 + (b.y - a.y)2 )

5.) Calcular y mostrar la pendiente de la recta que los une:


p = (b.y - a.y) / (b.x - a.x)

h.) Un número complejo tiene la forma c = a + b*i , donde a y b son números reales, y
el factor i es la unidad imaginaria, que se define como la raíz cuadrada del número (-1) aunque
simbólicamente, un número complejo simplemente puede representarse como c = (a , b*i) o incluso
como el par ordenado c = (a, b) si se asume que el factor i va implícito. Se puede pensar entonces en
una clase Complejo que use dos atributos para representar un número complejo, guardando en uno de
esos atributos el número a (parte real), y en el otro el número b (parte imaginaria). Formalmente, el
factor i (unidad imaginaria) se asume implícitamente en dicha representación, como acompañando al
Ing. Valerio Frittelli - 13
Ficha de Estudio: Gestión de Referencias y otros conceptos de Java

número b, y no es necesario almacenar ni representar al mismo en atributo alguno: cuando necesite


mostrarlo, simplemente haga aparecer una i en la pantalla... Desarrollar un programa que implemente y
pruebe métodos diversos en esa clase, para realizar las siguientes operaciones básicas de números
complejos:

1.) Dar valores iniciales a los atributos de un complejo.


2.) Retornar una cadena con el número completo adecuadamente
representado.
3.) Volver a cero un complejo: (a, b) = (0, 0)
4.) Sumar dos complejos: (a , b) + (c , d) = ( (a+c) , (b+d) )
5.) Restar dos complejos: (a , b) - (c , d) = ( (a-c) , (b-d) )
6.) Multiplicar: (a , b) * (c , d) = ( (a*c - b*d) , (a*d + c*b) )
7.) Devolver la parte real del complejo.
8.) Devolver la parte imaginaria.
9.) Devolver el módulo: abs( (a,b) ) = sqrt ( a*a + b*b )
10.) Devolver el conjugado del complejo: conjugado((a,b)) = (a,-b)

Ing. Valerio Frittelli - 14