Reputation:
I couldn't find a better title for describing how can I avoid code duplication (require expressions) in this Kotlin class:
class Person(email: String) {
var email: String = email
set(value) {
require(value.trim().isNotEmpty(), { "The email cannot be blank" })
field = value
}
init {
require(email.trim().isNotEmpty(), { "The email cannot be blank" })
}
}
In java, I would have a setter with the name validation and then I would call it from the constructor.
What is the idiomatic way of doing that in Kotlin ?
Upvotes: 9
Views: 5403
Reputation: 185
There's an alternative way, to use companion object and create object there, it's kind like the constructor and meets your requirement in a different way.
data class Target(
val date: LocalDate,
val id: Long,
val stringId: String,
) {
companion object {
fun create(date: LocalDate, id: Long, stringId: String?,): Target{
val nonNullStringId= if (stringId.isNullOrEmpty()) "" else stringId
return Target(date, id, nonNullStringId)
}
}
}
Upvotes: 0
Reputation: 1305
You can do it just like in java. You just have to remove the primary constructor and make a secondary constructor instead. You will have to do the assignment manually though, like in java. So it would look like this:
class Person {
constructor(email: String) {
this.email = email
}
var email: String
set(value) {
require(value.trim().isNotEmpty(), { "The email cannot be blank" })
field = value
}
}
Upvotes: 4
Reputation: 14029
Define the member outside of the constructor, and invoke the setter from the init block:
class Person(initialEmail: String) { // This is just the constructor parameter.
var email: String = "" // This is the member declaration which calls the custom setter.
set(value) { // This is the custom setter.
require(value.trim().isNotEmpty(), { "The email cannot be blank" })
field = value
}
init {
// Set the property at construct time, to invoke the custom setter.
email = initialEmail
}
}
Upvotes: 2
Reputation: 14029
Use a delegate. There's the observable() delegate that already exists.
class Person(initialEmail: String) { // No "var" any more.
var email: String by Delegates.observable("") {
_, _, newValue ->
// This code is called every time the property is set.
require(newValue.trim().isNotEmpty(), { "The email cannot be blank" })
}
init {
// Set the property at construct time, to invoke the delegate.
email = initialEmail
}
}
Upvotes: 3