viernes, 23 de marzo de 2007

Java: Paquetes y Jerarquia de Clases

Adriana E. Alturo Hoyos
Ingeniería de Sistemas
VII Semestre
Diseño de Aplicativos


¿Que son los Paquetes Informaticos de Java?


Los paquetes informáticos son colecciones de clases, contenidas en una colección que las une. Prácticamente son bibliotecas a las que el usuario puede acceder y que ofrecen varias funciones.
Los usuarios pueden también crear paquetes informáticos, por ejemplo, haciendo que contengan todas las clases que ha definido para poner en marcha algunas funciones que luego usará en varios programas.
Esta es la auténtica potencia de Java, el número de clases ya establecidas que realizan las más variadas tareas, y es también la parte que sigue creciendo más y más, y que sigue poniendose al día con las nuevas versiones de Java (JDK 1.3 bien contiene 18Mb). Los paquetes informáticos de Java son tantos que sólo describiré dos es decir, los que nos sirven para definir interfaces gráficas y apliques. Obviamente todos los paquetes informáticos del lenguaje están descritos en la mastodóntica guía en línea del JDK que se puede bajar junto al paquete del compilador (La JDK Documentation 1.3 beta es de 105 Megabyte, comprimida es de unos treinta Megas).
El núcleo del lenguaje Java contiene sólo las palabras claves para la construcción de las clases, los comentarios, las construcciones normales en if, switch, while, do-while, for, etiquetas, break, continue e return (falta el goto). Todo lo demás está contenido en los paquetes informáticos del lenguaje, incluidas las normales primitivas de Entrada y de Salida.

La lista completa de los paquetes informáticos de Java 1.2.1 en orden alfabético es el siguiente:
com.sun.image.codec.jpeg, com.sun.java.swing.plaf.windows,com.sun.java.swing.plaf.motif, java.applet, java.awt, java.awt.color, java.awt.datatransfer, java.awt.dnd, java.awt.event, java.awt.font, java.awt.geom, java.awt.im, java.awt.image, java.awt.image.renderable, java.awt.print, java.beans, java.beans.beancontext, java.io, java.lang, java.lang.ref, java.lang.reflect, java.math, java.net, java.rmi, java.rmi.activation, java.rmi.dgc, java.rmi.registry, java.rmi.server, java.security, java.security.acl, java.security.cert, java.security.interfaces, java.security.spec, java.sql, java.text, java.util, java.util.jar, java.util.zip, javax.accessibility, javax.swing, javax.swing.border, javax.swing.colorchooser, javax.swing.event, javax.swing.filechooser, javax.swing.plaf, javax.swing.plaf.basic, javax.swing.plaf.metal, javax.swing.plaf.multi, javax.swing.table, javax.swing.text, javax.swing.text.html, javax.swing.text.html.parser, javax.swing.text.rtf, javax.swing.tree, javax.swing.undo, org.omg.CORBA, org.omg.CORBA.DynAnyPackage, org.omg.CORBA.ORBPackage, org.omg.CORBA.portable, org.omg.CORBA.TypeCodePackage, org.omg.CosNaming, org.omg.CosNaming.NamingContextPackage, sun.tools.ttydebug, sunw.io, sunw.util.

Realmente parecen pocos, parece que haya dicho una tontería cuando me refería a la potencia de Java, sin embargo si pensáis que sólo el paquete informático Java.io comprende 50 clases y 10 interfaces, comprenderéis que los de antes son una colección de clases consistente.Llegados a este punto nos gustaría hacer la entrada y la salida de consolle y para hacerlo debemos usar el paquete informático java.lang .para usar un paquete informático en una de nuestras clases, antes de definir la clase, tenemos que introducir la instrucción import. Por ejemplo, si queremos usar el paquete informático java.awt tenemos que introducir al comienzo de nuestro archivo:

import java.awt.*;

El * indica que queremos usar todas las clases, en cambio si queremos usar sólo una clase lo podemos especificar, por ejemplo, import java.awt.Frame; podremos usar la clase Frame del awt. En nuestro caso, en el que queremos hacer una operación de entrada, tendremos que declarar al empezar import java.lang.*;o, sabiendo que la clase del paquete informático java.lang que contiene los métodos para hacerlo es System, podremos escribir

import java.lang.System;

La clase System, a su vez, contendrá en su interior una import java.io (que es el paquete informático para la entrada y la salida) para acceder a las clases de la entrada y de la salida, y las usará para mandar lo que queramos en la pantalla.Vimos un ejemplo de paquete informático que en su interior llama a otro paquete informático para que lleve a cabo unas tareas. En estas bibliotecas Java ocurre eso a menudo y es precisamente este fenómeno que hace de Java un lenguaje incomprensible para la mayoría. Sin embargo, superado este inconveniente que se refiere a este aspecto del lenguaje, la programación se hace fácil e inmediata.He introducido el paquete informático java.lang. Ahora os digo también que este es el más importante de Java, en éste están contenidos las clases fundamentales del lenguaje, hasta el punto de que no hace falta declarara el import, porque Java lo introduce automáticamente.Además me gustaría detenerme en un aspecto fundamental de la introducción de los paquetes informáticos. Si importo en mi archivo el paquete informático java.lang, éste importará a su vez el paquete informático java.io, y yo desde mi archivo no podré usar las clases de java.io; para hacerlo tengo que importarlo explícitamente. Esto sucede aunque programe una aplicación en más de un archivo (con más clases), en cada archivo tengo que importar los paquetes informáticos que necesito para la clase que estoy estableciendo, no basta con importarlos en una sola.
Veamos pues las clases que contiene este paquete informático java.lang tan importante para el lenguaje:

Boolean
hemos dicho que los tipos de datos se pueden representar también con objetos dichos;
contenedoreses una clase que genera los contenedores para los tipos de datos boolean (verdadero, falso).
Bytees
la clase que genera los contenedores para los tipos de datos enteros cortos (de un byte).
Characteres
una clase que genera los contenedores para los tipos de datos caracteres.
Character.Subsetes
la clase que genera los contenedores para los tipos de datos caracteres con codificación unicode.
Character.UnicodeBlockes
la clase que genera los contenedores para los tipos de caracteres con codificación unicode 2.0.
Class
representa las clases y las interfaces a runtime (en ejecución), en Java es posible, en tiempo de ejecución, crear, ejecutar y compilar clases. El compilador y el ejecutor se mezclan de una forma rara, sin embargo a nosostros no nos sirven estas clases "especiales" porque escribiremos unas aplicaciones fáciles.
ClassLoadercargador
de clases a tiempo de ejecución.
Compiler
compilador de clases a tiempo de ejecución.
Doublees
la clase que genera los contenedores para los tipos de datos reales en coma móvil de 64 bit.
Float
es la clase que genera los contenedores para los tipos de datos reales de 32 bit en coma móvil.
Integer
es la clase que genera los contenedores para los tipos de datos enteros.
Import
Lo siguiente que se pone después de una sentencia package y antes de las definiciones de clase en un archivo fuente en Java puede ser una lista de sentencias import. Todas las clases interesantes están almacenadas en algún paquete con nombre. Para no tener que introducir el largo nombre de trayecto de paquete para cada clase, Java incluye la sentencia import para que se puedan ver ciertas clases o paquetes enteros. La forma general de la sentencia import:
import paquete1.[ paquete2 ].( nombre_clase * );
paquete1 es el nombre de un paquete de alto nivel, paquete2 es el nombre de un paquete opcional contenido en el paquete exterior separado por un punto (.). No hay ningún límite práctico a la profundidad de la jerarquía de paquetes.Finalmente, nombre_clase explícito o un asterisco (*) que indica que el compilador Java debería buscar este paquete completo.
import java.util.Date;import java.io.*;
Long
es la clase que genera los contenedores para los tipos de datos enteros dobles.Mathcontiene métodos que simulan funciones matemáticas.
Number
clase de objetos contenedores de números genéricos.
Object
es la clase de la que derivan todas las clases del lenguaje Java, es decir, cada clase es subclase (no necesariamente directa) de ésta.
Package
Lo primero que se permite en un archivo Java es una sentencia package, que le dice al compilador en qué paquete se deberían definir las clases incluidas. Si se omite la sentencia package, las clase terminan en el paquete por defecto, que no tiene nombre. El compilador Java utiliza directorios de sistema de archivos para almacenar paquetes.
Si se declara que una clase está en dentro de un paquete llamado MiPaquete, entonces el archivo fuente de esa clase se debe almacenar en un directorio llamado MiPaquete.
Recuerde que se diferencia entre mayúsculas y minúsculas y que el nombre del directorio debe coincidir con el nombre exactamente. Esta es la forma general de la sentencia package.
package paq1[ .paq2 [ .paq3 ]];
Observe que se puede crear una jerarquía de paquetes dentro de paquetes separando los niveles por puntos. Esta jerarquía se debe reflejar en el sistema de archivos de desarrollo de Java. Un paquete declarado como
package java.awt.imagen;
se debe almacenar en java/awt/imagen, en java\awt\imagen o en java:awt:imagen en los sistemas de archivo UNIX, Windows o Macintosh, respectivamente.
ProcessJava
es un lenguaje que permite gestionar Thread, es decir pequeños programas que corren en paralelo. Esta clase se ocupa de ellos, como las demás clases de java.lang: Runtime, RuntimePermission, Thread, ThreadGroup, ThreadLocal, Throwable
SecurityManager
para la seguridad
Shortes
la clase que genera los contenedores para los tipos de datos enteros cortos.
Stringes
la clase que genera los contenedores para los tipos de datos cadenas de caracteres.
StringBufferes
la clase que genera los contenedores para los tipos de datos cadenas de caracteres modificables.
System
es la clase que interactúa con el sistema y contiene muchos métodos útiles, y unas referencias a otras clases (llamadas class field), es la que usaremos, por ejemplo, para crear una salida sobre la pantalla a caracteres.
Void
es la clase que genera los contenedores para los tipos de datos void, es decir, sin tipo. Éste parece un tipo de dato inútil, sin embargo veremos que no lo es en absoluto, además es utilísimo. En realidad, es útil cuando queremos definir un método-procedimiento (un método que no tiene valor de vuelta), en Java existen sólo dos funciones que obligan a devolver un valor del tipo que declaran. Declarando un método como void, se simula el procedimiento, es decir, no se necesita la vuelta.

Protección de accesos
Java proporciona unos cuantos mecanismos para permitir un control de acceso entre clase en circunstancias diferentes.
Dentro de un clase todas las variables y métodos son visibles para todas las otras partes de la misma clase. Por la existencia de paquetes, Java debe distinguir cuatro categorías de visibilidad entre elementos de clase: - Subclases del mismo paquete. - No subclases del mismo paquete. - Subclases en paquetes distintos.- Clases que no están ni en el mismo paquete ni en las subclases.
Las tres palabras clave, private, public y protected se combinan de varias maneras para generar muchos niveles de acceso.

¿Qué es la Jerarquía de Clases en Java?

Una clase es una agrupación de datos (variables o campos) y de funciones (métodos) que operan sobre esos datos.
public class Classname
{ ...// definición de variables y métodos
}
Un objeto (instance) es un ejemplar concreto de una clase.
Las características de una clase son las siguientes:
1) Todas las variables y funciones de Java deben pertenecer a una clase.
2) Si una clase deriva de otra (extends), hereda todas sus variables y métodos.
3) Java tiene una jerarquía de clases estándar de la que pueden derivar las clases que crean los usuarios.
4) En Java no hay herencia múltiple.
5) En un fichero se pueden definir varias clases, pero en un fichero no puede haber más que una clase public.
6) Si una clase contenida en un fichero no es public, no es necesario que el fichero se llame como la clase.
7) Los métodos de una clase pueden referirse de modo global al objeto de esa clase al que se aplican por medio de la referencia this.
8) Las clases se pueden agrupar en packages, introduciendo una línea al comienzo del fichero (package packageName;).

Variables miembro
Variables
miembro de clase (static). Son aquellas variables propias de la clase. Se crean anteponiendo la palabra static a su declaración, y se suelen utilizar para definir constantes comunes para todos los objetos de la clase.
Las variables de clase son lo más parecido que Java tiene a las variables globales de C/C++.
Variables finales
Variables que no pueden cambiar su valor a lo largo de la ejecución del programa. Puede ser considerada como una constante, y equivale a la palabra const de C/C++.
Java permite separar la definición de la inicialización de una variable final; es decir, la inicialización puede hacerse más tarde, en tiempo de ejecución, llamando a métodos o en función de otros datos.
Métodos (funciones miembro)
Los métodos son funciones definidas dentro de una clase.
La primera línea de la definición de un método se llama declaración o header; el código comprendido entre las llaves { ... } es el cuerpo o body del método.
public returnValue functionName(arg1,arg2,...)
{ // comienzo del método
... // cuerpo de la función
} // final del método
El header consta del cualificador de acceso (public, en este caso), del tipo del valor de retorno, del nombre de la función y de una lista de argumentos explícitos entre paréntesis, separados por comas.
Métodos de objeto
Se aplican siempre a un objeto de la clase por medio del operador punto (.). Dicho objeto es su argumento implícito.
Métodos de clase (static).
Métodos que no actúan sobre objetos concretos a través del operador punto. Los métodos de clase pueden recibir objetos de su clase como argumentos explícitos, pero no tienen argumento implícito ni pueden utilizar la referencia this.
Métodos sobrecargados (overloaded).
Métodos que tienen el mismo nombre, pero que se diferencian por el número y/o tipo de los argumentos.
Constructores
Un constructor es un método que se llama automáticamente cada vez que se crea un objeto de una clase. La principal misión del constructor es reservar memoria e inicializar las variables miembro de la clase.
Los constructores no tienen valor de retorno (ni siquiera void) y su nombre es el mismo que el de la clase. Su argumento implícito es el objeto que se está creando.
Una clase tiene varios constructores, que se diferencian por el tipo y número de sus argumentos (métodos sobrecargados). Se llama constructor por defecto al constructor que no tiene argumentos.
Inicializadores
Línea de actuación para evitar que haya variables sin inicializar correctamente, y estos pueden ser static (para la clase) o de objeto.
Inicializadores de clase (static).
Es un algo parecido a un método que se llama automáticamente al crear la clase. Se diferencia del constructor en que no es llamado para cada objeto, sino una sola vez para toda la clase.
Los tipos primitivos pueden inicializarse directamente con asignaciones en la clase o en el constructor, pero para inicializar objetos o elementos más complicados es bueno utilizar un inicializador, ya que permite gestionar excepciones (situaciones de error) con try... catch.
Los inicializadores static se crean dentro de la clase, como métodos sin nombre, sin argumentos y sin valor de retorno; tan solo es la palabra static y el código entre llaves { ... }.
Inicializadores de objeto.
No llevan la palabra static y se utilizan para las clases anónimas, que por no tener nombre no pueden tener constructor. En este caso, los inicializadores de objeto se llaman cada vez que se crea un objeto de la clase anónima.
Destrucción de objetos (liberación de memoria)
En Java no hay destructores como en C++. El sistema se ocupa automáticamente de liberar memoria de los objetos que ya han perdido la referencia, esto es, objetos que ya no tienen ningún nombre que permita acceder a ellos, por ejemplo por haber llegado al final del bloque en el que habían sido definidos, porque a la referencia se le ha asignado el valor null o porque a la referencia se le ha asignado la dirección de otro objeto. A esta característica se le llama recogida de basura (garbage collection).
Finalizadores
Son métodos que vienen a complementar la labor del garbage collector. Un finalizador es un método de objeto (no static), sin valor de retorno (void), sin argumentos, con nombre de función finalize(), y que se llama automáticamente cuando se va a destruir un objeto (antes de que la memoria sea liberada de modo automático por el sistema). Se utilizan para ciertas operaciones de terminación distintas de liberar memoria (por ejemplo: cerrar ficheros, cerrar conexiones de red, etc.)
Packages
Un package es una agrupación de clases.
Para que una clase pase a formar parte de un package llamado pkgName, hay que introducir en ella la sentencia: package pkgName; que debe ser la primera sentencia del fichero sin contar comentarios y líneas en blanco.
Los nombres de los packages se suelen escribir con minúsculas para distinguirlos de las clases.
Todas las clases que forman parte de un package deben estar en el mismo directorio. Los nombres compuestos de los packages están relacionados con la jerarquía de directorios en que se guardan las clases. Package permite que los nombres de las clases de Java sean únicos en Internet y así evitar conflictos.
Las clases de un package se almacenan en un directorio con el mismo nombre largo (path) que el package. Por ejemplo, la clase es.ceir.jgjalon.infor2.ordenar.QuickSort.class debería estar en el directorio CLASSPATH\es\ceir\jgjalon\infor2\ordenar\QuickSort.class, donde CLASSPATH es una variable de entorno del PC que establece la posición absoluta de los directorios en los que hay clases de Java (clases del sistema o de usuario), en este caso la posición del directorio es en los discos locales del ordenador.
Los packages se utilizan con las finalidades siguientes:
1) Para agrupar clases relacionadas.
2) Para evitar conflictos de nombres ya que el dominio de nombres de Java es la Internet.
3) Para ayudar en el control de la accesibilidad de clases y miembros.

Clases y
métodos abstractos
Una clase abstracta (abstract) es una clase de la que no se pueden crear objetos. Su utilidad es permitir que otras clases deriven de ella, proporcionándoles un marco o modelo que deben seguir y algunos métodos de utilidad general. Las clases abstractas se declaran anteponiéndoles la palabra abstract, como por ejemplo public abstract class Geometria { ... }
Una clase abstract puede tener métodos que no son abstract, pero si una clase tiene algún método abstract es obligatorio que la clase sea abstract.
Clases y
métodos finales
Una clase declarada final no puede tener clases derivadas. Esto se puede hacer por motivos de seguridad y también por motivos de eficiencia, porque cuando el compilador sabe que los métodos no van a ser redefinidos puede hacer optimizaciones adicionales.
Análogamente, un método declarado como final no puede ser redefinido por una clase que derive de su propia clase.
Interfaces
Una interface es un conjunto de declaraciones de métodos (sin definición).


Consideremos las figuras planas cerradas como el rectángulo, y el círculo. Tales figuras comparten características comunes como es la posición de la figura, de su centro, y el área de la figura, aunque el procedimiento para calcular dicha área sea completamente distinto. Podemos por tanto, diseñar una jerarquía de clases, tal que la clase base denominada Figura, tenga las características comunes y cada clase derivada las específicas. La relación jerárquica se muestra en la figura


La clase Figura es la que contiene las características comunes a dichas figuras concretas por tanto, no tiene forma ni tiene área. Esto lo expresamos declarando Figura como una clase abstracta, declarando la función miembro area abstract.

Las clases abstractas solamente se pueden usar como clases base para otras clases. No se pueden crear objetos pertenecientes a una clase abstracta. Sin embargo, se pueden declarar variables de dichas clases.
En el juego del ajedrez podemos definir una clase base denominada Pieza, con las características comunes a todas las piezas, como es su posición en el tablero, y derivar de ella las características específicas de cada pieza particular. Así pues, la clase Pieza será una clase abstracta con una función abstract denominada mover, y cada tipo de pieza definirá dicha función de acuerdo a las reglas de su movimiento sobre el tablero.
La clase Figura
La definición de la clase abstracta Figura, contiene la posición x e y de la figura particular, de su centro, y la función area, que se va a definir en las clases derivadas para calcular el área de cada figura en particular.


public abstract class Figura {
protected int x;
protected int y;
public Figura(int x, int y) {
this.x=x;
this.y=y;
}
public abstract double area();
}

La clase Rectangulo

Las clases derivadas heredan los miembros dato x e y de la clase base, y definen la función area, declarada abstract en la clase base Figura, ya que cada figura particular tiene una fórmula distinta para calcular su área. Por ejemplo, la clase derivada Rectangulo, tiene como datos, aparte de su posición (x, y) en el plano, sus dimensiones, es decir, su anchura ancho y altura alto.


class Rectangulo extends Figura{
protected double ancho, alto;
public Rectangulo(int x, int y, double ancho, double alto){
super(x,y);
this.ancho=ancho;
this.alto=alto;
}
public double area(){
return ancho*alto;
}
}


La primera sentencia en el constructor de la clase derivada es una llamada al constructor de la clase base, para ello se emplea la palabra reservada super. El constructor de la clase derivada llama al constructor de la clase base y le pasa las coordenadas del punto x e y. Después inicializa sus miembros dato ancho y alto.
En la definición de la función area, se calcula el área del rectángulo como producto de la anchura por la altura, y se devuelve el resultado
La clase Circulo


class Circulo extends Figura{
protected double radio;
public Circulo(int x, int y, double radio){
super(x,y);
this.radio=radio;
}
public double area(){
return Math.PI*radio*radio;
}
}


Como vemos, la primera sentencia en el constructor de la clase derivada es una llamada al constructor de la clase base empleando la palabara reservada super. Posteriormente, se inicializa el miembro dato radio, de la clase derivada Circulo.

En la definición de la función area, se calcula el área del círculo mediante la conocida fórmula r2, o bien *r*r. La
constante Math.PI es una aproximación decimal del número irracional .

Uso de la jerarquía de clases

Creamos un objeto c de la clase Circulo situado en el punto (0, 0) y de 5.5 unidades de radio. Calculamos y mostramos el valor de su área.
Circulo c=new Circulo(0, 0, 5.5);
System.out.println("Area del círculo "+c.area());
Creamos un objeto r de la clase Rectangulo situado en el punto (0, 0) y de dimensiones 5.5 de anchura y 2 unidades de largo. Calculamos y mostramos el valor de su área.
Rectangulo r=new Rectangulo(0, 0, 5.5, 2.0);
System.out.println("Area del rectángulo "+r.area());

Veamos ahora, una forma alternativa, guardamos el valor devuelto por new al crear objetos de las clases derivadas en una variable f del tipo Figura (clase base).
Figura f=new Circulo(0, 0, 5.5);
System.out.println("Area del círculo "+f.area());
f=new Rectangulo(0, 0, 5.5, 2.0);
System.out.println("Area del rectángulo "+f.area());

Enlace dinámico
En el lenguaje C, los identificadores de la función están asociados siempre a direcciones físicas antes de la ejecución del programa, esto se conoce como enlace temprano o estático. Ahora bien, el lenguaje C++ y Java permiten decidir a que función llamar en tiempo de ejecución, esto se conoce como enlace tardío o dinámico. Vamos a ver un ejemplo de ello.
Podemos crear un array de la clase base Figura y guardar en sus elementos los valores devueltos por new al crear objetos de las clases derivadas.
Figura[] fig=new Figura[4];
fig[0]=new Rectangulo(0,0, 5.0, 7.0);
fig[1]=new Circulo(0,0, 5.0);
fig[2]=new Circulo(0, 0, 7.0);
fig[3]=new Rectangulo(0,0, 4.0, 6.0);

La sentencia
fig[i].area();
¿a qué función area llamará?. La respuesta será, según sea el índice i. Si i es cero, el primer elemento del array guarda una referencia a un objeto de la clase Rectangulo, luego llamará a la función miembro area de Rectangulo. Si i es uno, el segundo elemento del array guarda una referencia un objeto de la clase Circulo, luego llamará también a la función area de Circulo, y así sucesivamente. Pero podemos introducir el valor del índice i, a través del teclado, o seleccionando un control en un applet, en el momento en el que se ejecuta el programa. Luego, la decisión sobre qué función area se va a llamar se retrasa hasta el tiempo de ejecución.

El polimorfismo en acción
Supongamos que deseamos saber la figura que tiene mayor área independientemente de su forma. Primero, programamos una función que halle el mayor de varios números reales positivos.

double valorMayor(double[] x){
double mayor=0.0;
for (int i=0; imayor){
mayor=x[i];
}
return mayor;
}
Ahora, la llamada a la función valorMayor
double numeros[]={3.2, 3.0, 5.4, 1.2};
System.out.println("El valor mayor es "+valorMayor(numeros));

La función figuraMayor que compara el área de figuras planas es semejante a la función valorMayor anteriormente definida, se le pasa el array de objetos de la clase base Figura. La función devuelve una referencia al objeto cuya área es la mayor.


static Figura figuraMayor(Figura[] figuras){
Figura mFigura=null;
double areaMayor=0.0;
for(int i=0; iareaMayor){
areaMayor=figuras[i].area();
mFigura=figuras[i];
}
}
return mFigura;
}


La clave de la definición de la función está en las líneas
if(figuras[i].area()>areaMayor){
areaMayor=figuras[i].area();
mFigura=figuras[i];
}

En la primera línea, se llama a la versión correcta de la función area dependiendo de la referencia al tipo de objeto que guarda el elemento figuras[i] del array. En areaMayor se guarda el valor mayor de las áreas calculadas, y en mFigura, la figura cuya área es la mayor.

La principal ventaja de la definición de esta función estriba en que la función figuraMayor está definida en términos de variable figuras de la clase base Figura, por tanto, trabaja no solamente para una colección de círculos y rectángulos, sino también para cualquier otra figura derivada de la clase base Figura. Así si se deriva Triangulo de Figura, y se añade a la jerarquía de clases, la función figuraMayor podrá manejar objetos de dicha clase, sin modificar para nada el código de la misma.

Veamos ahora la llamada a la función figuraMayor
Figura[] fig=new Figura[4];
fig[0]=new Rectangulo(0,0, 5.0, 7.0);
fig[1]=new Circulo(0,0, 5.0);
fig[2]=new Circulo(0, 0, 7.0);
fig[3]=new Rectangulo(0,0, 4.0, 6.0);
Figura fMayor=figuraMayor(fig);
System.out.println("El área mayor es "+fMayor.area());

Pasamos el array fig a la función figuraMayor, el valor que retorna lo guardamos en fMayor. Para conocer el valor del área, desde fMayor se llamará a la función miembro area. Se llamará a la versión correcta dependiendo de la referencia al tipo de objeto que guarde por fMayor. Si fMayor guarda una referencia a un objeto de la clase Circulo, llamará a la función area definida en dicha clase. Si fMayor guarda una referencia a un objeto de la clase Rectangulo, llamará a la función area definida en dicha clase, y así sucesivamente.

La combinación de herencia y enlace dinámico se denomina polimorfismo. El polimorfismo es, por tanto, la técnica que permite pasar un objeto de una clase derivada a funciones que conocen el objeto solamente por su clase base.

CYBERGRAFIA






No hay comentarios: