Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Room cannot pick a constructor since multiple constructors are suitable error

I try to implement persistent library in my android kotlin project, but catch this error on compile time:

error: Room cannot pick a constructor since multiple constructors are suitable. Try to annotate unwanted constructors with @Ignore.

Error code:

@Entity
data class Site(
        var name: String = "",
        var url: String = "",
        @PrimaryKey(autoGenerate = true) var id: Long = 0)
like image 992
Gogi Bobina Avatar asked Jun 19 '17 00:06

Gogi Bobina


People also ask

Can you have multiple constructors?

A class can have multiple constructors that assign the fields in different ways. Sometimes it's beneficial to specify every aspect of an object's data by assigning parameters to the fields, but other times it might be appropriate to define only one or a few.

Can a class have multiple constructors with different names?

The technique of having two (or more) constructors in a class is known as constructor overloading. A class can have multiple constructors that differ in the number and/or type of their parameters. It's not, however, possible to have two constructors with the exact same parameters.

What is the purpose of multiple constructors?

That's the purpose for multiple constructors. To give the programmer flexibility on saying what an object can be created from and which variables need to be initialized in the first place.


3 Answers

I had this error because Kotlin apparently generates multiple Java constructors for a single Kotlin constructor with default argument values. Working code see next:

@Entity
data class Site(
        var name: String,
        var url: String,
        @PrimaryKey(autoGenerate = true) var id: Long)
like image 171
Gogi Bobina Avatar answered Oct 24 '22 05:10

Gogi Bobina


None of the above solutions are good, since they work but may cause errors.

Kotlin's Data Class generates several Methods using the default constructor. That means that equals(), hashCode(), toString(), componentN() functions and copy() is generated using the attributes you assign to your constructor.

Using the above solutions like

@Entity data class Site(@PrimaryKey(autoGenerate = true) var id: Long) {
    @Ignore constructor() : this(0)
    var name: String = ""
    var url: String = ""
} 

generates all the above listed methods only for id. Using equals leads to unwanted quality, same as toString(). Solving this requires you to have all attributes you want to process inside the constructor and add a second constructor using ignore like

@Entity data class Site(
    @NonNull @PrimaryKey(autoGenerate = true) var id: Long,
    var name: String = "",
    var url: String = "") {
    @Ignore constructor(id = 0, name = ", url = "") : this()
} 

You should really keep in mind, that you usually use data classes to have methods like toString and copy. Only this solution is working to avoid unwanted bugs during runtime.

like image 28
Emanuel S Avatar answered Oct 24 '22 04:10

Emanuel S


This worked for me:

@Entity
data class Site(
    @PrimaryKey(autoGenerate = true) var id: Long = 0),
    var name: String = "",
    var url: String = "",
    @Ignore var ignored: String? = null
)
like image 2
Edwin Bello Avatar answered Oct 24 '22 06:10

Edwin Bello