Ich denke, es ist üblich, eine Funktion mit Standardargumenten in Kotlin zu definieren und zu verwenden, aber als ich versuchte, sie von Java aus zu verwenden, fühlte ich mich etwas unangenehm. Ich würde gerne wissen, wie es am besten geht, aber ich konnte es nicht finden, also lasse ich es in der Hoffnung, dass es mir jemand sagt.
Beachten Sie, dass der Implementierungsinhalt der Schnittstelle angemessen ist, da es sich um Bestätigungscodes handelt.
Definieren Sie die Verbindungsfunktion, die die Verbindung zur Datenbank mit einem Kreditmuster verwaltet.
ConnectionManager
interface ConnectionManager {
fun createConnection(host: String): Connection {
return Connection(host)
}
fun<A> connect(c: Connection = createConnection("localhost"), f: (Connection) -> A): A {
try {
c.begin()
return f(c)
} catch (e: Exception) {
c.rollback()
throw e
} finally {
c.commit()
}
}
}
Image, das eine Verbindung zur Datenbank herstellt, eine select-Anweisung ausgibt und eine Benutzerinstanz zurückgibt
UserDao
class UserDao : ConnectionManager {
fun findById(id: Int): User {
return connect { c -> c.select("select * from user where id = ${id}", User()) }
}
}
Bisher gibt es kein besonderes Problem. Ich hatte also ein Problem, als ich diese Schnittstelle auch von Java aus verwenden wollte.
UserDaoJava
public class UserDaoJava implements ConnectionManager {
public User findById(int id) {
return connect(c -> c.select("select * from user where id = " + id, new User()) );
}
}
Dies führt zu einem Kompilierungsfehler. In Java können Argumente, bei denen die Standardargumente weggelassen werden, nicht als eine Verbindungsfunktion aufgerufen werden.
Ich konnte nicht anders, also habe ich der Schnittstelle eine Funktion mit einem Argument hinzugefügt.
ConnectionManager
interface ConnectionManager {
···Kürzung···
//Fügen Sie diese Funktion unvermeidlich hinzu
fun<A> connect(f: (Connection) -> A): A {
return connect(createConnection("localhost"), f)
}
}
Ich frage mich, ob das in Ordnung ist, aber es wird immer noch nicht kompiliert. Unter Java kann die Standardimplementierung der Kotlin-Schnittstelle nicht unverändert aufgerufen werden. Daher muss es auf der Java-Klassenseite überschrieben werden, um verwendet zu werden.
UserDaoJava
public class UserDaoJava implements ConnectionManager {
···Kürzung···
//Ich brauche die unteren drei
@NotNull
@Override
public Connection createConnection(@NotNull String host) {
//Ich möchte die interne Implementierung von ConnectionManager verwenden, also nenne ich es so wie es ist.
return ConnectionManager.DefaultImpls.createConnection(this, host);
}
@Override
public <A> A connect(@NotNull Connection c, @NotNull Function1<? super Connection, ? extends A> f) {
return ConnectionManager.DefaultImpls.connect(this, c, f);
}
@Override
public <A> A connect(@NotNull Function1<? super Connection, ? extends A> f) {
return ConnectionManager.DefaultImpls.connect(this, f);
}
}
Jetzt funktioniert auch die Zusammenstellung. Ich mag es jedoch nicht, zwei Verbindungsfunktionen zu sehen, wenn ich ConnectionManager auf der Kotlin-Seite verwende, und vor allem kann ich es nicht jedes Mal überschreiben, wenn ich es auf der Java-Seite verwende.
Erstellen wir also einen Verbindungsmanager für Java!
Löschen Sie zunächst die Verbindungsfunktion mit einem Argument, das zuvor in ConnectionManager hinzugefügt wurde. Definieren Sie dann die Verbindungsfunktion mit einem Argument im neu erstellten Verbindungsmanager für Java.
ConnectionManagerJava
public interface ConnectionManagerJava extends ConnectionManager {
@NotNull
@Override
default Connection createConnection(@NotNull String host) {
return ConnectionManager.DefaultImpls.createConnection(this, host);
}
@Override
default <A> A connect(@NotNull Connection c, @NotNull Function1<? super Connection, ? extends A> f) {
return ConnectionManager.DefaultImpls.connect(this, c, f);
}
default <A> A connect(@NotNull Function1<? super Connection, ? extends A> f) {
return connect(createConnection("localhost"), f);
}
}
Und UserDaoJava wurde geändert, um ConnectionManagerJava zu verwenden
UserDaoJava
public class UserDaoJava implements ConnectionManagerJava {
public User findById(int id) {
return connect(c -> c.select("select * from user where id = " + id, new User()) );
}
}
Damit kann die Verbindungsfunktion mit einem Argument, das Kotlins ConnectionManager hinzugefügt wurde, gelöscht werden, und die Java-Seite ist ebenfalls ordentlich. Da jedoch die Standardimplementierung in der Schnittstelle verwendet wird, besteht das Problem, dass es sich um Java 8 handeln muss.
Mit diesem Gefühl kam ich auf den Trick, eine Schnittstelle auf der Java-Seite zu erstellen, um die Schnittstelle mit Kotlins Standardargumenten aus Java zu verwenden, aber ich habe das Gefühl, dass etwas nicht stimmt. .. ..
Ich frage mich, ob dies die richtige Antwort ist, ob sie sich von der in Kotlins Benutzeroberfläche implementierten unterscheidet oder ob es einen anderen Weg gibt.
Recommended Posts