Posteado por: albalba | Marzo 12, 2008

Practica 3 (Continuacion)

Continuamos con la práctica por el ejercicio 1, en el que nos quedamos, ya fuera de clase. Como no sabíamos por donde empezar pedimos una tutoría y ya en ella por fin vimos la luz, era más sencillo de lo que parecía. Lo vamos a intentar explicar lo mejor posible. Se trata de hacer una clase para cada parte de una clase, es decir, una clase atributo, una clase constructor, una clase métodos,… y utilizar estas clases para crear una clase Clase a partir de ellas. Se puede pensar como un puzzle, en el que tienes una pieza atributo, la pieza métodos,… y al unir todas las piezas formas el puzzle completo, la clase Clase.

Leímos el enunciado. Para hacer este ejercicio seguimos los principios fundamentales de la programación orientada a objetos que son: la abstracción y la encapsulación, las cuales definimos a continuación. Ambas han sido extraídas de la fuente Wikipedia:

   Abstracción: Abstracción consiste en aislar un elemento de su contexto o del resto de los elementos que lo acompañan. En programación, el término se refiere al énfasis en el “¿qué hace?” más que en el “¿cómo lo hace?” (característica de caja negra). El común denominador en la evolución de los lenguajes de programación, desde los clásicos o imperativos hasta los orientados a objetos, ha sido el nivel de abstracción del que cada uno de ellos hace uso.”·     

   Encapsulación: “En informática, se conoce como principio de ocultación de información a la ocultación de decisiones de diseño en un programa susceptible de cambios con la idea de proteger a otras partes del código si éstos se producen. Proteger una decisión de diseño supone proporcionar una interfaz estable que proteja el resto del programa de la implementación (susceptible de cambios). En los lenguajes de programación modernos el principio de ocultación de información se manifiesta de diferentes maneras, como por ejemplo la encapsulación.” Con estos dos conceptos claros resulta más sencillo empezar con el ejercicio 1 analizamos la clase Modificador que tiene como cuerpo: 

// NOTA: Estos imports son SOLO necesarios para los metodos que que YA ESTÁN IMPLEMENTADOS.
ÏÏÏimport java.lang.reflect.Modifier;/**
 *  Clase Modificador.
 *
 * @author DIT-UC3M
 */
ÏÕÖ×public class Modificador {
Ïϧ
ÏϧÏíÏpublic static final int PUBLIC = 1;
ÏϧÏíÏpublic static final int PRIVATE = 2;
ÏϧÏíÏpublic static final int PROTECTED = 4;
ÏϧÏíÏpublic static final int STATIC = 8;
ÏϧÏíÏpublic static final int FINAL = 16;
ÏϧÏíÏpublic static final int SYNCHRONIZED = 32;
ÏϧÏíÏpublic static final int VOLATILE = 64;
ÏϧÏíÏpublic static final int TRANSIENT = 128;
ÏϧÏíÏpublic static final int NATIVE = 256;
ÏϧÏíÏpublic static final int INTERFACE = 512;
ÏϧÏíÏpublic static final int ABSTRACT = 1024;
ÏϧÏíÏpublic static final int STRICT = 2048;
Ïϧ
ÏϧÏÞßàpublic static String toString( int modificador ) {
ÏϧÏϧ// ESTE MÉTODO YA ESTÁ IMPLEMENTADO.
Ïϧ¹Ĺ¹Ïreturn Modifier.toString( modificador );
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic static void main( String args[] ) {
ÏϧÏϧ// ESTE MÉTODO YA ESTÁ IMPLEMENTADO.
ÏϧÏϨ¹íÏint modificador = Integer.parseInt(args[0]);
ÏϧÏϧ
ÏϧÏϨ¹¹ÏSystem.out.println(” El modificador de acceso de “ + modificador  +” es “+ Modificador.toString(modificador) );
ÏϧÏϧ
ÏϧÏÏ©}
Ïϧ
ÏÏ©}

Lo que nos llamó la atención fue la clase Modifier, la cual llama a su método toString(), entonces recurrimos al API de Java en la que se define la clase Modifier de la siguiente manera:  

public class Modifier extends ObjectThe Modifier class provides static methods and constants to decode class and member access modifiers. The sets of modifiers are represented as integers with distinct bit positions representing different modifiers. The values for the constants representing the modifiers are taken from The JavaTM Virtual Machine Specification, Second edition tables 4.1, 4.4, 4.5, and 4.7.

Según lo que interpretamos la clase Modifier sirve para saber el tipo de modificador de acceso según el argumento que reciba.Compilando y ejecutando la clase Modificador, el resultado es el siguiente:

modificador.jpg

A continuación programamos una clase ModificadorPrueba cuyo método “main” imprima por pantalla todos los posibles valores de salida del método toString() de la clase Modificador, quedándonos así:

ÏÕÖ×public class ModificadorPrueba
Ïϧ
Ïϧ{
ÏϧÏÞßàpublic static void main(String[] args)
ÏϧÏϧ{
ÏϧÏϨ¹íÏint indice=1;
ÏϧÏϨ¹¹±while(indice<2048)
ÏϧÏϧÏÏ5{
ÏϧÏϧÏÏ7¹íÏModificador imprime=new Modificador();
ÏϧÏϧÏÏ7¹¹ÏSystem.out.println(imprime.toString(indice));
ÏϧÏϧÏÏ7¹¹Ïindice*=2;
ÏϧÏϧÏϰ}
ÏϧÏϧ
ÏϧÏÏ©}
ÏÏ©}

El resultado de la ejecución es el siguiente:

modificadorprueba.jpg

Después nos planteamos ¿qué pasaría si al método toString() le pasamos un argumento mayor que el numero de combinaciones de los modificadores de acceso?, la única manera de averiguarlo era ejecutando el programa con distintos valores. Este fue el resultado:

Entonces llegamos a una conclusión “Hay que pensar en binario”, el por qué se explica con ayuda de la siguiente tabla.

0 (no tiene modificador)
1 PUBLIC
2 PRIVATE
4 PROTECTED
8 STATIC
16 FINAL
32 SYNCHRONIZED
64 VOLATILE
128 TRANSIENT
256 NATIVE
512 INTERFACE
1024 ABSTRACT
2048 STRICT

Si metíamos, por ejemplo el 432, nos percatamos de que tan solo salían por pantalla los modificadores de acceso en los que su número tenía un uno al pasar el 432 de decimal a binario. Pensad que el primer bit corresponde con el número 2048 y así consecutivamente hasta que el último corresponde al 1, por eso el valor 0 no imprime nada ya que no tiene definido un modificador de acceso. Ejemplos:

680

001010101000

Static Synchcronized Transient Interface

68

000001000100

Protected Volatile

120

000001111000

Static Final Synchronized Volatile

0

000000000000

(no tiene modificador de acceso)

1024

010000000000

Abstract

1021

001111111101

Public Protected Static Final Synchronized Volatile Transient Native Interface

2050

100000000010

Prívate Strict

 Así sería si nos regimos a la cadena de bits, peeeeeeeeero como el método toString() está invocado por la clase Modifier provoca que se siga una jerarquía implicita en esta clase, de aquí el cambio de orden en la ejecución.

En el Ejercicio 2 implementamos la clase atributo rellenando los métodos:

/**
 * Clase Atributo.
 *
 * @author DIT-UC3M
 */
ÏÕÖ×public class Atributo {
Ïϧ
ÏϧÏíÏpublic String  nombre = null;
ÏϧÏíÏpublic String  tipo= null;
ÏϧÏíÏpublic int modificadores = 0;
Ïϧ
Ïϧ /**   Crea una instancia de Atributo   */
ÏϧÏÞßàpublic Atributo(String nombre, String tipo, int modificadores )
ÏϧÏϧ{
ÏϧÏϧ
ÏϧÏϧ
ÏϧÏϨ¹¹Ïthis.nombre=nombre;
ÏϧÏϨ¹¹Ïthis.tipo=tipo;
ÏϧÏϨ¹¹Ïthis.modificadores=modificadores;
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic String toString()
ÏϧÏϧ{
ÏϧÏϨ¹íÏModificador mod=new Modificador();
Ïϧ¹Ĺ¹Ïreturn “ATRIBUTO: NOMBRE= “+nombre+” TIPO= “+tipo+” MODIFICADOR DE ACCESO= “+mod.toString(modificadores);
ÏϧÏÏ©}
ÏÏ©}

Hicimos el correspondiente prueba para la clase atributo comprobando que todo estaba bien:

ÏÕÖ×public class PruebaAtributo
Ïϧ{
ÏϧÏÞßàpublic static void main(String[] args)
ÏϧÏϧ{
ÏϧÏϨ¹íÏAtributo nuevo=new Atributo(“variable”,“int”,1);
ÏϧÏϨ¹¹ÏSystem.out.println(nuevo);
ÏϧÏÏ©}
ÏÏ©}

Apareciendo por pantalla:

pruebaatributo.jpg

Continuamos con el Ejercicio 3 en el que implementamos esta vez las clases Método y Constructor:

/**
 *  Clase Metodo.
 * @author DIT-UC3M
 */
ÏÕÖ×public class Metodo
Ïϧ{
Ïϧ
ÏϧÏíÏpublic String nombre = null;
ÏϧÏíÏpublic int modificadores=0;
ÏϧÏíÏpublic String tipoRetorno = null;
Ïϧ
Ïϧ /** Crea una instancia de Metodo */
ÏϧÏÞßàpublic Metodo(String nombre, int modificadores, String tipoRetorno)
ÏϧÏϧ{
ÏϧÏϨ¹¹Ïthis.nombre=nombre;
ÏϧÏϨ¹¹Ïthis.modificadores=modificadores;
ÏϧÏϨ¹¹Ïthis.tipoRetorno=tipoRetorno; 
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic String toString()
ÏϧÏϧ{
ÏϧÏϨ¹íÏModificador nuevo=new Modificador();
Ïϧ¹Ĺ¹Ïreturn “METODO: NOMBRE= “+nombre+” MODIFICADOR DE ACCESO= “+nuevo.toString(modificadores)+” TIPO RETORNO= “+tipoRetorno;
ÏϧÏÏ©}
ÏÏ©}

  Con su respectivo prueba para la clase método:

ÏÕÖ×public class PruebaMetodo
Ïϧ{
ÏϧÏÞßàpublic static void main (String[] args)
ÏϧÏϧ
ÏϧÏϧ{
ÏϧÏϨ¹íÏMetodo prueba=new Metodo(“prueba”,128,“void”);
ÏϧÏϨ¹¹ÏSystem.out.println(prueba);
ÏϧÏÏ©}
ÏÏ©}

Y aparición por pantalla:

 pruebametodo.jpg

La clase Constructor:

// NOTA: Estos imports son SOLO necesarios para los metodos que que YA ESTÁN IMPLEMENTADOS.
ÏÏÏimport java.lang.reflect.*;/**
 *  Clase Constructor.
 *
 * @author DIT-UC3M
 */
ÏÕÖ×public class Constructor
Ïϧ{
Ïϧ
ÏϧÏíÏpublic String nombre = null;
ÏϧÏíÏpublic int modificadores=0;
Ïϧ
Ïϧ /**   Crea una instancia del objeto Constructor    */
ÏϧÏÞßàpublic Constructor(String nombre, int modificadores)
ÏϧÏϧ{
ÏϧÏϨ¹¹Ïthis.nombre=nombre;
ÏϧÏϨ¹¹Ïthis.modificadores=modificadores;
ÏϧÏϧ    
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic String toString()
ÏϧÏϧ{
ÏϧÏϨ¹íÏModificador acceso=new Modificador();
Ïϧ¹Ĺ¹Ïreturn “CONSTRUCTOR: NOMBRE= “+nombre+” MODIFICADOR ACCESO= “+acceso.toString(modificadores);
ÏϧÏÏ©}
Ïϧ
ÏÏ©}

El prueba de la clase Constructor:

ÏÕÖ×public class PruebaConstructor
Ïϧ{
ÏϧÏÞßàpublic static void main (String[] args)
ÏϧÏϧ{
ÏϧÏϨ¹íÏConstructor prueba=new Constructor(“Prueba”,1);
ÏϧÏϨ¹¹ÏSystem.out.println(prueba);
ÏϧÏÏ©}
ÏÏ©}

Mostrándose por pantalla: 

pruebaconstructor.jpg

A continuación terminamos “el puzzle” implementando la clase Clase, que corresponde al Ejercicio 4:

// NOTA: Estos imports son SOLO necesarios para los metodos que que YA ESTÁN IMPLEMENTADOS.
ÏÏÏimport java.lang.reflect.Field;
ÏÏÏimport java.lang.reflect.Method;/**
 *
 * @author DIT-UC3M
 */
ÏÕÖ×public class Clase
Ïϧ{
Ïϧ
ÏϧÏíÏpublic String nombre;
Ïϧ
ÏϧÏíÏprivate Atributo[] atributos;
ÏϧÏíÏprivate Constructor[] constructores;
ÏϧÏíÏprivate Metodo[] metodos;
Ïϧ
Ïϧ /** Constructor de la clase a partir de un objeto cualquiera. */
ÏϧÏÞßàpublic Clase( Object o)
ÏϧÏϧ{
ÏϧÏϧ// ESTE MÉTODO YA ESTÁ IMPLEMENTADO.      
ÏϧÏϨ¹¹Ïthis.nombre = o.getClass().getName();
ÏϧÏϧ 
ÏϧÏϨ¹íÏint numAtributos = o.getClass().getDeclaredFields().length;
ÏϧÏϨ¹íÏint numConstructores = o.getClass().getConstructors().length;
ÏϧÏϨ¹íÏint numMetodos = o.getClass().getDeclaredMethods().length;       
ÏϧÏϧ 
ÏϧÏϨ¹¹Ïatributos = new Atributo[numAtributos];
ÏϧÏϨ¹¹Ïconstructores = new Constructor[numConstructores];
ÏϧÏϨ¹¹Ïmetodos = new Metodo[numMetodos];
ÏϧÏϧ 
ÏϧÏϨ¹¹±for ( int i=0; i<numAtributos ; i++) {
ÏϧÏϧÏÏ7¹íÏField f = o.getClass().getDeclaredFields()[i];
ÏϧÏϧÏÏ7¹¹Ïatributos[i] = new Atributo(f.getName(),f.getType().getName(),f.getModifiers());
ÏϧÏϧÏϰ}
ÏϧÏϧ 
ÏϧÏϨ¹¹±for ( int i=0; i<numConstructores ; i++) {
ÏϧÏϧÏÏ7¹íÏjava.lang.reflect.Constructor c = o.getClass().getConstructors()[i];
ÏϧÏϧÏÏ7¹¹Ïconstructores[i] = new Constructor(c.getName(),c.getModifiers());
ÏϧÏϧÏϰ}
ÏϧÏϧ 
ÏϧÏϨ¹¹±for ( int i=0; i<numMetodos ; i++) {
ÏϧÏϧÏÏ7¹íÏMethod m =  o.getClass().getDeclaredMethods()[i];
ÏϧÏϧÏÏ7¹¹Ïmetodos[i] = new Metodo(m.getName(), m.getModifiers(),m.getReturnType().getName());
ÏϧÏϧÏϰ}
ÏϧÏϧ
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic Atributo[] getAtributos()
ÏϧÏϧ{
Ïϧ¹Ĺ¹Ïreturn atributos;
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic Constructor[] getConstructores()
ÏϧÏϧ{ 
Ïϧ¹Ĺ¹Ïreturn constructores;
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic Metodo[] getMetodos()
ÏϧÏϧ{
Ïϧ¹Ĺ¹Ïreturn metodos;
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic String toString()
ÏϧÏϧ{
ÏϧÏϨ¹íÏString informacion_clase=nombre;
ÏϧÏϨ¹¹±for(int i=0;i<atributos.length;i++)
ÏϧÏϧÏÏ5{
ÏϧÏϧÏÏ7¹¹Ïinformacion_clase+=“\n”+atributos[i].toString();
ÏϧÏϧÏϰ}
ÏϧÏϧ  
ÏϧÏϨ¹¹±for(int i=0;i<constructores.length;i++)
ÏϧÏϧÏÏ5{
ÏϧÏϧÏÏ7¹¹Ïinformacion_clase+=“\n”+constructores[i].toString();
ÏϧÏϧÏϰ}
ÏϧÏϧ  
ÏϧÏϨ¹¹±for(int i=0;i<metodos.length;i++)
ÏϧÏϧÏÏ5{
ÏϧÏϧÏÏ7¹¹Ïinformacion_clase+=“\n”+metodos[i].toString();
ÏϧÏϧÏϰ}
Ïϧ¹Ĺ¹Ïreturn informacion_clase;
ÏϧÏϧ
ÏϧÏÏ©}
ÏÏ©}

 Después dijimos: “bueno, pues venga, a seguir con el Ejercicio 5, cogiendo aire profundamente para terminar la clase AnalizadorObjeto:

/**
 *  Clase InfoObjeto.
 *
 * @author DIT-UC3M
 */
ÏÕÖ×public class AnalizadorObjeto
Ïϧ{
Ïϧ
ÏϧÏíÏprivate Clase clase;
ÏϧÏíÏpublic String alias = “no tiene”;
ÏϧÏíÏpublic static int contador;
Ïϧ
Ïϧ
Ïϧ /** Crea una instancia de AnalizadorObjeto a partir de un objeto sin alias. */
ÏϧÏÞßàpublic AnalizadorObjeto(Object o)
ÏϧÏϧ{
ÏϧÏϨ¹¹Ïclase=new Clase(o);
ÏϧÏϨ¹¹Ïcontador++;        
ÏϧÏÏ©}
Ïϧ
Ïϧ /** Crea una instancia de AnalizadorObjeto  a partir de un objeto de cualquier clase y con un alias. */
ÏϧÏÞßàpublic AnalizadorObjeto( Object o, String alias )
ÏϧÏϧ{
ÏϧÏϨ¹¹Ïclase=new Clase(o);
ÏϧÏϨ¹¹Ïthis.alias=alias;         
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic Clase getClase()
ÏϧÏϧ{
Ïϧ¹Ĺ¹Ïreturn clase;
ÏϧÏÏ©}
Ïϧ
Ïϧ
ÏϧÏÞßàpublic String toString()
ÏϧÏϧ{
Ïϧ¹Ĺ¹Ïreturn clase.toString();
ÏϧÏÏ©}
Ïϧ
Ïϧ
ÏÏ©}

 Continuamos programando la clase PruebaObjetos del Ejercicio 6 y para poder compilarlo necesitamos las clases ClasePrueba y OtroClasePrueba que nos dan ya hechos: 

/**
 *
 * @author DIT-Uc3M
 */
ÏÕÖ×public class ClasePrueba {
Ïϧ
ÏϧÏíÏpublic String atributoPublico=“publico”;
ÏϧÏíÏprotected int atributoProtegido = 0;
ÏϧÏíÏprivate char atributoPrivado=‘a’;
Ïϧ
ÏϧÏÞßàpublic ClasePrueba() {
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic ClasePrueba( String param1, int param2 ) {
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic void metodoPublico() {
ÏϧÏϧ 
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàprotected void metodoProtegido() {
ÏϧÏϧ 
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàprivate void metodoPrivado() {
ÏϧÏϧ 
ÏϧÏÏ©}
ÏÏ©}

/**
 *
 * @author DIT-Uc3M
 */
ÏÕÖ×public class OtraClasePrueba {
Ïϧ
ÏϧÏíÏpublic String otroAtributoPublico=“publico”;
ÏϧÏíÏprotected char otroAtributoProtegido = ‘b’;
ÏϧÏíÏprivate int otroAtributoPrivao=0;
Ïϧ
ÏϧÏÞßàpublic OtraClasePrueba() {
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic OtraClasePrueba( String param1, int param2 ) {
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàpublic void otroMetodoPublico1() {
ÏϧÏϧ 
ÏϧÏÏ©}
ÏϧÏÞßàpublic void otroMetodoPublico2() {
ÏϧÏϧ 
ÏϧÏÏ©}
Ïϧ    
ÏϧÏÞßàprotected void otroMetodoProtegido1() {
ÏϧÏϧ 
ÏϧÏÏ©}
Ïϧ
ÏϧÏÞßàprivate void otroMetodoPrivado1() {
ÏϧÏϧ 
ÏϧÏÏ©}
ÏÏ©}

De esta manera:

ÏÕÖ×public class PruebaObjetos
Ïϧ{
ÏϧÏÞßàpublic static void main(String[] args)
ÏϧÏϧ{
ÏϧÏϨ¹íÏClasePrueba una=new ClasePrueba();
ÏϧÏϨ¹íÏOtraClasePrueba dos=new OtraClasePrueba();
ÏϧÏϧ  
ÏϧÏϨ¹íÏAnalizadorObjeto uno_=new AnalizadorObjeto(una);
ÏϧÏϨ¹íÏAnalizadorObjeto dos_=new AnalizadorObjeto(dos);
ÏϧÏϧ  
ÏϧÏϨ¹¹ÏSystem.out.println(“\n\n”+uno_);
ÏϧÏϨ¹¹ÏSystem.out.println(“\n\n”+dos_);
ÏϧÏϧ  
ÏϧÏϨ¹¹ÏSystem.out.println(“\n\n————————\nObjetos analizados: “+dos_.contador+“\n————————”);
ÏϧÏϧ  
ÏϧÏϧ  
ÏϧÏÏ©}
ÏÏ©}

Y tras probarlo obtuvimos el fantástico resultado esperado BIEEEEEEN!!!!!!!!!! J

 pruebaobjetos.jpg

Y SE ACABOOOOOOOOOOOOOO!!ESTO ES TO..ESTO ES TO… ESTO ES TODO AMIGOS!

AH! POR CIERTO, SI OS COPIAS CONTENIDO DE ESTE BLOG POR FAVOR PONED DE DONDE OS HABEIS COPIADO, GRACIAS


Respuestas

  1. Hola!!!!
    Nosotras también nos tuvimos que quedar un día después de clase a terminar la práctica ya que tampoco nos dió tiempo, aunque avanzamos un poquito mas que vosotros. Hemos estado viendo los códigos que habeís puesto y coincidimos en todo XD. Nos gusta que pongaís el código ya que si estas un poco perdido es de gran ayuda. Bueno espero que lo sigaís haciendo.
    Y, ánimo que si seguimos haciendo las prácticas semana a semana seguro que aprobamos,jeje.
    Un saludo

  2. Buenass!!
    Me ha gustado mucho el post de esta práctica, la verdad es que no me había metido nunca en vuestro blog y ha habido algunas cosillas que me han ayudado para tener lalgunas cosas un poco mas claras.
    Os voi a hacer una preguntilla sobre el primer ejercicio que aun leyendo vuestro post no se porque es. Esta es mi clase ModificadorPrueba:

    public class ModificadorPrueba{
    public static void main(String[] args){
    int mod=4095;
    System.out.println(Modificador.toString(mod));

    }

    }

    Esta hecha a lo facil :) , pero nose porque cuando le meto un número de bits mayor que la suma de todos los modificadores no me sale nada(imagino que será algo que se defina en la clase Modifier).
    Venga gracias. Un saludo.
    Agur.

  3. [...] No hemos puesto los cuadros de ejecución porque son los mismo que la Practica 3. [...]


Dejar una respuesta

Su respuesta:

Categorías