Gedanke: Wie man eine funktionale Schnittstelle für eigene Funktionen verwendet (Java)

zunaechst

Selbst wenn Sie Lambda-Ausdrücke in Streams verwenden können, können Sie die Funktionsschnittstelle möglicherweise nicht für Ihre eigenen Funktionen nutzen. Für solche Leute möchte ich anhand eines einfachen Beispiels vorstellen, wie eine funktionale Schnittstelle auf eine selbst erstellte Funktion angewendet wird.

Beispiel

Es ist üblich, die Eigenschaften eines Objekts in ein anderes zu kopieren. Zu diesem Zeitpunkt ist es häufig der Fall, dass die Kopierbedingung nur festgelegt wird, wenn der Wert der Eigenschaft nicht null ist. Und wie in diesem Beispiel werden häufig Kopien verschiedener Typeneigenschaften in einer Reihe angeordnet. Es kann Fälle geben, in denen Sie auf diese Weise kopieren und einfügen können, aber ich möchte ein wenig darüber nachdenken. Erstellen wir eine allgemeine Funktion für den folgenden Code, um den Aufruf zu vereinfachen. Beachten Sie, dass getName () einen String zurückgibt und setName () einen String setzt. getFlag () gibt Boolean zurück und setFlag () setzt Boolean.

if(objA.getName()!=null) {
    objB.setName(objA.getName());
}
if(objA.getFlag()!=null) {
    objB.setFlag(objA.getFlag());
}

Pseudocode

Ich hoffe du kannst es wie folgt schreiben. Mal sehen, wie es in Java erreicht wird.

setIfNotNull(value,func) {
    if(value!= null) {
        func(value);
    }
}
setIfNotNull(objA.getName(),objB.setName);
setIfNotNull(objA.getFlag(),objB.setFlag);

Antwort über die Schnittstelle (Beispiel, das nicht funktioniert)

Im obigen Pseudocode zeigt func eine Methode, aber wie sollte sie in Java ausgedrückt werden? Eine Schnittstelle gibt eine Methode an. Auch dies kann mit einer Schnittstelle möglich sein.

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

Es war möglich, setName () zu unterstützen, aber es ist klar, dass es nicht mit setFlag () kompatibel ist. Diese Methode ist intuitiv, funktioniert aber nicht.

Antworte über die Schnittstelle (es funktioniert, ist aber redundant)

Weil wir setName () und setFlag () von setIfNotNull () mit dem gemeinsamen Funktionsnamen func aufrufen möchten. Wie wäre es mit einem Objekt mit func als Schnittstelle für setName () und 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 und ObjBSetFlag verfügen beide über Funktionsfunktionen, die in der FuncInterface-Schnittstelle definiert sind. Wenn die Funktion func aufgerufen wird, werden die ursprüngliche Verarbeitung objB.setName () und objB.setFlag () aufgerufen. In der FuncInterface-Schnittstelle wird der Typ des an die Methode übergebenen Parameters als generischer Typ deklariert (in diesem Fall T). Entsprechend ändert setIfNotNull () auch value und obj, um generische Typen zu verwenden.

Antworte mit einer anonymen Klasse

Ich habe erreicht, was ich damit machen möchte, aber es ist überflüssig, ObjBSetName und ObjBSetFlag vorzubereiten. Verwenden wir eine anonyme Klasse.

Wie schreibe ich eine anonyme Klasse

neuer übergeordneter Klassen- oder Schnittstellenname () { Anonymer Klasseninhalt (Feld- und Methodendefinitionen) };

Denn es ist

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

Schreiben, Der Anruf ist

    setIfNotNull(objA.getName(),objBSetName);
    setIfNotNull(objA.getFlag(),objBSetFlag);

Es wird sein. Innerhalb der anonymen Klasse können Sie direkt auf das Objekt objB verweisen.

Antworte mit der Lambda-Formel

Für Schnittstellen mit nur einer definierten Funktion kann die anonyme Klasse durch einen Lambda-Ausdruck ersetzt werden

    FuncInterface<String> objBSetName = (v) -> objB.setName(v);
    FuncInterface<Boolean> objBSetFlag = (v) -> objB.setFlag(v);

Kann umgeschrieben werden als. Der Lambda-Ausdruck hat nicht die Notationsfunktion, implementiert jedoch die in FuncInterface definierte Funktion. Es ist schwer zu erkennen, dass func im Lambda-Ausdruck verschwunden ist, aber Sie können es verstehen, indem Sie es mit der anonymen Klasse vergleichen.

Lassen Sie die Variable weiter weg,

    setIfNotNull(objA.getName(),(v) -> objB.setName(v));
    setIfNotNull(objA.getFlag(),(v) -> objB.setFlag(v));

Kann zusammengefasst werden als.

Antworten Sie über eine funktionale Schnittstelle

Die Deklaration der Schnittstelle FuncInterface ist übrigens eigentlich eine funktionale Schnittstelle. Der Verbraucher existiert bereits, also ersetzen wir ihn durch diesen. (Bevor Sie eine eigene Schnittstelle erstellen, sollten Sie prüfen, ob die bereitgestellte Funktionsschnittstelle verwendet werden kann.)

public <T>void setIfNotNull(T value,Consumer<T> obj) {
    if(value!= null) {
        obj.accept(value);
    }
}

Da es ein Argument gibt, kann der Aufruf außerdem unter Verwendung einer Methodenreferenz erfolgen.

    setIfNotNull(objA.getName(),objB::setName);
    setIfNotNull(objA.getFlag(),objB::setFlag);

Es wird sein. Es war ziemlich ordentlich.

Zusammenfassung

Dieses Mal habe ich mit einem kleinen Beispiel erklärt, aber Sie können sehen, dass "Verarbeitung" an die Funktion übergeben werden kann. Ich denke. Die Deklaration dafür ist die "Funktionsschnittstelle". Sie haben sich vielleicht schon vorgestellt, dass Sie damit ein "Strategiemuster" erzielen könnten. Bitte wenden Sie es auf Ihr Programm an und verwenden Sie es erneut.

Recommended Posts

Gedanke: Wie man eine funktionale Schnittstelle für eigene Funktionen verwendet (Java)
So lesen Sie Ihre eigene YAML-Datei (*****. Yml) in Java
So erstellen Sie Ihre eigene Anmerkung in Java und erhalten den Wert
Aufrufen von Funktionen in großen Mengen mit Java Reflection
Zusammenfassung der Implementierung von Standardargumenten in Java
[Forge] So registrieren Sie Ihre eigene Entität und Ihr Entity Render in 1.13.2
So leiten Sie den letzten Tag des Monats in Java ab
Wie man JAVA in 7 Tagen lernt
Behandeln Sie Ihre eigenen Anmerkungen in Java
Wie verwende ich Klassen in Java?
So benennen Sie Variablen in Java
So verketten Sie Zeichenfolgen mit Java
Verstehen Sie, wie die funktionale Programmierung in Java auf einen Schlag eingeführt wurde
So ermitteln Sie die Länge einer Audiodatei mit Java
So erhöhen Sie den Wert von Map in einer Zeile in Java
So implementieren Sie die Datumsberechnung in Java
So implementieren Sie den Kalman-Filter mit Java
Mehrsprachige Unterstützung für Java Verwendung des Gebietsschemas
[java] Zusammenfassung des Umgangs mit char
So führen Sie eine Basiskonvertierung in Java durch
So erzwingen Sie Codierungskonventionen in Java
Einbetten von Janus Graph in Java
[Java] [Maven3] Zusammenfassung der Verwendung von Maven3
So erhalten Sie das Datum mit Java
So ermitteln Sie den absoluten Pfad eines in Java ausgeführten Verzeichnisses
Erstellen Sie mit Xcode Ihre eigenen Verknüpfungen, um komplizierte Pod-Installationsarbeiten zu vermeiden
Das erste Jahr des Berufslebens fasste zusammen, wie man die Java Bronze-Prüfung ablegt
Zusammenfassung der Auswahl von Elementen in Selen
[java] Zusammenfassung des Umgangs mit Zeichenketten
So zeigen Sie eine Webseite in Java an
[Java] Zusammenfassung, wie Lambda-Ausdrücke weggelassen werden
So erhalten Sie eine Klasse von Element in Java
So verbergen Sie Nullfelder als Antwort in Java
Verwendung von JQuery in Rails 6 js.erb
So lösen Sie Ausdrucksprobleme in Java
Wie schreibe ich Java String # getBytes in Kotlin?
So erhalten Sie den Klassennamen des Arguments von LoggerFactory.getLogger, wenn Sie SLF4J in Java verwenden
[Java] Anzeigen der von LocalDate und DateTimeformatter erfassten Tage auf Japanisch
Zusammenfassung der Verwendung des im IE festgelegten Proxy-Sets bei der Verbindung mit Java
[Java] So erhalten Sie die URL der Übergangsquelle
So erstellen Sie eine Java-Umgebung in nur 3 Sekunden
[Java] So lassen Sie den privaten Konstruktor in Lombok weg
Wie schreibe ich Scala aus der Perspektive von Java
[Java] Arten von Kommentaren und wie man sie schreibt
Wie kann ich IBM Mainframe-Dateien in Java eingeben / ausgeben?
[Java] So erhalten Sie den Maximalwert von HashMap
Stand April 2018 So installieren Sie Java 8 auf einem Mac
Verwendung von CommandLineRunner im Spring Batch von Spring Boot
Zusammenfassung der Java-Kommunikations-API (3) Verwendung von SocketChannel
So konvertieren Sie A in a und a in A mit logischem Produkt und Summe in Java
So verwalten Sie Java EE-Projekte in Eclipse
Zusammenfassung der Java-Kommunikations-API (2) Verwendung von HttpUrlConnection
Wie man altes Java (8er) in macOS 10.15 Catalina einfügt
Ausführen des WebCamCapture-Beispiels von NyARToolkit für Java
Hinweise zur Verwendung regulärer Ausdrücke in Java
In Anbetracht der Einführung der Java-Sprache in der Reiwa-Ära ~ Auswahl eines sicheren SDK
Azure funktioniert in Java
So erhalten Sie den Namen einer Klasse / Methode, die in Java ausgeführt wird