2016-02-10 4 views
7

Я пытаюсь сделать интерфейс Parcelable, как таковой мне нужен интерфейс, как этотCompanion Объекты в Котлин Интерфейсы

interface AB : Parcelable { 
    companion object { 
     val CREATOR : Parcelable.Creator<AB> 
    } 
} 

и мои два класса А и В, глядя, как

data class A (...): Parcelable{ 
    ... 
    companion object { 
     val CREATOR : Parcelable.Creator<AB> = object : Parcelable.Creator<AB> { 
      override fun newArray(size: Int): Array<AB?> { 
       return arrayOfNulls(size) 
      } 

      override fun createFromParcel(parcel: Parcel): AB { 
       return A(parcel) 
      } 

     } 
    } 

Я пытаясь реализовать такой интерфейс в котлине. Кажется, класс интерфейс не позволяет ТВОРЦУ

Возможно, я беру неправильный подход,
У меня есть parcelable, который содержит список классов, А или B , так что я делаю

parcel.readTypedList(this.list, AB.CREATOR) 

Я требую, чтобы список был либо A, либо B, и именно поэтому я использую интерфейс.

У кого-нибудь есть совет или возможное решение?

+0

Если вы получаете определенную ошибку компиляции, пожалуйста, напишите ошибку. –

+0

Спасибо всем за вашу помощь, я не думаю, что хорошо описал свою проблему. В любом случае я решил это, выполнив этот ответ https://stackoverflow.com/questions/22576709/abstract-class-as-parcelable и переписав java в kotlin. Хорошо работает, только я больше не использую классы данных. Я попробовал ParcelPaper, но это не сработало для меня – user5910912

ответ

7

По convention классов, реализующих интерфейс Parcelable также должен иметь непустое статическое поле называется CREATOR типа, который реализует интерфейс Parcelable.Creator.

Необходимо указать аннотацию CREATOR с аннотацией @JvmField, чтобы опубликовать ее как общедоступное статическое поле в классе данных.

Также вы можете взглянуть на https://github.com/grandstaish/paperparcel - обработчик аннотации, который автоматически генерирует безопасные посылки для Kotlin и Java.

+0

Не думаю, что первая часть вашего ответа поможет. Вторая часть полезна сама по себе. –

+0

@JaysonMinard В этой ситуации требуется удовлетворить Parcelable convention, я отредактировал ответ, чтобы объяснить, почему. – Ilya

+0

Огромное спасибо, было бы также 'JvmStatic', или' JvmField' делает это также, когда в сопутствующем объекте? –

11

В Kotlin интерфейс может иметь companion object, но он не является частью контракта, который должен реализовываться классами, реализующими интерфейс. Это всего лишь объект, связанный с интерфейсом, который имеет один экземпляр singleton. Таким образом, это место, где вы можете хранить вещи, но ничего не значит для класса реализации.

Однако вы можете иметь интерфейс, который реализуется классом companion object. Может быть, вы хотите что-то больше, как это:

interface Behavior { 
    fun makeName(): String 
} 

data class MyData(val data: String) { 
    companion object: Behavior { // interface used here 
     override fun makeName(): String = "Fred" 
    } 
} 

Обратите внимание, что класс данных не реализует интерфейс, но его companion object делает.

companion object на интерфейсе будет полезно для хранения констант или вспомогательные функции, связанные с интерфейсом, такие как:

interface Redirector { 
    fun redirectView(newView: String, redirectCode: Int) 

    companion object { 
     val REDIRECT_WITH_FOCUS = 5 
     val REDIRECT_SILENT = 1 
    } 
} 

// which then can be accessed as: 
val code = Redirector.REDIRECT_WITH_FOCUS 
+3

Раньше было разрешено иметь общие ограничения, в которых говорилось о таких вещах, как «любой класс, у которого есть сопутствующий объект, реализующий Xyz» и который исчез в начале Kotlin, надеюсь, что он появится в будущем как еще один тип общих ограничений. Тогда вы могли бы в общих чертах рассказать о классе и его компаньоне вместе. –

+0

Я предполагал, что это все еще есть положение вещей по состоянию на 4/13/17 в Котлине? –

+0

@AdamHughes Вы имеете в виду общие ограничения, которые включают объекты-компаньоны? Если так, я не думаю, что они вернулись. –