Sunteți pe pagina 1din 14

Llamar desde una clase java a otra clase

Contenido
[ocultar]

1 La clase A instancia a la clase B 2 Pasar la clase B a la clase A desde el exterior. Inversin de control 3 Uso de interfaces 4 Complicando el asunto 5 Localizador de servicios 6 Inversin de control o localizador de servicios?

Una de las dudas bsicas de los principiantes en java es cmo llamar a mtodos o acceder a atributos de una clase java desde otra clase. Veamos aqu varias opciones.

La clase A instancia a la clase B


Si desde una clase A queremos llamar a mtodos de una clase B, lo ms inmediato es que la clase A haga el new de la clase B y la utilice. Por ejemplo, si la clase B es public class B { public void unMetodoDeB() { System.out.println("soy B"); } }

La clase A slo tendra que hacer algo como esto public class A { public void unMetodoDeA() { B b = new B(); b.unMetodoDeB(); } }

Por supuesto, vale cualquier variante, hacer el new de B en el constructor y guardrselo para usarlo luego o lo que queramos public class A { private B b = new B(); public void unMetodoDeA() { b.unMetodoDeB(); } }

Pasar la clase B a la clase A desde el exterior. Inversin de control


El mtodo anterior no siempre puede ser vlido. A veces en el main o en otro sitio hacemos los new de las clases A y B y no nos interesa que A haga otro new de B. Para estos casos, la solucin es pasarle a A, bien en el constructor, bien en un mtodo hecho con tal fin, la clase B para que pueda usarla. El cdigo de A podra ser cualquiera de los dos siguientes public class A { private B b; public A(B b){ this.b = b; } public void unMetodoDeA() { b.unMetodoDeB(); } } public class A { private B b; public void setB(B b) { this.b = b; } public void unMetodoDeA() { b.unMetodoDeB(); } }

Y en el sitio donde hagamos los new, haramos una de las siguientes cosas B b = new B(); A a = new A(b); a.unMetodoDeA(); B b = new B();

A a = new A(); a.setB(b); a.unMetodoDeA();

Esto se conoce como "inversin de control" o "IoC". La clase A, en vez de hacer el new, espera que alguien lo haga por ella y se lo pase.

Uso de interfaces
Con el procedimiento anterior, pasar la clase B a la clase A, suelen usarse interfaces, aunque no es necesario. La idea es que B implemente una InterfazB y que A espere recibir esa interfaz, tal que as public interface InterfazB { public void unMetodoDeB(); } public class B implements InterfazB { @Override public void unMetodoDeB() { System.out.println("Soy B"); } } public class A { private InterfazB b; public A (InterfazB b) { this.b = b; } public void unMetodoDeA() { b.unMetodoDeB(); } }

Las ventajas del uso de interface en vez de pasar directamente la clase B son principalmente dos. Imagina que la clase A es el algoritmo de un juego maravilloso que acabas de hacer y que la clase B es la interfaz grfica de usuario. Cuando A llama a b.unMetodoDeB() en realidad le est diciendo a la interfaz de usuario que dibuje un movimiento que nuestro algoritmo de juego acaba de decidir. Imagina ahora que tienes otro proyecto en el que el juego es el mismo, pero esta vez el juego es en web y la interfaz de usuario B no te sirve para nada, tienes que hacer otra interfaz web y adems, como tu algoritmo A va a estar en el servidor, la interfaz web se ejecuta en los navegadores del cliente.

La primera ventaja del uso de interfaces es la siguiente: Si no usamos interfaz y A usa directamente a B, en nuestro nuevo proyecto tendramos que llevarnos tanto la clase A como la clase B, aunque esta ltima no nos sirva de nada. Nuestro servidor tendr que cargar intilmente con toda la interfaz grfica de usuario, o bien tendremos que modificar el cdigo de la clase A para que no haga uso de esta clase B. Si usamos una interfaz, entonces nuestro servidor podra tener solo la clase A y la InterfazB, mucho ms ligera que la clase B completa. Adems, nuestra clase A podra ser un poco lista y hacer algo como public class A { private InterfazB b = null; public void setB (InterfazB b) { this.b = b; } public void unMetodoDeA() { if ( null != b) { b.unMetododDeB(); } } }

es decir, A es lo suficientemente lista como para llamar a b slo si se la han pasado previamente. As no tenemos que tocar nada en A para llevrnosla a nuestro nuevo juego en web. La segunda ventaja es la siguiente: En nuestro juego en web, posiblemente cuando A decida hacer una jugada tendr que llamar a alguiente para que la pinte, pero en este caso quizs sea enviar ese movimiento por un socket o una conexin en vez de llamar directamente a la interfaz grfica de usuario B. Al haber hecho la interface, en nuestro nuevo juego podemos hacer una clase Conexion encargada de enviar los movimientos decididos por A a la pgina web que est visualizando el cliente. Slo tendremos que hacer que nuestra nueva clase Conexion implemente InterfazB y podremos usarla exactamente igual que usamos antes la clase B, sin necesidad de tocar para nada A. public class Conexion implements InterfazB { @Override public void unMetodoDeB() { System.out.println("Te he engaado, no soy B, soy la nueva clase Conexion"); } } Conexion c = new Conexion(); A a = new A(c);

a.unMetodoDeA();

Resumiendo, las dos ventajas del uso de interfaces son: Nuestra clase es ms reutilizable, podemos llevarla a otros proyectos sin necesidad de llevarnos muchas ms clases. Nuestra clase puede cambiar su comportamiento, llamando a futuras clases que hagamos simplemente implementando la interfaz.

Complicando el asunto
El ejemplo que hemos hecho de A y B es bastante simple en el sentido de que hay un trozo de cdigo que hace new de A y de B y luego pasa B a A. Pero en un programa ms complejo, esto puede liarse. Imagina que tenemos una clase AA que es la que hace el new de A y otra clase BB que es la que hace el new de B y seguimos necesitando que A pueda llamar a mtodos de B. El procedimiento que debemos seguir es el mismo, pero tenemos que poner mtodos setB() y getB() por doquier, de forma que donde se haga el new de AA y de BB se pueda obtener B y pasrselo a A. El cdigo puede ser as Por un lado, AA debe tener un setB() que le pasa B a A. public class AA { private A a = new A(); public void setB (InterfazB b) { a.setB(b); } }

Por otro lado, BB debe tener un mtodo getB() que nos permita obtener B public class BB { private InterfazB b = new B(); public InterfazB getB() { return b; } }

Y nuestro main() hara algo como esto AA aa = new AA(); BB bb = new BB();

aa.setB(bb.getB());

Localizador de servicios
El tema puede complicarse mucho, puede haber muchas ms clases que debamos pasar de un lado a otro, no solo B. Y puede haber muchos niveles de clases, como AAAA que hace new de AAA que a su vez hace new de AA y a su vez de A, por lo que el trasiego de getB() y setB() puede crecer mucho. Cuando una clase B se va a usar en muchos sitios y queremos evitar todo el "folln" de andar poniendo getters y setters en las clases, hay otra alternativa que es usar lo que se conoce como un localizador de servicios. En realidad, hay muchas variantes, como localizador de servicios, singleton, factoras, etc, etc, pero la idea bsica de todos estos mecanismos es la misma y vamos a explicar cmo. La idea es tener una clase, llamemosla Servicio, que sea la que tenga la instancia de B y un mtodo para obtenerla. Como queremos poder llamar a esta clase en cualquier sitio, tanto la instancia de B como el mtodo deben ser estticos. Algo as public class Servicio { private static InterfazB b = new B(); public static InterfazB getB() { return b; } }

Listo,al ser static, podemos llamarla desde cualquier lado de nuestro cdigo haciendo esto public class A { public void unMetodoDeA() { Servicio.getB().unMetodoDeB(); } }

Este mecanismo es muy til cuando la clase B es algo que se va a usar en muchos sitios de nuestro programa, como una clase de acceso a base de datos, a sockets, etc. La "pega" tal cual lo hemos hecho es que si queremos reutilizar A en otro cdigo, tenemos que llevarnos la clase Servicio y para llevarnos esta, tenemos que llevarnos tambin la clase B, aunque

estemos usando la Interfaz, por qu? porque la clase Servicio est haciendo directamente un new de B y por tanto, sin B, no funciona. Para evitar esto, debemos evitar que Servicio haga el new directamente, as que le ponemos un mtodo set, tal que asi public class Servicio { private static InterfazB b; public static setB(InterfazB b) { this.b = b; } public static InterfazB getB() { return b; } }

Y en nuestro main tendremos que hacer esto Servicio.setB (new B()); A a = new A(); a.unMetodoDeA();

Ya hemos conseguido lo que queramos, podemos llevarnos A, Servicio e InterfazB a cualquier otro proyecto sin necesidad de llevarnos la clase B que ha dejado de sernos til. Tambin, en el nuevo proyecto del juego web que comentbamos antes, podramos pasar a Servicio la clase Conexion en lugar de pasarle la clase B. Servicio.setB (new Conexion()); A a = new A(); a.unMetodoDeA();

Comentbamos antes que haba varias variantes de esta opcin: localizador de servicios, factoras, singleton, etc. La diferencia bsica entre todas ellas es bsicamente dnde se hace el new de la clase B y si siempre se devuelve la misma instancia de B o se devuelven instancias distintas cada vez que se llama a Servicio.getB(). La versin de Servicio que acabamos de ver es un "localizador de servicios". Los servicios (la clase B) se "registran" en algn momento (Servicio.setB(new B());) y a partir de ah se pueden usar en cualquier sitio (Servicio.getB().unMetodoDeB();)

Inversin de control o localizador de servicios?

Cual es mejor? Por supuesto, va en cuestin de gustos. Lo habitual es que cuando una clase se va a usar en muchos sitios y se quiera que sea siempre la misma instancia, por ejemplo, conexiones a base de datos, sockets de comunicaciones, etc, se use un servicio. Por otro lado, si la clase B fuese una clase un tanto especial que solo se va a usar en un sitio o dos, o queremos que haya muchas instancias de B circulando por ah, como por ejemplo un panel de una interfaz de usuario con una tabla de ventas, una caja de texto que pide valores numricos, etc, entonces se usara inversin de control, es decir, pasarle a las clase A de nuestro cdigo a travs de setter sobre qu clases B en concreto tendran que actuar. Pero como siempre, es mejor usar la cabeza que seguir recetas al pie de la letra. El uso de uno u otro mecanismo depende de cada caso concreto y de los posibles cambios y posibilidades de reutilizacin que preveamos en nuestro cdigo. Si no prevemos que la clase A se vaya a reutilizar nunca, podemos obviar el uso de InterfazB y hacer que vea directamente a B, el cdigo queda ms sencillo y no lo complicamos para algo que nunca vamos a usar. Un localizador de servicios aade una complejidad adicional, es una clase ms (Servicio) que necesita ser inicializada en nuestro main() ( Servicio.setB(new B)); ) y que nunca sabemos dnde se va a usar (clase A, otra clase C, otra clase D, ...), por lo que es bastante frecuente llevarse esas clase A,C,D a otros proyectos ... y olvidarse de registrar los servicios que necesitan. As que debemos evaluar si esa complejidad adicional compensa los setters y getters que eliminamos al no usar la inversin de control.

OTRA VERSION

Nombre de usuario: * Contrasea: *


Iniciar sesin

Crear cuenta nueva

Solicitar nueva contrasea

Navegacin
o
Blogs Categorias Contenido Foros de Discusin Encuestas Tips Usuarios Envos recientes

Temas nuevos

Exportar e importar a excel Como persistir una entidad que tiene asociacion con otras mediante una Lista con JPA Formato de un string more

En lnea
En este momento hay 0 usuarios y 103 invitados en lnea.

Comentarios recientes

jajaja y si tenias razon en mis variables respuesta hace 8 horas 56 mins Ya lo resolvi hace 9 horas 2 mins Lo que pasa es que ah inclu hace 13 horas 3 mins Si, es todo el proyecto slo hace 13 horas 11 mins Lo puedes pegar en otro lado hace 13 horas 30 mins La parte que es distinta es hace 14 horas 24 mins Por si les sirve hace 14 horas 31 mins Para que entiendas el hace 16 horas 2 mins Asociar la pregunta la pregunta a la respuesta hace 16 horas 3 mins Ok, pero entendiste que tu hace 16 horas 9 mins

Encuesta
Qu lenguaje alternativo para la JVM te llama ms la atencin?: Groovy Scala Clojure JRuby Jython Otro... (menciona cul)
Votar

Contenido popular
Hoy:

Preprocesadores para desarrollar las pginas Web y PreprocessJS ISO-8583 en Java Estructura de datos java (Listas simplemente enlazadas) Primer aporte Exportar e importar a excel Java para principiantes (Ambito o alcance de las variables en Java)

Siempre:

Como programar en java Deitel & Deitel 7ma Edicion Estructura de datos java (Listas simplemente enlazadas) Primer aporte Cargar una imagen en un JPanel en netbeans como generar un archivo txt en java Interfaz grafica para programa de gestion en java

ltimas impresiones:

problema con aplicacin: funciona en Netbeans pero al ejecutar el JAR independientemente se queda colgado archivos directos Hibernate, cache, carga de datos en tiempo real. Conexion JSP con SQLServer 2008 y Netbeans

Encriptacion con Open SSL

Agradecemos el apoyo de:

llamar a un metodo que esta en una clase hacia otra clase


Submitted by junior0941 on Mar, 12/07/2010 - 08:47

Java Standard Edition


estoy trabajando en net beans 6.9.1, con el libro COMO PROGRAMAR EN JAVA 7 DE deitel &deitel: y estoy teniendo problemas con lo siguiente: tengo dos proyectos por separado 1-el primero crea el siguiente metodo: public class Libro { public void mostrarMensaje() { System.out.println("Bienvenido al Libro de Calificaciones !"); } } 2- el segundo quiere llamar al metodo de la parte de arriba haciendo lo siguiente: public class Main { public class pruebalibro { public static void main(String[] args) { Libro miLibro = new Libro(); ----------------- crea una instancia del objeto Libro.mostrarMensaje(); aqui quiero llamar al metodo QUE DEBO HACER PARA SOLUCIONARLO? EL CODIGO DEL "LIBRO" ESTA MAL? ESPERO ME PUEDAN AYUDAR con este problema GRACIAS DE ANTEMANO. Hola Tengo una duda?Adjuntar Base de Datos a aplicacin Java para convertirla en EXE

Opciones de visualizacin de comentarios


Lista plana: expandida

Fecha: primero los ms antiguos

50 comentarios por pgina

Guardar las opciones

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en Guardar las opciones para activar los cambios.

Prueba llamando al metodo de


Submitted by javadicto on Mar, 12/07/2010 - 14:00.

Prueba llamando al metodo de esta manera: miLibro.mostrarMensaje();

como lo dice javadicto} el


Submitted by beckveg on Mar, 12/07/2010 - 18:07.

como lo dice javadicto el cdigo correcto seria public class Main { public class pruebalibro { public static void main(String[] args) { Libro miLibro = new Libro(); ----------------- crea una instancia del objeto miLibro.mostrarMensaje(); } }

RTFS
Submitted by Gustavo on Mar, 12/07/2010 - 18:22.

Te dejo un post muy constructivo de aqui mismo link

no puedo usar el metodo


Submitted by junior0941 on Mi, 12/08/2010 - 11:08.

public static void main(String[] args) -------------inner classes cannot have static declarations { Libro Libro1 = new Libro(); -------------------- LA PALABRA Libro SIGUE SALIENDO SUBRAYADO EN ROJO Libro1.mostrarMensaje(); ------------- AQUI EL METODO MOSTRAR MENSAJE SIGUE SALIENDO SUBRAYADO EN ROJO CREATE class "libro" en package pruebalibro CREATE class "libro" en pruebalibro.Main

La clase main
Submitted by francisco.santiagoj on Mi, 12/08/2010 - 13:20.

Hola @junior0941, tu clase Main debe estar de esta forma para que pueda llamar al mtodo de otra clase. package paquete1; public class Main { public static void main(String[] args){ Libro libro = new Libro(); libro.mostrarMensaje(); } } recuerda que deben de estar en el mismo paquete La clase Libro: package paquete1; public class Libro { public void mostrarMensaje() { System.out.println("Bienvenido al libro de calificaciones"); } }

llamando al metodo mostrar mensaje


Submitted by junior0941 on Vie, 12/17/2010 - 10:25.

MUCHAS GRACIAS POR TU RESPUESTA, ESPERO K PUEDAS RESPONDER A ESTAS PREGUNTAS PORQUE LAS 2 CLASES DEBEN ESTAR EN EL MISMO PAQUETE? A QUE SE LLAMA VARIABLE DE INSTANCIA Y VARIABLE DE CLASE? PORQUE SALIA ERROR EN EL CODIGO ANTERIOR? CUAL ERA LA CAUSA DEL PROBLEMA? ESPERO QUE ME PUEDAS AYUDAR. SALUDOS DESDE PERU.

Esto me huele a tarea, pero...


Submitted by CharlieCorner on Vie, 12/17/2010 - 14:20.

... Siempre hay que otorgar el beneficio de la duda. Aunque djame decirte que no puedo evitar pensar mal ahora que son pocas de exmenes finales en muchos lugares, ojal no traiciones nuestra confianza... Pasando as a tus preguntas: PORQUE LAS 2 CLASES DEBEN ESTAR EN EL MISMO PAQUETE? No es requisito, aunque para tus ejemplos prcticos ponlos en el mismo, si no lo estuvieran tendras que hacer un import a las clases que vayas a usar (con todo y el paquete definido). Como seguramente te confundirs ahora con paquetes, slo mtelo todo en el mismo. A QUE SE LLAMA VARIABLE DE INSTANCIA Y VARIABLE DE CLASE? La variable de instancia, si programaste alguna vez en C, es el equivalente a una variable global. La variable de instancia define todos los atributos de un objeto (instancia) y generalmente se declaran fuera de cualquier mtodo, dentro de la declaracin de clase y, por cuestiones de seguridad, es recomendable declararlas como private delegando su manejo exclusivamente a los mtodos get y set que para este fin se declaren. PORQUE SALIA ERROR EN EL CODIGO ANTERIOR? CUAL ERA LA CAUSA DEL PROBLEMA? Entramos con otro concepto, el de un elemento static. Bsicamente puedes tener elementos propios a cada uno de los objetos que instancies, pero tambin puedes tener atributos o mtodos que sean comunes a todas las instancias de esa clase. Ahora bien, de la forma que lo mandabas llamar era Clase.metodo() cosa que slo hubiera funcionado si hubieras declarado tu mtodo mostrarMensaje() como static, de manera que, como es comn a todos los objetos de esa clase, no es, por definicin, necesario crear un objeto para accesar a ese mtodo. Si no te me has perdido hasta aqu, vamos bien. Te comentaban que crearas un objeto de la clase Libro() porque tu mtodo mostrarMensaje() no es esttico, es decir, es independiente para cada una de las instancias que de esa clase se creen. De modo que su llamaba slo ser exitosa si y slo si creas una instancia y luego mandas llamar el mtodo mostrarMensaje() de la misma. Objeto.metodo(). Revisa que hayas copiado correctamente el cdigo del libro. Estoy casi seguro que por ah te equivocaste en algo, sino, proporcioname la pgina y lo reviso en el mo para una ayuda ms certera. Espero haberme explicado bien, trat de digerirlo lo ms posible para explicrtelo lo ms sencillo posible, si no, cualquier duda, hznosla saber.

el error era por que tus


Submitted by freddyrrc on Mar, 08/21/2012 - 17:02.

el error era por que tus clases estaban en diferentes paquetes . y la solucion a eso era hacer un import . en la clase main donbe llamas al metodo mostrar mensaje hacer esto import nombredelpaquetequecontieneelmetodomostrarmensaje .*; nada mas eso es todo y listo.

S-ar putea să vă placă și