Search code examples
kotlinconstructordata-class

Data class without default constructor


I have these fields in my data class:

    val year: Int,
    val month: Int? = null,
    val day: Int? = null,

How can I insure via constructor that If day in not-null, month is not null as well? Ideally, I wanna have only 3 constructors without default nullable fields at all.

(year: Int) (year: Int, month: Int) and (year: Int, month: Int, day: Int)

Solution

  • You can create a normal class, with a private constructor, and add your overloaded constructors:

    class X private constructor(val year: Int, val month: Int?, val day: Int?) {
        constructor(year: Int) : this(year, null, null)
        constructor(year: Int, month: Int) : this(year, month, null)
        constructor(year: Int, month: Int, day: Int) : this(year, month, day as Int?)
    
        // Optionally create equals, hashCode, toString and componentN methods...
    }
    

    If you need any of the extra methods that a data class would have auto-generated, just add them manually, or let your IDE generate them for you.

    Rationale

    Why did we create a normal class? Well, you could create a data class with a private constructor, but that wouldn't prevent the user of your class from calling the copy function and passing invalid parameters to it, such as a day with a null month.

    Unlike toString, hashCode and equals, you cannot override the copy function or disable it in any way. If you declare your class as a data class, you'll get an unwanted copy function that you can't get rid of. With a normal class, you can define your own logic in the copy function, though you probably wouldn't want to define it at all as it's problematic.