Pergunta

Eu estou tentando envolver minha mente em torno de algo em java. Quando eu passar um objeto para outro método de classe, que não posso apenas chamar quaisquer métodos inerentes a essa classe de objeto?

O que é o código de razão, como o exemplo a seguir não compila?

Obrigado,

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);  
  }
}

Edit: A razão de eu ter deixado o parâmetro no myMethod como tipo de objeto, é porque eu gostaria de ser capaz de passar em uma variedade de tipos de objetos, cada um com um método de teste () .

Foi útil?

Solução

Se você gostaria de passar em uma variedade de objetos com métodos testing(), têm cada objeto implementar uma interface Testable:

public interface Testable
{
   public void testing()
}

Então, myMethod() dar uma Testable.

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

Edit: Para esclarecer, a implementação de um meio de interface que a classe é a garantia de ter o método, mas o método pode fazer o que quiser. Então, eu poderia ter duas classes cujos métodos testing() fazer coisas 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");
   }
}

Outras dicas

O problema é que myMethod não pode saber que está ficando um objeto b até que ele realmente funciona. Você poderia passar um String, por tudo o que sabe.

Mude-o para

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

e ele deve funcionar.


Atualização da pergunta:

Edit: A razão de eu ter deixado o parâmetro no myMethod como tipo de objeto, é porque eu gostaria de ser capaz de passar em uma variedade de tipos de objetos, cada um com um método de teste () .

Como Amanda S e vários outros já disseram, este é um caso perfeito para uma interface. A maneira de fazer isso é criar uma interface que define o método testing() e mudança myMethod levar objetos implementar essa interface.

Uma solução alternativa (sem as interfaces) seria descobrir reflexivamente se o objeto tem um método testing() e chamá-lo, mas isso não é recomendado e não é necessário para um caso simples.

O que você está falando é pato digitação. Java não tem tipagem pato.

Portanto, você precisa definir uma interface que todas as classes com um método testing() implementar.

por exemplo:

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();
  }
}

Seu problema é um argumento clássico em favor de uma interface. Você quer o mais genérico possível, ainda que você quer cada objeto que você passa a ter um método de teste (). Eu sugiro algo ao longo das linhas do seguinte:

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 você está passando em um objeto (b herdar de Object). Objeto não tem testando, b faz.

Você pode passar em b ou converter o objeto para b antes de chamar o método.

EDIT Para passar em uma classe genérica que implementa esse método: você vai querer fazer uma interface que tem a assinatura do método e passar o tipo de interface em vez de objeto. Todos os objetos que você passar no deve implementar a interface.

Você só pode acessar os membros que são visíveis para o tipo de referência que você tem para o objeto.

No caso de myMethod(Object myObj) Isso significa que apenas os membros definidos no objeto, portanto, em class a os membros da class b não será visível.

Se você mudou a definição de a.myMethod ser public static void myMethod(b myObj) você, então, seria capaz de ver o método testing na instância do b enquanto em myMethod.

atualização com base no esclarecimento:

Nesse caso, definindo uma interface para todos eles para implementar é provável que você quer.

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 que não java encontrar meu método?

Devido à forma como Java foi projetado.

Java é "tipagem estática" que os objectos tipos são verificados durante compilação.

Em Java você pode chamar um método somente se esse método pertence a esse tipo.

Uma vez que esta verificação é feita durante a compilação eo tipo de objeto não tem o método "teste ()", a compilação falhar (embora se em tempo de execução os objetos têm esse método". Isto é principalmente para a segurança.

A solução como descrito por outros exigirá que você criar um novo tipo, onde você pode dizer o compilador

"Hey, as instâncias desse tipo responder o método de teste"

Se você quer passar uma variedade de objetos e mantê-lo muito genérica, de uma maneira é ter esses objetos para implementar e interface.

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() { 
        //.... 
    }
}

Mais tarde, em outro lugar

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

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

O "outro" maneira de fazer isso, em java está invocando os métodos reflexivamente , mas eu não tenho certeza se é isso que você precisa, para o código é muito mais abstrata quando você fazê-lo dessa forma, mas é assim que testes automatizados enquadramentos (e um monte de outras estruturas, como Hibernate ) fazer realmente trabalho.

Espero que isso ajude a esclarecer a razão.

Se você realmente quiser manter o parâmetro tão abstrato quanto possível, você deve considerar a reflexão API. Dessa forma, você pode passar qualquer objeto que você deseja e executar dinamicamente o método que você deseja. Você pode dar uma olhada em alguns exemplos .

Não é o único caminho, mas pode ser uma alternativa válida dependendo do seu problema.

Tenha em mente que a reflexão é muito mais lento do que chamar seus métodos diretamente. Você pode considerar o uso de uma interface bem, como aquele no post de Amanda.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top