如何通过继承正确构造Room实体

时间:2019-07-17 01:02:37

标签: android inheritance kotlin constructor android-room

我有一个我希望每个实体都拥有的字段列表,因此我创建了一个基本实体。

open class Syncable(
    @ColumnInfo(name = "id")
    var oid: String? = null,
    @ColumnInfo(name = "created")
    var created: Long = System.currentTimeMillis(),
    @ColumnInfo(name = "updated")
    var updated: Long = System.currentTimeMillis())

然后我有许多实体都继承自该实体,例如:

@Entity(tableName = ProfileContract.TABLE_NAME, indices = [Index(value = ["id"], unique = true)])
data class Profile(ColumnInfo(name = "first_name")
     var firstName: String,
     @ColumnInfo(name = "last_name")
     var lastName: String,          
     @ColumnInfo(name = "email")
     var email: String? = null,
     @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "row_id")
     var id: Long? = null) : Syncable()

现在,当我想构造这些实体之一时。我该怎么办?

我目前正在这样做:

val newProfile = Profile(
                    "Bob",
                    "Shoruncle",
                    "bobshoruncle@test.com)
newProfile.id = "bob1"
newProfile.created = 1233L
newProfile.updated = 1233L

有没有办法做到这一点:

val newProfile = Profile("Bob", "Shoruncle", "bobshoruncle@test.com","bob1",1233L,1233L)

3 个答案:

答案 0 :(得分:1)

@a_local_nobody处在正确的轨道上,但答案更为复杂。

我需要在子类上创建一个自定义构造函数,以设置父类的字段

 @Entity(tableName = ProfileContract.TABLE_NAME, indices = [Index(value = ["id"], unique = true)])
 data class Profile(ColumnInfo(name = "first_name")
 var firstName: String,
 @ColumnInfo(name = "last_name")
 var lastName: String,          
 @ColumnInfo(name = "email")
 var email: String? = null,
 @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "row_id")
 var id: Long? = null) : Syncable() {
 @Ignore constructor(
   firstName: String,
   lastName: String,
   email: String,
   id: String,
   created: Long,
   updated:Long) : this(firstName, lastName, email) {
     this.id = id
     this.created = created
     this.updated = updated
   }
 }

现在,对于外部创作者来说,它看起来像一个大型构造函数

答案 1 :(得分:0)

您可能不能做这样的事情吗?

open class Syncable(
    @ColumnInfo(name = "id")
    var oid: String? = null,
    @ColumnInfo(name = "created")
    var created_on: Long = System.currentTimeMillis(),
    @ColumnInfo(name = "updated")
    var updated_on: Long = System.currentTimeMillis())

@Entity(tableName = ProfileContract.TABLE_NAME, indices = [Index(value = ["id"], unique = true)])
data class Profile(ColumnInfo(name = "first_name")
     var firstName: String,
     @ColumnInfo(name = "last_name")
     var lastName: String,          
     @ColumnInfo(name = "email")
     var email: String? = null,
     @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "row_id")
     var id: Long? = null) : Syncable(){
    constructor(profile: Account) : this(profile.firstName, profile.lastName, profile.email, profile.id,profile.oid, profile.created_on, profile.updated_on)
}

基本上,尝试尝试为kotlin调用超级方法构造器

我试图根据此处的帖子作为答案,请看一下,希望对您有所帮助:Call super class constructor in Kotlin, Super is not an expression

答案 2 :(得分:0)

您可能想使用@Embedded批注(documentation)。

下面是QuizTest对象的示例,它们每个对象都有一个嵌套的Stats对象:

data class Stats(
        @ColumnInfo(name = "right") val right: Int = 0,
        @ColumnInfo(name = "wrong") val wrong: Int = 0
)

// You can also embed an object multiple times and specify a prefix
// to differentiate the column names of the embedded fields
@Entity(tableName = "quiz")
data class Quiz(
        @PrimaryKey
        @ColumnInfo(name = "id") val id: Int,
        @ColumnInfo(name = "name") val name: String,
        @Embedded(prefix = "nov_") val noviceStats: Stats = Stats(),
        @Embedded(prefix = "adv_") val advancedStats: Stats = Stats(),
        @Embedded(prefix = "exp_") val expertStats: Stats = Stats()
)

@Entity(tableName = "test")
data class Test (
        @PrimaryKey
        @ColumnInfo(name = "id") val id: Int,
        @ColumnInfo(name = "name") val name: String,
        @Embedded val stats: Stats = Stats()
)

/**
 * You'll get the following tables:
 * 
 * quiz
 * ----
 * id | name | nov_right | nov_wrong | adv_right | adv_wrong | exp_right | exp_wrong
 * 
 * test
 * ----
 * id | name | right | wrong
 */