2017-08-20 13 views
5

Tôi đã đi loanh quanh với Kotlin gần đây, và thật tuyệt vời!Làm thế nào để làm cho Kotlin dừng lập luận đối với lớp sai (Giao diện)

Tôi đã làm việc với thư viện Twitter4j để thử một số nội dung với API Twitter. Tôi đã viết mã này trong 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() 

    } 
} 

nhưng mỗi lần tôi chạy nó, tôi nhận 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)

Sau khi điều tra thêm, Tools-> Kotlin-> Hiển thị Kotlin Bytecode. Tôi dịch ngược sang Java, chỉ để khám phá ra rằng đây là những gì đã được tạo ra.

@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 đã cố gắng để cast nghe để StreamListener đó là tin trong thư viện (StatusListener mở rộng nó) do đó IllegalAccessError

Bất kỳ ý tưởng làm thế nào để giải quyết được không?

PS: Đây là một phiên bản Java làm việc của mã - https://github.com/yusuke/twitter4j/blob/master/twitter4j-examples/src/main/java/twitter4j/examples/stream/PrintSampleStream.java

PPS: Tôi đang sử dụng Kotlin 1.1.4, trên IntelliJ IDEA 2017.2.2

Trả lời

2

Kotlin thêm các phôi để đảm bảo đúng phương pháp được gọi khi xử lý các phương thức quá tải. Vấn đề xảy ra vì một api công cộng addListener mong đợi một giao diện gói riêng tư StreamListener. Cố gắng tạo ra một api như vậy thực sự gây ra một cảnh báo chính xác vì vấn đề này và nên được cố định trên bên Twitter4j.

Không có cách trực tiếp để sửa lỗi này trong Kotlin, bạn có thể làm việc xung quanh vấn đề bằng cách sử dụng một lớp helper Java và có lẽ một phương pháp khuyến nông:

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


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

Cảm ơn bạn đã phản hồi @Kiskae. Tôi sẽ thử cái này. Trên thực tế nó hoạt động hoàn hảo trong Java vì vậy không cần cho một fixer – Enoobong

+0

Làm việc như quyến rũ tốt quá. Rất cám ơn – Enoobong

0

Kiskae đặt một điểm tốt, Có lẽ tác giả của twitter4j làm không tương tác với các ngôn ngữ jvm khác.

Tôi không nghĩ rằng việc sửa chữa là cần thiết.

Bạn chỉ có thể đưa lớp học của mình vào package twitter4j nếu bạn phải sử dụng giao diện riêng tư gói twitter4j.StreamListener do truyền không mong muốn.

+0

Cảm ơn bạn đã phản hồi @aristottl! Làm thế nào để đưa lớp của tôi vào 'gói twitter4j' đó là một thư viện bên ngoài. Chỉ cần thêm phụ thuộc vào pom.xml của tôi – Enoobong

+0

@Enoobong Bạn chỉ cần tạo một gói mới có tên 'twitter4j'. – aristotll

+0

Làm việc như vẻ đẹp quyến rũ. Cảm ơn nhiều! – Enoobong

Các vấn đề liên quan