Ce que je n'aime pas lors de l'utilisation de l'interface d'une fonction avec des arguments par défaut dans Kotlin depuis Java

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

Ce que je n'aime pas lors de l'utilisation de l'interface d'une fonction avec des arguments par défaut dans Kotlin depuis Java
Ce que j'ai appris lors de la création d'un serveur en Java
Je veux créer une fonction avec kotlin et java!
Implémentation d'une fonction similaire en Java
[Note] Ce que j'ai appris en six mois grâce à des inexpérimentés (Java)
[Note] Ce que j'ai appris en six mois grâce à des inexpérimentés (Java) (1)
[Note] Ce que j'ai appris en six mois grâce à des inexpérimentés (Java) (3)
Ce à quoi j'ai pensé lorsque j'ai commencé à migrer de Java vers Kotlin
Comment utiliser la fonction implémentée dans l'interface de Kotlin introduite dans Maven comme implémentation par défaut de Java 8
Une note de ce sur quoi j'ai trébuché et remarqué en rattrapant Laravel de Rails
[Rails] Ce que j'ai appris d'une petite pierre d'achoppement lors de l'utilisation de l'ascendance
J'ai écrit une fonction Lambda en Java et l'ai déployée avec SAM
Résumé des points qui m'inquiétaient lors de la migration de Java vers Kotlin
Ce que j'ai fait lorsque j'ai converti Java en Kotlin
Appeler une méthode avec le bloc de rappel de Kotlin depuis Java
J'ai essayé de créer une fonction de connexion avec Java
Résumé de la mise en œuvre des arguments par défaut en Java
Résumé des points que les programmeurs Java trouvent glissants lorsqu'ils lisent la source Kotlin pour la première fois
Je veux faire une liste avec kotlin et java!
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3
J'ai créé un client RESAS-API en Java
J'ai écrit un analyseur C (comme) en utilisant PEG dans Ruby
Trouvez le nombre de jours dans un mois avec Kotlin
[Rails] Implémentation de la fonction de catégorie multicouche en utilisant l'ascendance "J'ai essayé de créer une fenêtre avec Bootstrap 3"
Quand j'étais inquiet des méthodes statiques dans l'interface java, je suis arrivé à l'ordre d'interprétation des noms
[Java] Précautions lors de la création d'un processus qui appelle une méthode de classe abstraite utilisant DI à partir d'une classe enfant
Lors de l'installation d'un gem avec l'extension C dans Ruby, je veux le terminer rapidement en utilisant plusieurs cœurs de processeur comme make -j4
J'ai créé une interface de ligne de commande avec WinMerge Plugin en utilisant JD-Core
Exemple d'utilisation de l'API Bulk de Salesforce à partir d'un client Java avec PK-chunking
J'ai essayé d'implémenter le traitement Ajax de la fonction similaire dans Rails
Je ne peux pas créer une classe Java avec un nom spécifique dans IntelliJ
Créons une application TODO en Java 6 Implémentation de la fonction de recherche
À propos de ce que j'ai fait lors de la création d'un fichier .clj avec Clojure
Créons une application TODO en Java 8 Implémentation des fonctions d'édition
J'ai écrit une sorte de livre qui ressemble à Java
Ce que j'ai appris en travaillant Java avec Visual Studio Code
Ce que je fais souvent quand j'ai du mal à nommer avec Java (etc.)
J'ai créé un PDF avec Java.
Ce que j'ai appris avec Java Gold
J'ai essayé d'utiliser JWT en Java
Ce que j'ai appris avec Java Silver
J'ai essayé d'utiliser Google HttpClient de Java
L'histoire de la création d'un lanceur de jeu avec une fonction de chargement automatique [Java]
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3 (édition PowerMockito)
J'ai essayé de créer une application de conversation en Java à l'aide de l'IA «A3RT»
Je veux ForEach un tableau avec une expression Lambda en Java
[Java] Récupère MimeType à partir du contenu du fichier avec Apathce Tika [Kotlin]
Une erreur s'est produite lors de l'exécution d'une fonction avec CURSOR défini dans le paramètre OUT de MyBatis dans PostgreSQL.