2014-09-12 2 views
3

En Java: Quelle est la meilleure façon de passer une méthode d'un objet à un autre afin qu'elle puisse être appelée plus tard par le second objet?Méthode déléguée appelant en Java

Je viens d'un contexte ActionScript où il est aussi facile de passer des références à des méthodes que de passer des références à des variables, mais cela semble beaucoup plus difficile en Java. Les premiers liens que j'ai trouvé à plat disent que ce n'est pas possible (et cela peut avoir été au moment de leur publication), mais j'ai ensuite trouvé http://www.javacamp.org/javavscsharp/delegate.html qui détaille comment cela peut être accompli.

Mon problème avec l'utilisation de l'exemple de Javacamp est la référence à la méthode basée sur une chaîne. Les méthodes sont renommées tout le temps et une référence de chaîne ne se plaindra qu'une fois que vous aurez exécuté cette fonction, par opposition à la compilation d'un lien explicite approprié.

N'y a-t-il aucun moyen de le faire avec des liens explicites appropriés à la méthode que vous voulez que l'autre classe exécute?

modèle de ce que j'espère accomplir:

  1. joueur clique sur un bouton de mise à niveau sur Activité1> Activité1 passe méthode mise à niveau vers une nouvelle activité de confirmation
  2. joueur clique sur « Oui »> Activité de confirmation appelle la méthode de mise à niveau passé dans de Activité1
  3. OU: joueur clique sur « Non »> Activité de confirmation ferme

EDIT: Pour être clair, je suis Je ne cherchais pas de solution de méthode statique car cela nécessiterait que mon activité de confirmation contienne de nombreuses lignes de logique pour lesquelles la méthode statique appelle. L'activité de confirmation sera utilisée partout dans mon application: un simple "Êtes-vous sûr de vouloir X?" -Oui -Non, si oui, exécuter X

Je cherche actuellement à mettre en œuvre onActivityResult pour éviter ce problème mais ce sera plus logique que ce que je préfère pour ce genre de problème.

+0

Vérifiez le motif de commande. –

+0

Depuis que vous travaillez sur Android, voici ce que vous avez besoin: http://stackoverflow.com/a/16800770/1400672 –

Répondre

0

Si vous avez besoin de la méthode pour agir différemment selon le contexte (AKA, elle est différente selon la façon dont elle est créée), vous voudrez transmettre l'instance de la classe dans laquelle se trouve la méthode.

S'il s'agit d'une méthode statique, vous pouvez simplement référencer la méthode elle-même si vous importez cette classe en haut de votre nouvelle classe. Par exemple, disons que vous avez une méthode qui vous dira des choses sur une certaine chaîne. Si la classe ressemble à ceci:

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

Ensuite, vous aurez envie de passer le long de l'instance, car il est non-statique. Différentes instances ont des chaînes différentes avec lesquelles elles ont été créées, de sorte que vous obtiendrez un résultat différent si vous utilisez une instance différente.

Cependant, si votre classe ressemble plus à ceci:

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

Ensuite, vous pouvez simplement la référence ces méthodes avec stringChecker.getStringLength (« test ») ;, car les méthodes sont statiques. Peu importe l'instance dans laquelle ils se trouvent. Le résultat renvoyé dépend UNIQUEMENT de ce qui est transmis. Vous devez simplement vous assurer d'ajouter import stringChecker; au sommet ou quel que soit votre classe sera appelée. Pour vous, ce sera probablement quelque chose comme com.example.blah.otherthing.stringChecker, puisque vous travaillez avec Android.

Bonne chance! J'espère que cela aide :)

EDIT: On dirait que j'ai peut-être lu le problème trop rapidement ... si ce n'est pas ce que vous avez demandé, faites le moi savoir avec un commentaire et je vais supprimer cette réponse afin de ne confondre personne d'autre.

+0

Merci pour l'entrée, mais un appel statique n'est pas ce que je cherche. Je veux utiliser l'activité de confirmation sur l'ensemble de mon application là où c'est nécessaire et je ne veux pas d'un commutateur et d'une logique massifs à l'intérieur d'une simple classe de confirmation. J'espère trouver un moyen de passer dans la méthode désirée, puis le feu si le joueur frappe oui, une ligne propre vs un désordre de la logique. – Currence

1

La méthode habituelle pour passer des méthodes consiste à utiliser une classe d'interface et une classe interne anonyme. Afin de maintenir le typage statique, une interface est utilisée pour déclarer la signature de la méthode et les informations de frappe. L'appelant peut utiliser une implémentation concrète de cette interface en tant que classe normale ou en utilisant des classes internes anonymes pour une création de classe rapide. Je vais utiliser des classes Java SDK standard pour illustrer:

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

Ce qui précède est un exemple de modèle de stratégie. La chose sur le modèle de stratégie (et passer des méthodes de rappel comme en Javascript). L'auteur doit planifier pour ces types d'extensions. L'auteur doit prédire d'avance où il veut que vous étendiez. Et il arrive que ce soit le plus propre si vous utilisez Interfaces.

Cependant, la délégation pure ne doit pas toujours impliquer des interfaces. Vous pouvez passer des classes concrètes, puisque Java peut toujours passer une sous-classe qui remplace les diverses méthodes de cette classe pour changer la méthode ou le code qui sera appelé. Par exemple, en Java InputStream/OutputStream sont des classes abstraites et vous passez généralement des instances de sous-classes aux méthodes.

+0

Merci Je vais regarder dans ce modèle plus loin – Currence

6

vous pouvez utiliser des interfaces comme ceci:

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

ce ne résout votre problème?

+0

Je passe d'une activité (Activité1 dans mon exemple) à une autre (Confirmation) dans mon application android donc je ne peux pas appeler directement une méthode de l'un à l'autre mais je peux être capable utiliser cette stratégie pour stocker la méthode dans le modèle, puis l'extraire dans la confirmation. Souhaitez-moi bonne chance – Currence

+0

Bonne chance, et lisez ce livre "tête premiers modèles de conception" si vous pouvez – jcstar

+0

:(Non, après avoir travaillé avec lui, j'ai trouvé que j'ai besoin d'une méthode spécifique sur un objet existant appelé, mais cela crée un nouvel objet anonyme pour effectuer la fonction passée. – Currence

0

Vous avez indiqué que vous l'utilisiez dans un projet pour ouvrir une activité de confirmation. Les activités ne doivent pas contenir de références les unes aux autres pour éviter les fuites de mémoire. Pour transmettre des données entre les activités, il faut utiliser Intention class. Pour recevoir un résultat, appelez le StartActivityForResult() et obtenez le résultat dans la méthode onActivityResult().

Mais en général pour votre tâche est plus approprié AlertDialog ou popupWindow.