2017-08-20 12 views
5

Przeszukałem z Kotlinem od niedawna i to było niesamowite!Jak sprawić, by Kotlin przestał rzucać argumenty na niewłaściwą klasę (Interfejs)

Pracowałem z biblioteką Twitter4j, aby wypróbować niektóre rzeczy za pomocą Twitter API. Napisałem ten kod w 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() 

    } 
} 

ale za każdym razem wpadłem go, mam 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)

Po dalszych badaniach, Narzędzia-> Kotlin-> Pokaż Kotlin kodu bajtowego. Dekompilowałem do Javy, ale odkryłem, że właśnie to było generowane.

@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 próbował rzucić słuchacza StreamListener który jest prywatny w Bibliotece (StatusListener rozciąga go) stąd IllegalAccessError

Wszelkie pomysły jak rozwiązać proszę?

PS: Oto działa wersja Java kodu - https://github.com/yusuke/twitter4j/blob/master/twitter4j-examples/src/main/java/twitter4j/examples/stream/PrintSampleStream.java

PPS: Używam Kotlin 1.1.4, na IntelliJ IDEA 2017.2.2

Odpowiedz

2

Kotlin dodaje te odlewane w celu zapewnienia prawidłowego sposobu jest wywoływana w przypadku przeciążonych metod. Problem występuje, ponieważ publiczny api addListener oczekuje interfejsu pakiet-prywatny StreamListener. Próba stworzenia takiego api faktycznie powoduje ostrzeżenie właśnie z powodu tego problemu i powinna zostać naprawiona na stronie Twitter4j.

Nie ma bezpośredni sposób aby to naprawić w Kotlin, można obejść ten problem za pomocą klasy pomocnika Java i być może metodę rozszerzenia:

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


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

Dzięki za odpowiedź @Kiskae. Wypróbuję to. Właściwie działa to doskonale w Javie, więc nie ma potrzeby naprawy. – Enoobong

+0

Działa również jak delikatny urok. Wielkie dzięki – Enoobong

0

Kiskae umieścić dobry punkt, Może autor twitter4j robi nie uwzględniać interakcji z innymi językami jvm.

Nie sądzę, że poprawka jest konieczna.

Możesz po prostu umieścić swoją klasę w package twitter4j, jeśli musisz użyć prywatnego interfejsu pakietu twitter4j.StreamListener z powodu niechcianego rzucania.

+0

Dzięki za odpowiedź @aristottl! Jak umieścić moją klasę w 'package twitter4j' to biblioteka zewnętrzna. Właśnie dodałem zależność do mojego pom.xml – Enoobong

+0

@Enoobong Po prostu musisz utworzyć nowy pakiet o nazwie 'twitter4j'. – aristotll

+0

Pracował jak piękny urok. Wielkie dzięki! – Enoobong

Powiązane problemy