2017-08-20 4 views
5

Je me suis amusé avec Kotlin récemment, et ça a été génial!Comment faire pour que Kotlin arrête de lancer l'argument à la mauvaise classe (Interface)

Je travaillais avec la bibliothèque Twitter4j pour essayer quelques trucs avec l'API Twitter. J'ai écrit ce code dans Kotlin

object Demo { 

    private val twitterStream = TwitterStreamFactory().instance 
    @JvmStatic 
    fun main(args: Array<String>) { 

     val listener = object : StatusListener { 

      override fun onStallWarning(warning: StallWarning?) { 
       println("Got stall warning:" + warning) 
      } 

      override fun onScrubGeo(userId: Long, upToStatusId: Long) { 
       println("Got scrub_geo event userId:$userId upToStatusId:$upToStatusId") 
      } 

      override fun onStatus(status: Status) { 
       println("@" + status.user.screenName + " - " + status.text) 
      } 

      override fun onDeletionNotice(statusDeletionNotice: StatusDeletionNotice) { 
       println("Got a status deletion notice id:" + statusDeletionNotice.statusId) 
      } 
      override fun onTrackLimitationNotice(numberOfLimitedStatuses: Int) { 
       println("Got track limitation notice:" + numberOfLimitedStatuses) 
      } 
      override fun onException(ex: Exception) { 
       ex.printStackTrace() 
      } 
     } 

     twitterStream.addListener(listener) 
     twitterStream.sample() 

    } 
} 

, mais chaque fois que je l'ai couru, je me suis exception in thread "main" java.lang.IllegalAccessError: tried to access class twitter4j.StreamListener from class co.enoobong.eno.twitter.bot.Demo at co.enoobong.eno.twitter.bot.Demo.main(Demo.kt:63)

Après enquête, Outils-> Kotlin-> Afficher Kotlin bytecode. Je me suis décompilé en Java, seulement pour découvrir que c'est ce qui était généré.

@JvmStatic 
public static final void main(@NotNull String[] args) { 
    Intrinsics.checkParameterIsNotNull(args, "args"); 
    <undefinedtype> listener = new StatusListener() { 
    public void onStallWarning(@Nullable StallWarning warning) { 
     String var2 = "Got stall warning:" + warning; 
     System.out.println(var2); 
    } 

    public void onScrubGeo(long userId, long upToStatusId) { 
     String var5 = "Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId; 
     System.out.println(var5); 
    } 

    public void onStatus(@NotNull Status status) { 
     Intrinsics.checkParameterIsNotNull(status, "status"); 
     String var2 = "@" + status.getUser().getScreenName() + " - " + status.getText(); 
     System.out.println(var2); 
    } 

    public void onDeletionNotice(@NotNull StatusDeletionNotice statusDeletionNotice) { 
     Intrinsics.checkParameterIsNotNull(statusDeletionNotice, "statusDeletionNotice"); 
     String var2 = "Got a status deletion notice id:" + statusDeletionNotice.getStatusId(); 
     System.out.println(var2); 
    } 

    public void onTrackLimitationNotice(int numberOfLimitedStatuses) { 
     String var2 = "Got track limitation notice:" + numberOfLimitedStatuses; 
     System.out.println(var2); 
    } 

    public void onException(@NotNull Exception ex) { 
     Intrinsics.checkParameterIsNotNull(ex, "ex"); 
     ex.printStackTrace(); 
    } 
    }; 
    twitterStream.addListener((StreamListener)listener); 
    twitterStream.sample(); 

}

Kotlin essayait de jeter auditeur StreamListener qui est privé dans la bibliothèque (StatusListener prolonge), d'où les IllegalAccessError

Toute idée comment résoudre s'il vous plaît?

PS: Voici une version Java du code de travail - https://github.com/yusuke/twitter4j/blob/master/twitter4j-examples/src/main/java/twitter4j/examples/stream/PrintSampleStream.java

PPS: J'utilise Kotlin 1.1.4, sur IntelliJ IDEA 2017.2.2

Répondre

2

Kotlin ajoute ces moulages pour assurer la bonne méthode est appelé lorsqu'il s'agit de méthodes surchargées. Le problème se produit car une API publique addListener attend une interface de package privé StreamListener. Essayer de créer une telle API provoque en fait un avertissement à cause de ce problème et devrait être corrigé du côté de Twitter4j.

Il n'y a aucun moyen direct de résoudre ce problème dans Kotlin, vous pouvez contourner le problème en utilisant une classe d'aide Java et peut-être une méthode d'extension:

class Twitter4jFixer { 
    public static void addListener(TwitterStream stream, StatusListener listener) { 
     stream.addListener(listener); 
    } 
} 


fun TwitterStream.addListenerFixed(listener: StatusListener) { 
    Twitter4jFixer.addListener(this, listener) 
} 
+0

Merci pour votre réponse @Kiskae. Je vais essayer ça. En fait, il fonctionne parfaitement en Java, donc pas besoin d'un fixateur – Enoobong

+0

A travaillé aussi bien que le charme. Merci beaucoup – Enoobong

0

Kiskae mettre un bon point, peut-être auteur de twitter4j fait ne pas prendre en compte les interactions avec d'autres langues jvm.

Je ne pense pas que le correctif est nécessaire.

Vous pouvez simplement mettre votre classe dans package twitter4j si vous devez utiliser l'interface privée du paquet twitter4j.StreamListener en raison de la distribution indésirable.

+0

Merci pour votre réponse @aristottl! Comment puis-je mettre ma classe dans «package twitter4j» c'est une bibliothèque externe. Juste ajouté la dépendance à mon pom.xml – Enoobong

+0

@Enoobong Vous avez juste besoin de créer un nouveau paquet avec le nom 'twitter4j'. – aristotll

+0

A travaillé comme un charme. Merci beaucoup! – Enoobong