2014-09-12 3 views
3

В Java: Каков наилучший способ передать метод от одного объекта к другому, чтобы он мог быть вызван позднее вторым объектом?Вызов метода делегата в Java

Я пришел из фона ActionScript, где так же легко передавать ссылки на методы, как и передавать ссылки на переменные, но это, по-видимому, намного сложнее в Java. Первые несколько ссылок, которые я нашел, говорят, что это невозможно (и, возможно, это было во время их публикации), но затем я нашел http://www.javacamp.org/javavscsharp/delegate.html, где подробно описано, как это можно сделать.

Моя проблема с использованием примера Javacamp - это основанная на строках ссылка на метод. Методы получают переименованное все время, и ссылка на строку будет жаловаться только после того, как вы на самом деле запустили эту функциональную среду выполнения, в отличие от времени компиляции для правильной явной ссылки.

Нет ли способа сделать это с помощью правильных явных ссылок на метод, который должен выполнять другой класс?

модель того, что я надеюсь достичь:

  1. Игрок нажимает на кнопку обновления на Activity1> Activity1 проходит обновление метод новой активности подтверждения щелкает
  2. игрока «Да»> активность подтверждения требует обновления метод передается из Activity1
  3. ИЛИ: Игрок нажимает кнопку «Нет»> активность подтверждения закрывает

EDIT: Чтобы быть ясно, я не ища решение статического метода, так как это потребует, чтобы моя операция подтверждения содержала много строк логики, для которых статический метод для вызова. Подтверждение активности будет использоваться по всему моему приложению: простой «Вы уверены, что хотите X?» -Yes -Нет, если да, выполните X

В настоящее время я изучаю реализацию onActivityResult, чтобы избежать этой проблемы, но это будет логичнее, чем мне нравится в этом вопросе.

+0

Проверьте шаблон команды. –

+0

Поскольку вы работаете на Android, вот что вам нужно: http://stackoverflow.com/a/16800770/1400672 –

ответ

0

Если вам нужен способ действовать по-разному в зависимости от контекста (AKA, он отличается в зависимости от того, как он создается), вам нужно пройти по экземпляру класса, в котором находится этот метод.

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

Например, скажем, у вас есть метод, который расскажет вам о некоторой строке. Если класс выглядит следующим образом:

class stringChecker { 
    private String stringToCheck; 
    public class stringChecker(String s) { 
     stringToCheck = s; 
    } 
    public int getStringLength() { 
     return stringToCheck.length(); 
    } 
    public boolean stringStartsWith(String startsWith) { 
     return (stringToCheck.indexOf(startsWith) == 0); 
    } 
} 

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

Однако, если ваш класс выглядит так:

class stringChecker { 
    public static int getStringLength(String s) { 
      return s.length(); 
    } 
    public static boolean stringStartsWith(String s, String startsWith) { 
      return (s.indexOf(startsWith) == 0); 
    } 
} 

Тогда вы можете просто ссылаться на эти методы с stringChecker.getStringLength («тест») ;, потому что методы являются статическими. Не имеет значения, в каком экземпляре они находятся. Возвращенный результат зависит ТОЛЬКО от того, что передается. Вам просто нужно обязательно добавить import stringChecker; наверху или независимо от того, что будет вызван ваш класс. Для вас это, вероятно, будет что-то вроде com.example.blah.otherthing.stringChecker, поскольку вы работаете с Android.

Удачи вам! Надеюсь, это поможет :)

EDIT: Похоже, я, возможно, слишком быстро прочитал проблему ... если это не то, о чем вы просили, просто дайте мне знать с комментарием, и я удалю этот ответ чтобы не путать никого другого.

+0

Спасибо за ввод, но статический звонок не то, что я ищу. Я хочу использовать операцию подтверждения по всему моему приложению, когда это необходимо, и я не хочу, чтобы массивный логический элемент и простой логический элемент находились в простом классе подтверждения. Я надеюсь найти способ пройти по желаемому методу, а затем запустить его, если игрок нажмет «да», одну чистую линию и беспорядок логики. – Currence

1

Типичным способом передачи методов является использование интерфейса и анонимных внутренних классов. Чтобы поддерживать статическую типизацию, интерфейс используется для объявления сигнатуры метода и ввода информации. Вызывающий может использовать конкретную реализацию этого интерфейса как обычный класс или использовать Анонимные Внутренние Классы для быстрого создания класса. Я буду использовать стандартные классы Java SDK для иллюстрации:

interface Comparator<T> { 
    public int compare(T a, T b); 
} 

class SpecialCollection<T> { 
    public void sort(Comparator<T> comparator) {...} 
} 

public class SomeClient { 
    public void doSomething(SpecialCollection<SpecialObj> collection) { 

     collection.sort(new Comparator<SpecialObj>() { 
      public int compare(SpecialObject a, SpecialObject b) { 
       // some implementation 
      } 
     }); 
    } 
} 

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

Однако чистое делегирование не обязательно должно включать интерфейсы. Вы можете передавать конкретные классы, поскольку Java всегда может передавать подкласс, который переопределяет различные методы этого класса, чтобы изменить способ вызова или кода. Например, в Java InputStream/OutputStream являются абстрактными классами, и вы обычно передаете экземпляры подкласса методам.

+0

Спасибо, я буду изучать этот шаблон далее – Currence

6

вы можете использовать интерфейсы, как это:

public interface MyMethod { 
    public void method(); 
} 


public class FirtObject{ 

    private SecondObject ob; 

    public void tellSecondObjectExecuteLater(){ 
     ob.executeLater(new MyMethod() { 
      public void method(){System.out.println("duh Method");} }); 
    } 
} 

public class SecondObject { 

    private MyMethod myMth; 

    public void executeLater(MyMethod mth){ 
     myMth = mth; 
    } 

    public void executeNow(){ 
     myMth.method(); 
    } 
} 

ли это решить проблему?

+0

Я перехожу от одного действия (Activity1 в моем примере) к другому (Подтверждение) в моем приложении Android, поэтому я не могу напрямую вызвать метод от одного к другому, но я могу быть в состоянии чтобы использовать эту стратегию для хранения метода в модели, а затем выберите это в Подтверждении. Пожелайте мне удачи – Currence

+0

Удачи вам и прочитайте эту книгу «head first design patterns», если вы можете – jcstar

+0

:(Нет, после работы с ней я обнаружил, что мне нужен конкретный метод для существующего объекта, но это создает новый анонимный объект для выполнения переданной функции. – Currence

0

Вы сказали, что используете его в проекте, чтобы открыть операцию подтверждения.

Мероприятия не должны содержать ссылок друг на друга, чтобы избежать утечек памяти. Для передачи данных между видами деятельности следует использовать Намерение класс. Чтобы получить результат, позвоните StartActivityForResult() и получите результат в методе onActivityResult().

Но в целом для вашей задачи больше подходит AlertDialog или PopupWindow.

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