Pregunta

Estoy tratando de envolver mi mente alrededor de algo en java. Cuando paso un objeto a otro método de clase, ¿no puedo simplemente llamar a algún método inherente a esa clase de objeto?

¿Cuál es el código de razón, como el ejemplo a continuación, no se compila?

Gracias,

class a {
  public static void myMethod(Object myObj) {
    myObj.testing();
  }
}


class b {
  public void testing() {
    System.out.println ("TESTING!!!");
  }
}


class c {  
  public static void main (String[] args) {
    b myB = new b();    
    a.myMethod(myB);  
  }
}

Editar: la razón por la que he dejado el parámetro en mi Método como tipo de Objeto, es porque me gustaría poder pasar una variedad de tipos de objetos, cada uno con un método testing ().

¿Fue útil?

Solución

Si desea pasar una variedad de objetos con los métodos testing () , pida a cada objeto que implemente una interfaz de Probar :

public interface Testable
{
   public void testing()
}

Luego haga que myMethod () tome un Testable .

public static void myMethod(Testable testable)
{
  testable.testing();
}

Editar: para aclarar, implementar una interfaz significa que se garantiza que la clase tiene el método, pero que el método puede hacer lo que quiera. Así que podría tener dos clases cuyos métodos de testing () hacen cosas diferentes.

public class AClass implements Testable
{
   public void testing()
   {
      System.out.println("Hello world");
   }
}

public class BClass implements Testable
{
   public void testing()
   {
      System.out.println("Hello underworld");
   }
}

Otros consejos

El problema es que myMethod no puede saber que está recibiendo un objeto b hasta que realmente se ejecuta. Podría pasar un String , por lo que sabe.

Cambia a

public static void myMethod(b myObj) {
  myObj.testing();
}

y debería funcionar.


Actualización de la pregunta:

  

Editar: la razón por la que he dejado el parámetro en mi Método como tipo de Objeto, es porque me gustaría poder pasar una variedad de tipos de objetos, cada uno con un método testing ().

Como han dicho Amanda S y varios otros, este es un caso perfecto para una interfaz. La forma de hacerlo es crear una interfaz que defina el método testing () y cambiar myMethod para que los objetos implementen esa interfaz.

Una solución alternativa (sin interfaces) sería descubrir de manera reflexiva si el objeto tiene un método de testing () y llamarlo, pero esto no se recomienda y no es necesario para un caso tan simple.

De lo que estás hablando es de escribir pato. Java no tiene escritura de pato.

Por lo tanto, debe definir una interfaz que implementen todas las clases con el método testing () .

por ejemplo:

public interface Testable
{
   public void testing()
}

class B implements Testable 
{
  public void testing() {
    System.out.println ("TESTING!!!");
  }
}

class A {
  public static void myMethod(Testable myObj) {
    myObj.testing();
  }
}

Su problema es un argumento clásico a favor de una interfaz. Desea que sea lo más genérico posible, pero desea que cada objeto que pase tenga un método testing (). Sugiero algo como lo siguiente:

public interface Testable
{
  public void testing();
}

public class A
{
  public static void myMethod(Testable myObj)
  {    
    myObj.testing();
  }
}

public class B implements Testable
{
  public void testing()
  {
    System.out.println("This is class B");
  }
}

public class C implements Testable
{
  public void testing()
  {
    System.out.println("This is class C");
  }
}

public class Test
{  
  public static void main (String[] args) 
  {
    B myB = new B();
    C myC = new C();
    A.myMethod(myB); // "This is class B"
    A.myMethod(myC); // "This is class C" 
  }
}

Porque estás pasando un objeto (b heredado de un objeto). El objeto no tiene pruebas, b tiene.

Puede pasar b o convertir el objeto en b antes de llamar al método.

EDITAR Para pasar una clase genérica que implemente ese método: querrá hacer una interfaz que tenga la firma del método y pasar el tipo de interfaz en lugar de Objeto. Todos los objetos que pase deben implementar la interfaz.

Solo puede acceder a los miembros que son visibles para el tipo de referencia que tiene para el objeto.

En el caso de myMethod (Object myObj) , eso significa solo los miembros definidos en Object, por lo tanto, en class a los miembros de class b no será visible.

Si cambia la definición de a.myMethod para que sea public static void myMethod (b myObj) , entonces podrá ver la prueba de método en la instancia de b mientras está en myMethod .

actualización basada en aclaraciones:

En ese caso, la definición de una interfaz para que todos ellos implementen es probablemente lo que quieres.

public interface Testable {
    public void testing();
}

public class a {
    public static void myMethod(Testable myObj) {
        myObj.testing();
    }
}

public class b implements Testable {
    public void testing () {
        System.out.println("TESTING!!!");
    }
}
  

¿Por qué java no puede encontrar mi método?

Por la forma en que fue diseñado Java.

Java es " escrito de forma estática " que significa que los tipos de objetos se comprueban durante compilación.

En Java, puedes invocar un método solo si ese método pertenece a ese tipo.

Dado que esta verificación se realiza durante la compilación y el tipo de objeto no tiene el " testing () " método, la compilación falla (aunque si en tiempo de ejecución los objetos tienen ese método " ;. Esto es principalmente por seguridad.

La solución alternativa descrita por otros requerirá que crees un nuevo tipo, donde puedas decirle al compilador

" Hey, las instancias de este tipo responderán al método de prueba "

Si desea pasar una variedad de objetos y mantenerlo muy genérico, una forma es tener esos objetos para implementar e interactuar.

public interface Testable { 
    public void testing();
}

class A implements Testable { // here this class commits to respond to "testing" message 
    public void testing() {
    }
}

class B implements Testable { // B "is" testable 
    public void testing() { 
        System.out.println("Testing from b");
    } 
}


class C implements Testable { // C is... etc. 
    public void testing() { 
        //.... 
    }
}

Más tarde en otro lugar

public void doTest( Testable object ) { 
    object.testing();
}

doTest( new A() );
doTest( new B() );
doTest( new C() );

El " OTROS " La forma de hacer esto, en java es invocar los métodos reflexivamente , pero no estoy seguro de si eso es lo que necesita, ya que el código es mucho más abstracto cuando lo hace de esa manera, pero así es como funcionan los marcos de prueba automatizados (y muchos otros marcos, como Hibernate).

Espero que esto te ayude a aclarar la razón.

Si REALMENTE, REALMENTE desea mantener el parámetro lo más abstracto posible, debe considerar la API de reflexión. De esa manera, puede pasar cualquier objeto que desee y ejecutar dinámicamente el método que desee. Puede consultar algunos ejemplos .

No es la única forma, pero podría ser una alternativa válida según su problema.

Tenga en cuenta que la reflexión es mucho más lenta que llamar directamente a sus métodos. También puedes considerar usar una interfaz, como la que está en la publicación de Amanda.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top