Free Web Site - Free Web Space and Site Hosting - Web Hosting - Internet Store and Ecommerce Solution Provider - High Speed Internet
Search the Web
 
Objetos.
 

En Java se crea un objeto mediante la creación de un objeto de una clase, es decir, instanciando una clase.  Ej:

Date hoy = new Date();
String nombre = new String("Juan");
 

Para declarar un objeto se procede como cualquier otra declaración de variable, las declaraciones de objetos pueden ser:

Date hoy;
 

Las declaraciones no crean nuevos objetos.  Para ejemplarizar una clase, se utiliza el operador NEW.

Numeros n = new Numeros();
 

El operador new permite realizar una instancia de una clase, mediante la asignación de memoria para el objeto nuevo de ese tipo.  new necesita un sólo argumento:  una llamada al método del constructor.

Rectangle rect = new Rectangle(0, 0, 100, 200);
 

Una clase podría tener múltiples constructores para realizar diferentes tipos de inicialización en los nuevos objetos.  Los constructores tienen el mismo nombre de la clase y no tienen tipo de retorno.  Un constructor que no tiene ningún argumento, es conocido como construtor por defecto.  Si una clase tiene varios constructores, éstos tendrán el mismo nombre pero diferentes parámetros.Ej:

Date hoy = new Date();
Date cumpleaños = new Date(1951,04,04);
 
 
 

Recolector de basura.
 

Un objeto es elegible para la recolección de basura cuando no existen más referencas a ese objeto.  Las referencias que se mantienen en una variable desaparecen de forma natural cuando la variable sale de su ámbito o cuando se borra explicitamente un objeto mediante el uso de null.

String nom=new String("Juan");
nom=null;

El recolector de basura funciona en un thread(hilo) de baja prioridad de forma síncrona o asíncrona.  Escanea dinámicamente la memoria buscando objetos, marcando aquellos que han sido referenciados.  Se puede invocar al recolector de basura aunque no se garantiza que los objetos sean recolectados con System.gc();

Antes de que un objeto sea recolectado, el recolector de basura le permite limpiarse él mismo mediante la llamada al método finalize() del propio objeto.
 
 

Clases.
 

La clase es un prototipo que se puede utilizar para crear objetos. La implementeación de una clase comprende dos componentes: la declaración  y el cuerpo de la clase.

class Nombre de la Clase{
 
    //cuerpo de la clase
}

Dentro de la declaración de la clase se puede declarar cual es la superclase de la clase, listar las interfaces implementadas por la clase y declarar si la clase es pública, abstracta o final.

En Java, todas las clases tienen una superclase.  Si no se especifica una superclase para una clase que es la clase Object(declarada en java.lang). Para especificar explícitamente una superclase de una clase, se debe poner la palabra clave "extends" más el nombre de la superclase.

class NombreClase extends NombreSuperclase
 

El cuerpo de la clase compone la implementación de la propia clase y contiene dos secciones diferentes:  la declaración de variables y la de métodos.  Primero se declaran las variables miembro  de la clase y después la declaración e implementación de los métodos.

Como mínimo una declaración de variables miembro tiene dos coponentes:   el tipo de dato y el nombre de la variable.Ej:

class Entero{
    static final int unEntero=10;
    float unFlotante;
}

La declaración de variables miembro, aparece dentro de la implementación del cuerpo de la clase pero no dentro de un método.  Este posicionamiento determina que una variable es variable miembro.  La implementación de métodos consiste en dos partes:  Declaración y el cuerpo del método.  Los únicos elementos necesarios de una declaración de método son el nombre y el tipo de retorno de método.  Ej:

public boolean action(Event e,Object o){
    if(e.target==factorial){
        num1=Integer.parseInt(input1.getText());
        repaint();  res=1;
    }
    return true;
}
 

Las variables son públicas por omisión.
 
 

this.
 

La palabra this, se utiliza para llamara a una variable miembro de una clase, cuando alguno de sus métodos llama a una de sus variables con el mismo nombre.

class HSBColor{
    int luminosidad, saturacion, brillo;
    HSBColor(int luminosidad, int saturacion, int brillo){
        this.luminosidad=luminosidad;
        this.saturacion=saturacion;
        this.brillo=brillo;
    }
}
 
 

super.
 

Si el método oculta una de las variables miembro de la superclase se puede referir a la variable oculta utilizado super.

class MiClase{
    boolean unaVariable;
    void unMetodo(){
        unaVariable=true;
    }
}

class OtraClase extends MiClase{
    boolean unaVariable;
    void unMetodo(){
        unaVariable=false;
        super.unMetodo();
        System.out.println(unaVariable);
        System.out.println(super.unaVariable);
        }
}
 
 

Acceso a los miembros de una clase.
 

En Java se puede utilizar los especificadores de accceso para proteger tanto las variables como los métodos de la clase cuando se declaran.  En Java se tienen cuatro niveles de acceso: provate, protected, public y acceso a paquetes.

Especificador         Clase         SubClase         Paquete         Mundo
private                        X
protected                    X                  X*                     X
public                          X                  X                       X                    X
package                     X                                            X

Private.-  Un miembro privado es accesible sólo para la clase en la que está definido.
Proteceted.-Un miembro es accesible para la clase, las subclases y todas las clases dentro del mismo paquete que
                     accedan a los miembros.
Public.-Todas las clases tienen acceso a lso miembros públicos.
Acceso de Paquete.-Se obtiene si no se especifica ningún otro nivel de acceso a los miembros. Este nivel permite
                                   que las clases del mismo paquete que la clase tengan acceso a los miembros.Ej:

class Alfa{
    private int soyPrivado;
    private void metodoPrivado(){
        System.out.println(“Metodo Privado”);
    }
}

class Beta{
    public static void main(String arg[]){
        Alfa a=new Alfa();
        a.soyPrivado=10;declarados como privados}}
 
 

Constructores.
 

Los constructores tienen la tarea de crear e inicializar el objeto.  Tienen el mismo nombre de la clase y no retornan un dato, por lo cual, en la declaración del constructor no se incluye un tipo de dato.  Java soporta la sobrecarga de los nombres de métodos, en consecuencia una clase podrá tener más de un constructor.  Al igual que cualquier método, los constructores se diferencían por el número y tipo de argumentos.  Si el programador no especifica un constructor, Java proporciona un constructor por default, este constructor no tiene argumentos.  Ej:

class Animation Thread extends Thread{
    int framesPerSecond;
    int numImages;
    Image[]images;
    Animation Thread(int fps,int num){
        int i;
        super(“Animation Thread”);
        this.framesPerSecond=fps;
        this.numImages=num;
        this.images=new Image[numImages];
        for(i=0;i<numImages;i++){
            //Carga de imágenes
        }
    }
}

Cuando se declaren constructores para las clases, se pueden utilizar los especificadores de acceso para especificar si otros objetos pueden crear ejemplares de sus clase.
 

Métodos de la clase Applet.
 

Estos métodos están definidos por la Java API de modo tal que no hacen nada a menos que el programador provea una definición en la definición de la clase de su applet.

Método                                             Descripción

public void init()                               Este método es invocado una vez por el Appletviewer o navegador cuando se
                                                           carga un applet para ejecutarse. Este método inicializa un applet
                                                          (inicialización de variables, componentes GUI, creación de hilos).

public void paint(Graphics g)         Este método se invoca para dibujar el applet después que el método init termina
                                                           de ejecutarse y se ha comenzado a ejecutar el método start; también se ejecuta
                                                          cuando el applet necesita dibujarse.
 

public void start()                              Este método se invoca después de que termina de ejecutarse el método init y
                                                            cada vez que el usuario del navegador regresa a la página HTML en la que
                                                            el applet reside. Este método realiza todas las tareas que deben llevarse a
                                                            cabo cuando el applet se carga por primera vez y cada vez que se vuelva a
                                                            visitar la página.

public void stop()                               Este método se invoca cuando la applet debe terminar su ejecución,
                                                            regularmente cuando el usuario del navegador abandona la página.

public void destroy()                         Este método se invoca cuando el applet se va a desalojar de la memmoria, lo
                                                            que normalmente sucede cuando el usuario del navegador sale de la sesion de
                                                            navegación.
 
 
 



Paneles.

Un panel es un contenedor. La clase Panel hereda de la
clase Container y la clase Applet hereda de Panel. Por
tanto, los Applet y los paneles son contenedores y se les
puede agregar componentes, incluidos otros paneles. El
constructor Panel no recibe aargumentos y no está
sobrecargado. Ej:

Panel panel1;//Declaración
Label label1;

panel1 = new Panel();//Crea un objeto en init()
label1 = new Label("Panel 1");
panel1 = setBackground(Color.blue);//en init

panel1.add(label);
.
.
.
add(panel1);



Casillas de verificación y botones de radio.


Estos son botones de estaado encendido/apagado o
verdadero/falso.

-Casillas de verificación:

Constructores. public Checkbox() Crea un objeto sin
título y sin marca.

public Checkbox(String s) Crea un
objeto con títulos y sin marca.

Ej:

Font fuente;
.
.
.
CheckBox checa1, checa2;
checa1 = new CheckBox("Negrita");
checa2 = new CheckBox();

checa2.setLabel("Cursiva");
t = new Font("TimesRoman", Font.PLAIN, 14);
t.setFont(t);
add(t);
add(checa1);
add(checa2);
//fin init

//en action
int b, i;

if(e.target instanceof Checkbox){
if(checa1.getState() == true)
b = Font.BOLD;
else
b = Font.PLAIN;
if(checa2.getState() == true)
i = Font.ITALIC;
else
i = font.PLAIN;

f = new Font("TimesRoman", b+i, 14);
t.setFont(f);
}
return true;
.
.
.


ARCHIVOS

Java considera los archivos como flujos secuenciales de
bytes. Cada archivo termina con un marcador de fin de
archivo.

Cuando se abre un archivo, se crea un objeto y se asocia un
flujo (stream) a dicho objeto.

Para procesar archivos se necesita importar el paquete
java.io que contiene entre otras cosas la definicion de las
clases FileInputStream y FileOutputStream (para flujos de
entrada y salida) Estas clases heredan de las clases
Inputsream y OutputStream (flujos de entrada / salida de
datos).

En java se pueden utilizar archivos de:

* acceso secuencial
* acceso aleatorio

ACCESO SECUENCIAL

El programador debe estructurar los archivos.

DataOutputStream output; //para escribir tipos de datos

output = new DataOutputStream(new FileOutputStream
("Dato.dat")) //encadenamiento de objetos
//de flujo

^ se abre archivo para esritura ^

DataInputStream input;

input = new DataInputStream(new FileInputStream("Dato.dat"));

^ se abre archivo para lectura ^


ejemplo de escritura:

output.write(Cadena);

ejemplo de lectura:

input.read();


debemos agregar las exepciones en caso de haber algun error:

try{

output = new DataOutput....
Output.write...
}catch(IOExeption e){
vista.append("error al crear archivo");
}

ejemplo para escribir diferentes tipos de datos:

output.writeUTF(cadena);
output.writeInt(entero);
output.writeBoolean( );
output.writeByte( );
output.writeBytes( );
output.writeChar( );
output.writeChars( );
output.writeDouble( );
output.writeFloat( );
output.writeLong( );
output.writeShort( );


Introducción a los Canales de I/O.

El paquete java.io contiene dos clases, InputStream y
OutputStream, de las que derivan la mayoría de las clases de
este paquete.

La clase InputStream es una superclase abstracta que
proporciona un interface de programación mínimo y una
implementación parcial del canal de entrada. La clase
InputStream define métodos para leer bytes o arrays de
bytes, marcar posiciones en el canal, saltar bytes de la
entrada, conocer el número de bytes disponibles para ser
leídos, y resetear la posición actual dentro del canal. Un
canal de entrada se abre automáticamente cuando se crea. Se
puede cerrar un canal explícitamente con el método close(),
o puede dejarse que se cierre implícitamente cuando se
recolecta la basura, lo que ocurre cuando el objeto deja de
referenciarse.

La clase Outputstream es una superclase abstracta que
proporciona un interface de programación mínimo y una
implementación parcial de los canales de salida. Un canal
de salida se abre automáticamente cuando se crea. Se puede
cerrar un canal explícitamente con el método close(), o se
puede dejar que se cierre implícitamente cuando se recolecta
la basura, lo que ocurre cuando el objeto deja de
referenciarse.

El paquete java.io contiene muchas subclases de InputStream
y OutputStream que implementan funciones específicas de
entrada y salida. Por ejemplo, FileInputStream y
FileOutputStream son canales de entrada y salida que operan
con ficheros en el sistema de ficheros nativo.


Canales simples de I/O.

Lo siguiente es una introducción a las clases no abstractas
que descienden directamente desde InputStream y OutputStream:

FileInputStream y FileOutputStream.
Leen o escriben datos en un fichero del sistema de ficheros
nativo.l

PipedInputStream y PipedOutputStream.
Implementan los componentes de entrada y salida de una
tubería. Las tuberías se utilizan para canalizar la salida
|n programa hacia la entrada de otro. Un PipedInputStream
debe ser conectado a un PipedOutputStream y un
PipedOutputStream debe ser conectado a un PipedInputStream.

ByteArrayInputStream y ByteArrayOutputStream.
Leen o escriben datos en un array de la memoria.

SequenceInputStream.
Concatena varios canales de entrada dentro de un solo canal
de entrada.

StringBufferInputStream.
Permite a los programas leer desde un StringBuffer como si
fuera un canal de entrada.
Introducción a los Canales de I/O. El paquete java.io contiene dos clases, InputStream y OutputStream, de las que derivan la mayoría de las clases de este paquete. La clase InputStream es una superclase abstracta que proporciona un interface de programación mínimo y una implementación parcial del canal de entrada. La clase InputStream define métodos para leer bytes o arrays de bytes, marcar posiciones en el canal, saltar bytes de la entrada, conocer el número de bytes disponibles para ser leídos, y resetear la posición actual dentro del canal. Un canal de entrada se abre automáticamente cuando se crea. Se puede cerrar un canal explícitamente con el método close(), o puede dejarse que se cierre implícitamente cuando se recolecta la basura, lo que ocurre cuando el objeto deja de referenciarse. La clase Outputstream es una superclase abstracta que proporciona un interface de programación mínimo y una implementación parcial de los canales de salida. Un canal de salida se abre automáticamente cuando se crea. Se puede cerrar un canal explícitamente con el método close(), o se puede dejar que se cierre implícitamente cuando se recolecta la basura, lo que ocurre cuando el objeto deja de referenciarse. El paquete java.io contiene muchas subclases de InputStream y OutputStream que implementan funciones específicas de entrada y salida. Por ejemplo, FileInputStream y FileOutputStream son canales de entrada y salida que operan con ficheros en el sistema de ficheros nativo. Canales simples de I/O. Lo siguiente es una introducción a las clases no abstractas que descienden directamente desde InputStream y OutputStream: FileInputStream y FileOutputStream. Leen o escriben datos en un fichero del sistema de ficheros nativo.l PipedInputStream y PipedOutputStream. Implementan los componentes de entrada y salida de una tubería. Las tuberías se utilizan para canalizar la salida |n programa hacia la entrada de otro. Un PipedInputStream debe ser conectado a un PipedOutputStream y un PipedOutputStream debe ser conectado a un PipedInputStream. ByteArrayInputStream y ByteArrayOutputStream. Leen o escriben datos en un array de la memoria. SequenceInputStream. Concatena varios canales de entrada dentro de un solo canal de entrada. StringBufferInputStream. Permite a los programas leer desde un StringBuffer como si fuera un canal de entrada. Canales Filtrados. FilterInputStream y FilterOutputStream son subclases de InputStream y OutputStream respectivamente, y también son clases abstractas. Estas clases definen el interface para los canales filtrados que procesan los datos que están siendo leídos o escritos. Por ejemplo, los canales filtrados BufferedInputStream y BufferedOutputStream almacenan datos mientras los leen o escriben para aumentar su velocidad. DataInputStream y DataOutputStream Lee o escribe datos primitivos de Java en una máquina independiente del formato. BufferedInputStream y BufferedOutputStream Almacena datos mientras los lee o escribe para reducir el número de accesos requeridos a la fuente original. Los canales con buffer son más eficientes que los canales similares sin buffer. LineNumberInputStream Tiene en cuenta los números de línea mientras lee. PushbackInputStream Un canal de entrada con un buffer de un byte hacia atrás. Algunas veces cuando se leen bytes desde un canal es útil chequear el siguiente carácter para poder decir lo que hacer luego. Si se chequea un carácter del canal, se necesitará volver a ponerlo en su sitio para que pueda ser leído y procesado normalmente. PrintStream Un canal de salida con los métodos de impresión convenientes. Además de las clases streams, el paquete java.io contiene estas otras clases: File Representa un fichero en el sistema de ficheros nativo. Se puede crear un objeto File para un fichero en el sistema de ficheros nativo y luego pedirle al objeto la información que se necesite sobre el fichero(como su path completo). FileDescriptor Representa un manejador de fichero (o descriptor) para abrir un fichero o una conexión. RandomAccessFile Representa un fichero de acceso aleatorio. StreamTokenizer Divide el contenido de un canal en Token(partes). Los Tokens son la unidad más pequeña reconocida por el algoritmo de análisis de texto(como son palabras, símbolos, etc...). Un objeto StreamTokenize puede ser utilizado para analizar cualquier fichero de texto. Por ejemplo, podrías utilizarlo para dividir un fichero fuente de Java en nombres de variables, etc... o un fichero HTML en etiquetas de HTML. Y finalmente el paquete java.io define tres interfaces: DataInput y DataOutput Estos dos interfaces describen canales que pueden leer o escribir datos de tipos primitivos de Java en máquinas independientes del formato. DataInputStream, DataOutputStream y RandomAccessFile implementan estos interfaces. FilenameFilter El método list() de la clase File utiliza un objeto FilenameFilter para determinar los ficheros a listar en un directorio. Este interface acepta ficheros basándose en sus nombres. Se podría utilizar FileNameFilter para implementar una sencilla expresión de búsqueda al estilo de los comodines como fichero.*, etc.... Utilizar ficheros de acceso aleatorio. La clase RandomAccessFile implementa los interfaces DataInput y DataOutput y por lo tanto puede utilizarse tanto para leer como para escribir. RandomAccessFile es similar a FileInputStream y FileOutputStream en que se especifica un fichero del sistema de ficheros nativo para abrirlo cuando se crea. Se puede hacer esto con un nombre de fichero o un objeto File. Cuando se crea un RandomAccessFile se debe indicar si solo se va a leer el fichero o también se va a escribir en él. La siguiente línea de código java crea un RandomAccessFile para leer el fichero llamado farrago.txt: new RandomAccessFile("farrago.txt", "r"); Y esta otra abre el mismo fichero para leer y escribir: new RandomAccessFile("farrago.txt", "rw"); Después de haber abierto el fichero, se pueden utilizar los métodos comunes readXXX() o writeXXX() par arealizar la I/O sobre el fichero. RandomAccessFile soporta la noción de puntero de fichero. El puntero de fichero indica la posición acutal dentro del fichero. Cuando el fichero se crea por primera vez, el puntero de fichero es cero, indicando el principio del fichero. Las llamadas a los métodos readXXX() y writeXXX() ajustan el puntero de fichero el número de bytes leidos o escritos. Además de los métodos normales de I/O que mueven implícitamente el puntero de fichero cuanod ocurre una operación, RandomAccessfile contiene tres métodos que manipulan explícitamente el puntero de fichero. skipBytes() Mueve el puntero de fichero hacia delante el número de bytes especificado. seek() Posiciona el puntero de fichero justo en el byte especificado. GetFilePointer() Devuelve la posición actual del puntero de fichero. Interface Definición: Un interface es una colección de definiciones de métodos (sin implementaciones) y de valores constantes. Los interfaces se utilizan para definir un protocolo de comportamiento que puede ser implementado por cualquier clase del árbol de clases. Los interfaces son útiles para: * Capturar similitudes entre clases no relacionadas sin forzar una relación entre ellas. * Declarar métodos que una o varias clases necesitan implementar. * Revelar el interface de programación de un objeto sin recelar sus clases (los objetos de este tipo son llamados objetos anónimos y pueden ser útiles cuando compartas un paquete de clases con otros desarrolladores). En java, un interface es un tipo de dato de referencia, y por tanto, puede utilizarse en muchos de los sitios donde se pueda utilizar cualquier tipo (como en un argumento de métodos y una declaración de variables). Definir un Interface. Para crear un Interface se debe escribir tanto la declaración como el cuerpo del interface: declaraciondeInterface{ cuerpodeInterface } La declaración de interface declara varios atributos del interface, como su nombre o si se extiende desde otro interface. El cuerpo de interface contiene las constantes y las declaraciones de métodos del Interface. La declaración de interface. Como mínimo, una declaración de interface contiene la palabra clave interface y el nombre del interface que se va a crear: interface Contable{ ... } Nota: Por convención, los nombres de interfaces empiezan con una letra mayúscula al igual que las clases. Frecuentemente los nombres de interfaces terminan en "able" o "ible". Una declaración de interface puede tener otros dos componenetes: el especificador de acceso public y una lista de "superinterfaces". Un interface puede extender otros interfaces como una clase puede extender o subclasificar otra clase. Sin embargo, mientras que una clase sólo puede extender una superclase, los interfaces pueden extender de cualquier número de interfaces. Así, nua declaración completa de interface se parecería a esto: [public] interface Nombredeinterface [extends listadeSuperInterfaces]{ ... } El especificador de acceso public indica que el interface puede ser utilizado por todas las clases en cualquier paquete. Si el interface no se especifica como público, sólo será accesible para las clases definidas en el mismo paquete que el interface. La claúsula extends es similar a la utilizada en la declaración de una clase, sin embargo, un interface puede extender varios interfaces(mientras una clase sólo puede extender una), y un interface no puede extender clases. Esta lista de superinterfaces es una lista delimintada por comas de todos los interfaces extendidos por el nuevo interface. Un interface hereda todas las constantes y métodos de sus superinterfaces a menos que el interface oculte una constante con el mismo nombre o redeclare un método con una nueva declaración. El cuerpo de interface. El cuerpo del interface contiene las declaraciones de métodos para los métodos definidos en el interface, además de las declaraciones de los métodos, una interface puede contener declaraciones de constantes. Nota: Las declaraciones de miembros en un interface no permiten el uso de algunos modificadores y desaconsejan el uso de otros. No se podrán utilizar transient, volatile, o synchronized en una declaración de miembro en un interface. Tampoco se podrá utilizar los especificadores private y protected cuando se declaren miembros de un interface. Todos los valores constantes definidos en un interface son implícitamente públicos, estáticos y finales. El uso de estos modificadores en una declaración de constante en un interface está desaconsejado por falta de estilo. Similarmente, todos los métodos declarados en un interface son implícitamente públicos y abstractos. Este código define un nuevo interface llamado colección que contiene un valor constante y tres declaraciones de métodos: interface colección{ int MAXIMO = 500; void añadir(Object obj); void borrar(Object obj); Object buscar(Object obj); Int contadorActual(); } El interface anterior puede ser implementado por cualquier clase que reperesente una colección de obejtos como pueden ser pilas, vectores, enlaces, etc... Observa que cada declaración de método está seguida por un punto y coma (;) porque un interface no proporciona implementación para los métodos declarados dentro de él. Implementar un Interface. Para utilizar un interface se debe escribir una clase que lo mplemente. Una clase declara todos los interfaces que implementa en su declaración de la clase. Para declarar que una clase implementa uo o más interfaces, se utiliza la palabra clave implementes seguida por una lista delimitada por comas con los interfaces implementados por la clase. Por ejemplo, consideremos el interface colección presentado en la página anterior. Ahoraa supongamos qu queremos escribir una clase que implemente una pila FIFO (primero en entrar, primero en salir). Como una ppila FIFO contiene otros objetos tiene sentido que implemente el interface colección. La clase PilaFIFO declara que implementa el interface colección de esta forma: class PilaFIFO implements coleccion{ ... void añadir(Object obj){ ... } void borrar(Object obj){ ... } Object buscar(Object obj){ ... } Int contadorActual(){ ... } } así se garantiza que proporciona implementación para los métodos añadir(), borrar(), buscar() y contadorActual(). Por convención, la clausula implements sigue a la clausula extends si es que ésta existe. Observa que las firmas de los métodos del interface colección implementados en la clase PilaFIFO debe corresponder exactamente con las firmas de los métodos declarados en la interface colección. Utilizar un interface como un tipo. Como se mencionó anteriormente, cuando se define un nuevo interface, en esencia se está definiendo un tipo de referencia. Se pueden utilizar los nombres de interface en cualquier lugar donde se usaría un nombre de dato de tipos primitivos o un nombre de datos del tipo de referencia. Por ejemplo, supongamos que se ha escrito un programa de hoja de cálculo que contiene un conjunto tabular de celdas y cada una contiene un valor. Querríamos poder poner cadenas, fechas, enteros, ecuaciones, en cada una de las celdas de la hoja. Para hacer esto, las cadenas, las fechas, los enteros y las ecuaciones tienen que implementar el mismo conjunto de métodos. Una forma de conseguir esto es encontrar el ancestro común de las clases e implementar ahi los métodos necesarios. Sin embargo, esto no es una solución práctica porque el ancestro común más frecuente es Object. Una aproximación podría ser escribir una clase llamada ValordeCelda que representara los valores que pudiera contener una celda de la hoja de cálculo. Entonces se podrían crear distintas subclases de ValordeCelda para las cadenas, los enteros o las ecuaciones.