2009-03-06 2 views
2

Я пытаюсь окунуться в что-то в java. Когда я передаю объект другому методу класса, не могу ли я просто вызвать любые методы, присущие этому классу объектов?Почему Java не может найти мой метод?

В чем причина, почему код, такой как приведенный ниже пример, не компилируется?

Спасибо,

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: Причина, я оставил параметр в MyMethod как тип объекта, потому что я хотел бы иметь возможность передавать в различных типах объектов, каждый из которых имеет testing().

+1

Как хорошая практика, имена классов должны начинаться с прописной буквы. –

+0

Отмечено - спасибо большое. – barfoon

ответ

19

Если вы хотели бы передать в различных объектах с testing() методами, имеют каждый объект реализовать интерфейс Testable:

public interface Testable 
{ 
    public void testing() 
} 

Тогда же myMethod() взять Testable.

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

Edit: Для того, чтобы уточнить, реализующий интерфейс означает, что класс гарантированно имеет метод, но метод может делать все, что хочет. Поэтому я мог бы иметь два класса, методы testing() делают разные вещи.

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"); 
    } 
} 
+0

Каждый метод tests() для каждого класса объекта будет другим. Таким образом, невозможно иметь один общий метод тестирования. – barfoon

+0

Под «разными», вы имеете в виду разные подписи или просто разные в том, что он делает? Если только реализация отличается, это все равно будет работать. –

+0

Разные в том, что он делает. «Тесты», применяемые к этому типу объекта, будут отличаться внутри каждого метода class.testing(). – barfoon

8

Проблема в том, что myMethod не может знать, что он получает объект b, пока он фактически не запустится. Вы можете передать String, поскольку все это знает.

Изменить его

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

и он должен работать.


Обновление вопроса:

Edit: Причина, я оставил параметр в MyMethod как тип объекта, потому что я хотел бы иметь возможность передавать в различных типах объектов , каждый из которых имеет метод testing().

Как сказал Аманда С. и некоторые другие, это идеальный случай для интерфейса. Способ сделать это - создать интерфейс, который определяет метод testing() и изменить myMethod, чтобы взять объекты, реализующие этот интерфейс.

Альтернативное решение (без интерфейсов) должно было бы отражать, если объект имеет метод testing() и вызывает его, но это не рекомендуется и не требуется для такого простого случая.

+0

Теперь это немного яснее. Я обновил вопрос, но что, если я хочу передать в a или c, с каждым из этих объектов, имеющих свой собственный метод testing()? – barfoon

+0

Затем вы должны объявить, что он принимает параметр обычного суперкласса. Проблема в том, что java.lang.Object не имеет метода тестирования. –

+0

Хех, я немного ухожу и возвращаюсь, чтобы узнать, что вопрос изменен, и есть лучший ответ на новый вопрос. Ну что ж. –

2

Потому что вы проходите в Object (b наследуете от Object). Объект не имеет тестирования, b делает.

Вы можете либо передать в b, либо передать объект в b перед вызовом метода.

EDIT Чтобы передать в общий класс, который реализует этот метод: вы хотите создать интерфейс, который имеет подпись метода и передать тип интерфейса вместо Object. Все объекты, которые вы передаете, должны реализовывать интерфейс.

1

Доступ к элементам, доступным только для типа ссылки, доступен только для объекта.

В случае myMethod(Object myObj) это означает только элементы, определенные в объекте, поэтому в class a члены class b не будут видны.

Если вы изменили определение a.myMethod быть public static void myMethod(b myObj) вы бы тогда быть в состоянии увидеть метод testing на экземпляре b время в myMethod.

обновления на основе разъяснений:

В этом случае определяющего интерфейс для всех их реализации, скорее всего, что вы хотите.

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!!!"); 
    } 
} 
6

Что вы говорите, это печатание на утке. У Java нет утиной печати.

Поэтому вам необходимо определить интерфейс, который реализует все классы с помощью метода testing().

например:

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

Ваш вопрос является классическим аргументом в пользу интерфейса. Вы хотите как можно больше, но вы хотите, чтобы каждый объект, который вы проходили, имел метод testing(). Я предлагаю что-то вдоль линий следующее:

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" 
    } 
} 
+0

Это очень полезно, спасибо. – barfoon

1

Почему не ява найти мой метод?

Из-за того, что была разработана Java.

Java является "statically typed", что означает, что проверяются типы объектов во время компиляция.

В Java вы можете вызывать метод, только если этот метод принадлежит этому типу.

Поскольку эта проверка выполняется во время компиляции, а тип объекта не имеет метода «test()», компиляция не выполняется (хотя, если во время выполнения объекты имеют этот метод ».Это в первую очередь касается безопасности.

обходной, как описано другими потребует от вас, чтобы создать новый тип, где вы можете сказать компилятору

«Эй, экземпляры этого типа будет реагировать метод тестирующего»

Если вы хотите передать множество объектов и сохранить их очень универсальными, один из способов - реализовать эти объекты и интерфейс.

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 
    pubic void testing() { 
     System.out.println("Testing from b"); 
    } 
} 


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

Позже где-то еще

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

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

«Другой» способ сделать это, в Java является вызов методов reflectively, но я не уверен, что это то, что вам нужно, для кода гораздо более абстрактные, когда вы делаете это именно так, но это то, как фактически работают автоматизированные рамки тестирования (многие другие структуры, такие как Hibernate).

Надеюсь, это поможет вам прояснить причину.

0

Если вы ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО хотите, чтобы параметр был максимально абстрактным, вы должны рассмотреть отражение API. Таким образом, вы можете передать любой объект, который вам нужен, и динамически выполнять метод, который вы хотите. Вы можете посмотреть some examples.

Это не единственный способ, но это может быть приемлемая альтернатива в зависимости от вашей проблемы.

Имейте в виду, что отражение намного медленнее, чем прямое обращение к вашим методам. Вы могли бы также использовать интерфейс, например, тот, который был на посту Аманды.

+0

Quiza primero deba de entender como funcionan las cosas en Java, y luego salar a cosas más avanzadas. :) Салудос! – OscarRyz

Смежные вопросы