Même si vous pouvez utiliser des expressions lambda dans des flux, etc., il peut y avoir des personnes qui ne peuvent pas utiliser l'interface fonctionnelle pour leurs propres fonctions. Pour ces personnes, je voudrais présenter comment appliquer une interface fonctionnelle à une fonction auto-créée à l'aide d'un exemple simple.
Il est courant de copier les propriétés d'un objet dans un autre. A ce moment, il arrive souvent que la condition de copie soit définie uniquement lorsque la valeur de la propriété n'est pas nulle. Et, comme dans cet exemple, des copies de diverses propriétés de type sont souvent alignées. Il peut y avoir des cas où vous pouvez copier et coller de cette manière, mais je voudrais imaginer un peu. Créons une fonction commune pour le code suivant afin de simplifier l'appel. Notez que getName () renvoie une chaîne et setName () définit une chaîne. getFlag () renvoie Boolean et setFlag () définit Boolean.
if(objA.getName()!=null) {
objB.setName(objA.getName());
}
if(objA.getFlag()!=null) {
objB.setFlag(objA.getFlag());
}
J'espère que vous pourrez l'écrire comme suit. Voyons comment cela est réalisé en java.
setIfNotNull(value,func) {
if(value!= null) {
func(value);
}
}
setIfNotNull(objA.getName(),objB.setName);
setIfNotNull(objA.getFlag(),objB.setFlag);
Dans le pseudo code ci-dessus, func montre une méthode, mais comment doit-elle être exprimée en java? Une interface est ce qui indique une méthode. Encore une fois, cela peut être possible avec une interface.
public interface SetNameInterface {
void setName(String value);
}
public Class ObjB implements SetNameInterface{
void setName(String name);
}
public void setIfNotNull(String value,SetNameInterface obj) {
if(value!= null) {
obj.setName(value);
}
}
setIfNotNull(objA.getName(),objB);
Il était possible de prendre en charge setName (), mais il est clair qu'il ne peut pas supporter setFlag (). Cette méthode est intuitive, mais elle ne fonctionne pas.
Parce que nous voulons appeler setName () et setFlag () depuis setIfNotNull () avec le nom de fonction commun func. Que diriez-vous d'avoir un objet avec func comme interface pour setName () et setFlag ()?
public Class ObjB {
public void setName(String name) {
System.out.println("OnjB.setName:"+name);
}
public void setFlag(Boolean flag) {
System.out.println("OnjB.setFlag:"+flag);
}
}
public interface FuncInterface<T> {
void func(T value);
}
public class ObjBSetName implements FuncInterface<String> {
ObjB obj;
public ObjBSetName(ObjB obj) {
this.obj = obj;
}
@Override
public void func(String value) {
obj.setName(value);
}
}
public class ObjBSetFlag implements FuncInterface<Boolean> {
ObjB obj;
public ObjBSetFlag(ObjB obj) {
this.obj = obj;
}
@Override
public void func(Boolean value) {
obj.setFlag(value);
}
}
public <T>void setIfNotNull(T value,FuncInterface<T> obj) {
if(value!= null) {
obj.func(value);
}
}
setIfNotNull(objA.getName(),new ObjBSetName(objB));
setIfNotNull(objA.getFlag(),new ObjBSetFlag(objB));
ObjBSetName et ObjBSetFlag ont tous deux des fonctions func définies dans l'interface FuncInterface. Lorsque la fonction func est appelée, le traitement d'origine objB.setName () et objB.setFlag () sont appelés. Dans l'interface FuncInterface, le type du paramètre passé à la méthode est déclaré comme type générique (T dans ce cas). En conséquence, setIfNotNull () modifie également value et obj pour utiliser des types génériques.
J'ai réalisé ce que je veux faire avec cela, mais il est redondant de préparer ObjBSetName et ObjBSetFlag. Utilisons une classe anonyme.
Comment écrire une classe anonyme
nouveau nom de classe ou d'interface parente () { Contenu de classe anonyme (définitions de champs et de méthodes) };
Parce que c'est
var objBSetName = new FuncInterface<String>() {
@Override
public void func(String value) {
objB.setName(value);
}
};
var objBSetFlag = new FuncInterface<Boolean>() {
@Override
public void func(Boolean value) {
objB.setFlag(value);
}
};
Écrire, L'appel est
setIfNotNull(objA.getName(),objBSetName);
setIfNotNull(objA.getFlag(),objBSetFlag);
Ce sera. Dans la classe anonyme, vous pouvez référencer directement l'objet objB.
Pour les interfaces avec une seule fonction définie, la classe anonyme peut être remplacée par une expression lambda, donc
FuncInterface<String> objBSetName = (v) -> objB.setName(v);
FuncInterface<Boolean> objBSetFlag = (v) -> objB.setFlag(v);
Peut être réécrit comme. L'expression lambda n'a pas la notation func, mais elle implémente la fonction définie dans FuncInterface. Il est difficile de voir que func a disparu dans l'expression lambda, mais vous pouvez le comprendre en le comparant à la classe anonyme.
Omettez la variable plus loin,
setIfNotNull(objA.getName(),(v) -> objB.setName(v));
setIfNotNull(objA.getFlag(),(v) -> objB.setFlag(v));
Peut être résumé comme.
À propos, la déclaration de l'interface appelée FuncInterface est en fait une interface fonctionnelle. Le consommateur existe déjà, alors remplaçons-le par celui-ci. (Avant de créer votre propre interface, c'est une bonne idée de vérifier si l'interface fonctionnelle fournie peut être utilisée.)
public <T>void setIfNotNull(T value,Consumer<T> obj) {
if(value!= null) {
obj.accept(value);
}
}
De plus, comme il a un argument, l'appel peut être effectué à l'aide d'une référence de méthode.
setIfNotNull(objA.getName(),objB::setName);
setIfNotNull(objA.getFlag(),objB::setFlag);
Ce sera. C'était plutôt chouette.
Cette fois, j'ai expliqué avec un petit exemple, mais vous pouvez voir que le "traitement" peut être passé à la fonction. Je pense. La déclaration pour cela est "l'interface fonctionnelle". Vous avez peut-être déjà imaginé que vous pourriez l'utiliser pour réaliser un «modèle de stratégie». Veuillez l'appliquer à votre programme et réutiliser le programme.