2015-09-28 1 views
1

Disons que nous avonsQuel est le type d'une référence de méthode?

class A { 
    B method1 (C c) { ... } 
} 

Quel est le type de method1 comme référence de méthode?

C'est, quelle est la signature de la méthode de foo() pour cet appel ?:

foo (A::method1); 

Note:

J'ai défini une interface

interface I { 
    B m (A a, C c); 
} 

et il semble qu'il est juste déclarer foo comme

void foo (I i) { } 

(puisqu'il correspond à l'appel foo(A::method1) - à l'intérieur foo vous devez écrire b=i.m(a,c) pour signifier b=a.method1(c)).

Est-ce la seule façon de procéder?

Répondre

3

Les références de méthode et les lambdas sont de type cible pour correspondre à SAM interfaces. Dans votre cas, il doit correspondre I car c'est le type d'argument de foo.

1

explication informelle:

Rappelez-vous que les références de méthode peuvent être considérés comme une syntaxe alternative pour certains lambdas, et que lambdas tout mettre en œuvre une ou plusieurs functional interfaces.

Et rappelez-vous que les lambdas sont (actuellement) un moyen d'écrire des classes anonymes mono-méthode sous une forme beaucoup plus concise; ainsi, les lambdas peuvent toujours être réduits à une classe anonyme (mais pas toujours l'inverse).

Alors

foo (A::method1); 

peut devenir

foo ((c) -> <body>); 

qui peut être réduite à la classe anonyme:

foo (new Function<B>() { 
    <body> 
}); 

qui est une classe anonyme qui est un sous-type de fonction

Meth Les références od sont donc des sous-types anonymes de toute interface fonctionnelle qu'elles représentent, et le type du paramètre doit donc être l'interface fonctionnelle correspondante ou l'un de ses supertypes.


Le JLS a en fait une section intitulée "15.13.2. Type d'une méthode de référence", mais le libellé est peut-être un peu obtus. En bref:

Une référence de procédé peut être utilisé comme un type T si:

  • T est un type d'interface fonctionnelle (section 9.8)
  • La méthode abstraite de l'interface fonctionnelle correspond au type de compilation de la référence de procédé
  • Soit:
    • Les rendements de référence void
    • La référence renvoie un type qui peut être attribuée au type correspondant de l'interface fonctionnelle, p.ex. Une référence de la méthode doit retourner Number ou un sous-type soit compatible avec `B foo (Fonction f)
+0

ce n'est pas l'équivalent des classes internes anonymes car les lambdas ne capturent pas $ ceci comme un champ – the8472

+0

@ the8472 Ah, je ne savais pas à ce sujet. A pris un coup à un fixant, j'espère que ce n'est pas faux. Merci d'avoir fait remarquer cela! – awksp

0

J'admettais ici que cette question me est trop complexe pour de répondre sans essayer, mais je J'ai essayé de comprendre votre question, d'où ma compréhension de cette situation. Votre approche est bonne. Fondamentalement, vous faites ici les choses suivantes -

  1. En utilisant une syntaxe abrégée pour avoir une classe anonyme qui implémente l'interface fonctionnelle - ce qui est bien.
  2. Laisser le compilateur savoir utiliser A::method1 comme l'implémentation de I.m - ce qui est bien aussi.
  3. Parce que A::method1 existe déjà, vous pouvez utiliser la référence de méthode au lieu de l'expression lambda - - ce qui est bien aussi.
  4. Passage du paramètre réel c qui est effectué dans le corps de la méthode foo dans la ligne - b=i.m(a,c). Le paramètre utilisé ici pour c devrait être passé à A::method1.
  5. objet a dans a.method1 reste arbitraire selon spécification Java 8 pour cette syntaxe que vous spécifiant Class::Method et non Instance::Method
1

Au lieu de déclarer la nouvelle interface, vous pouvez utiliser un BiFunction existant:

void foo(BiFunction<? super A, ? super C, ? extends B> fn) { 
    ... 
    B b = fn.apply(a, c); 
    ... 
}