Je pense qu'il est courant de définir une fonction avec des arguments par défaut dans Kotlin et de l'utiliser, mais quand j'ai essayé de l'utiliser à partir de Java, je me suis senti un peu désagréable. J'aimerais connaître le meilleur moyen, mais je ne l'ai pas trouvé, alors je vais le laisser dans l'espoir que quelqu'un me le dira.
Notez que le contenu d'implémentation de l'interface est approprié car il s'agit de codes de vérification.
Définissez la fonction de connexion
qui gère la connexion à la base de données avec un modèle de prêt.
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 qui se connecte à la base de données, émet une instruction SELECT et renvoie une instance User
UserDao
class UserDao : ConnectionManager {
fun findById(id: Int): User {
return connect { c -> c.select("select * from user where id = ${id}", User()) }
}
}
Il n'y a pas de problème particulier pour l'instant. J'ai donc eu un problème lorsque j'ai voulu utiliser cette interface depuis Java également.
UserDaoJava
public class UserDaoJava implements ConnectionManager {
public User findById(int id) {
return connect(c -> c.select("select * from user where id = " + id, new User()) );
}
}
Cela entraînera une erreur de compilation. À partir de Java, les arguments qui omettent les arguments par défaut ne peuvent pas être appelés comme une fonction de connexion.
Je n'ai pas pu m'en empêcher, j'ai donc ajouté une fonction avec un argument à l'interface.
ConnectionManager
interface ConnectionManager {
···réduction···
//Ajouter cette fonction inévitablement
fun<A> connect(f: (Connection) -> A): A {
return connect(createConnection("localhost"), f)
}
}
Je me demande si ça va, mais ça ne compile toujours pas. Depuis Java, l'implémentation par défaut de l'interface de Kotlin ne peut pas être appelée telle quelle. Par conséquent, il doit être remplacé du côté de la classe Java pour être utilisé.
UserDaoJava
public class UserDaoJava implements ConnectionManager {
···réduction···
//J'ai besoin des trois derniers
@NotNull
@Override
public Connection createConnection(@NotNull String host) {
//Je souhaite utiliser l'implémentation interne de ConnectionManager, je l'appelle donc telle quelle.
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);
}
}
Désormais, la compilation fonctionne également. Cependant, je n'aime pas voir deux fonctions de connexion lors de l'utilisation de ConnectionManager côté Kotlin, et surtout, je ne peux pas le remplacer à chaque fois que je l'utilise côté Java.
Créons donc un gestionnaire de connexion pour Java !!
Tout d'abord, supprimez la fonction de connexion avec un argument ajouté précédemment à partir de ConnectionManager. Ensuite, définissez la fonction de connexion avec un argument dans le gestionnaire de connexion nouvellement créé pour 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);
}
}
Et UserDaoJava a changé pour utiliser ConnectionManagerJava
UserDaoJava
public class UserDaoJava implements ConnectionManagerJava {
public User findById(int id) {
return connect(c -> c.select("select * from user where id = " + id, new User()) );
}
}
Avec cela, la fonction de connexion avec un argument ajouté au ConnectionManager de Kotlin peut être supprimée, et le côté Java est également soigné. Cependant, comme l'implémentation par défaut est utilisée dans l'interface, il existe un problème selon lequel il doit s'agir de Java 8.
Avec ce genre de sentiment, j'ai trouvé l'astuce de créer une interface côté Java afin d'utiliser l'interface avec les arguments par défaut de Kotlin depuis Java, mais je pense que quelque chose ne va pas. .. ..
Je me demande si c'est la bonne réponse, si elle est différente de ce qui est implémenté dans l'interface de Kotlin, ou s'il existe un autre moyen.
Recommended Posts