@Parcelize аннотация вместе с наследованием
Я не могу создать общую структуру вместе с аннотацией @parcelize. Я хочу, чтобы конструктор использовался как конструктор для Jason, Room и Parcelable.
Предположим, у нас есть класс
@Parcelize
class Food(var taste: String = "")
Теперь два решения, которые приходят мне в голову сначала
1. жалуется, что вкус должен быть var или val, чтобы иметь пригодный для использования конструктор Parceable
@Parcelize
class FastFood(var callory:String = "", taste: String): Food(taste) // error
2. жалуется, что я должен явно овверидировать вкус - так каковы преимущества полиморфизма?
@Parcelize
class FastFood(var callory: String = "", var taste: String): Food(taste) // error
Как я могу эффективно использовать наследование вместе с вашей библиотекой?
4 ответа
В Kotlin, если вы добавите значение в конструктор 'val' или 'var', оно станет свойством класса. Чтобы использовать Parceable, вам нужно добавить его, потому что без него Parcelable.Creator не сможет получить к нему доступ. Затем вам нужно добавить модификатор 'open' к классу Food и к свойству 'вкус', потому что в Kotlin все final по умолчанию, так что вы сможете переопределить значение вкуса.
@Parcelize
open class Food(open val taste: String)
@Parcelize
class FastFood(var callory:String = "", override val taste: String): Food(taste)
Я не смог найти идеального решения с помощью @Parcelize, но есть два слегка ошибочных способа.
1) Сделайте базовый класс абстрактным и используйте только @Parcelize в дочерних элементах. Это означает, что у вас не может быть экземпляра родительского объекта, но иногда это нормально. Если вы можете себе это позволить, это эффективное решение.
abstract class Food : Parcelable {
abstract var taste: String
}
@Parcelize
class FastFood(var callory: String = "", override var taste: String = "") : Food()
2) Возможно, вам нужно создать экземпляр родителя. Один из способов сделать это - сделать базовый класс не родительским, а родительским для родительского и дочернего классов. К сожалению, это немного нарушает иерархию классов, и FastFood не будет разновидностью еды, а скорее будет разновидностью BaseFood.
abstract class BaseFood : Parcelable {
abstract var taste: String
}
@Parcelize
class Food(override var taste: String = "") : BaseFood()
@Parcelize
class FastFood(var callory: String = "", override var taste: String = "") : BaseFood()
По состоянию на декабрь 2021 года проблема все еще существует, я не могу использовать наследование с @Parcelize.
Родительский класс:
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
open class Parent (
var parentString : String
) : Parcelable {
constructor(): this("")
}
Дочерний класс (который наследует родительский класс)
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class Child (
var childString : String
) : Parent(), Parcelable {
constructor() : this("")
}
Я отправляю объект дочернего класса из ActivityA в ActivityB
Код ActivityA: (Отправитель)
val child = Child()
child.childString = "THIS IS CHILD"
child.parentString = "THIS IS PARENT"
val intent = Intent(this, ActivityB::class.java)
val bundle = Bundle()
bundle.putParcelable("parcel", child)
intent.putExtra("bundle", bundle)
startActivity(intent)
Код ActivityB: (Получатель)
val bundle = intent.getBundleExtra("bundle")
val child = bundle?.getParcelable<Child>("parcel") as Child
Log.e("Child Class c", child.childString) //THIS IS CHILD
Log.e("Parent Class p", child.parentString) //"" <- issue
child.parentString = "" вместо ЭТО РОДИТЕЛЬ , который является проблемой @Parcelize
Основываясь на предложениях из проблемы YouTrack , мне удалось использовать обходной путь, основанный наinterface
декларация примерно такая:
interface MyInterface {
val value01: String
val value02: String
}
@Parcelize
data class Child01(
override val value01: String,
override val value02: String
) : MyInterface, Parcelable
@Parcelize
data class Child02(
override val value01: String,
override val value02: String
) : MyInterface, Parcelable