2015-02-12 2 views
5

У меня есть метод в Котлин, который возвращает Rx Наблюдаемые из общего списка:Как обеспечить соблюдение общего типа с Котлин Interop

public fun getObservable(): Observable<List<FooBar>> { 
    return Observable.just(theList) 
} 

Поскольку список черта Котлин определяется как List<out T>, Java будет видеть тип возвращаемого Observable<List<? extends FooBar>>.

Есть ли способ сообщить компилятору Kotlin, что Java должен видеть это как Observable<List<FooBar>>?

http://kotlinlang.org/docs/reference/generics.html

Обновлено правильно показать проблему.

+0

Путь вокруг этого использовать 'MutableList', однако это не помогает, если' GetList() 'запрашивать неизменяемый тип возвращаемого значения. –

+0

Не можете ли вы просто нарисовать на Java? –

+0

Да, это возможно, однако я бы предпочел не помешать каждому экземпляру этой ситуации бросать. Кроме того, вопрос заключается скорее в любопытстве к языковым преимуществам Котлина для этой ситуации. –

ответ

3

Редактировать: изменено в Kotlin Beta 4. См. answer Jayson Minard.

Я вижу два варианта:

  • Первый вернуть Observable<MutableList<FooBar>>. Поскольку List является неизменным в котлин, он объявляется как List<out T>, поскольку объекты типа T могут быть приняты только вне.
    MutableList С другой стороны, это истинный эквивалент Java List: поскольку он изменен, он объявлен как MutableList<T>.
    Так что ваша функция будет:

    public fun getObservable(): Observable<MutableList<FooBar>> 
         = Observable.just(theList) 
    

    Проблема с этим решением является то, что вы должны использовать его в Котлин, вы предоставляете «слишком много» доступ к вашему списку, если вы только хотели иметь Наблюдаемые неизменного списка ,

  • Второй вариант заключается в написании «прокси» метод в Java, что делает бросок раз и навсегда:

    @SuppressWarnings("unchecked") 
    public static Observable<List<String>> _getObservable() { return (Observable) TestPackage.getObservable(); } 
    

    Это некрасиво, но это работает, и это не нарушает Котлин

    Тем не менее, я полагаю, вы используете R44JAX Observable, так почему бы не использовать эту возможность для обеспечения неизменного семантического семпла kotlin в Java?

    public static Observable<List<String>> _getObservable() { 
        return TestPackage.getObservable().map(new Func1<List<? extends String>, List<String>>() { 
         @Override 
         public List<String> call(List<? extends String> list) { 
          return Collections.unmodifiableList(list); 
         } 
        }); 
    } 
    
+0

Мне нравится первый вариант, так как java.util.List изменен, однако мне нравится ваш третий вариант для передовой совместимости, так как я вижу, как мы перемещаем больше кода в Kotlin. Благодаря! –

+1

Это поведение изменилось, см. [Новый ответ ниже] (http://stackoverflow.com/a/34561939/3679676). –

5

Вы можете контролировать, как Java видит дженерики Котлин с помощью JvmWildcard и JvmSuppressWildcards аннотацию. Он был добавлен в Kotlin 1.0 Beta 4 (см. announcement).

Это изменение означает, что ваш код будет уже изменен, чтобы быть в порядке, и больше не генерирует шаблон. Поскольку новый параметр по умолчанию не использует их во многих случаях, и вы можете вернуть их с помощью аннотаций или подавить их, когда это нежелательно.

Анонс этого изменения состояния:

Java Wildcards

Были проблемы с тем, как Котлин переведенный типы вариант, например, должен ли List быть List на Java или просто List. Тонкости детали в сторону, мы сделали следующее:

  • По умолчанию, мы не генерируют символы в возвращаемых типов и где они не имеют никакого смысла
  • Когда подстановочные требуется, можно применять свое присутствие аннотации типа : Список < @JvmWildcard String> всегда перечисляют в Java
  • Когда нам нужно избавиться от маски, мы можем использовать @JvmSuppressWildcards (это могут быть использованы на типе или любого заявления, содержащего его)

Примеры:

fun foo(l: List<String>) // in Java: List<String> (String is final) 
fun foo(l: List<@JvmWildcard String>) // in Java: List<? extends String> 

interface Open {} 
fun bar(p: List<Open>) // in Java: List<? extends Open> (Open is not final) 
@JvmSuppressWildcards 
fun bar(p: List<Open>) // in Java: List<Open> 

Так применяя это на ваш вопрос, если вы по-прежнему возникают проблемы:

@JvmSuppressWildcards 
public fun getObservable(): Observable<List<FooBar>> { 
    return Observable.just(theList) 
} 
Смежные вопросы