Reputation: 1023
So I have the code below, written in Kotlin.
I'm getting a compilation error on the last instruction line (return params.keys.containsAll(MANDATORY_PARAMS)
), the compiler says Unsolved reference: MANDATORY_PARAMS
, but I don't really get why.
I thought companion objects were supposed to have some kind of visibility into the attributes of the classes they "keep company to".
What could I do to solve this? How could I make MANDATORY_PARAMS
visible to both MandatoryParametersValidator
and its companion object?
(disclaimer: this code is being migrated from Java to Kotlin. On Java version, mandatoryParametersHaveBeenProvided
used to be a static method on the same class.)
import javax.validation.ConstraintValidator
import javax.validation.ConstraintValidatorContext
class MandatoryParametersValidator : ConstraintValidator<EnforceMandatoryParameters, Map<String, String>> {
val MANDATORY_PARAMS = arrayOf("bookingReference", "lastName")
override fun initialize(constraintAnnotation: EnforceMandatoryParameters?) {
// do nothing
}
override fun isValid(params: Map<String, String>, context: ConstraintValidatorContext?): Boolean {
MANDATORY_PARAMS
.filter { !params.containsKey(it) }
.forEach { parameterName ->
context?.disableDefaultConstraintViolation()
context?.buildConstraintViolationWithTemplate("Mandatory parameter $parameterName is missing.")?.addConstraintViolation()
}
return mandatoryParametersHaveBeenProvided(params)
}
companion object {
fun mandatoryParametersHaveBeenProvided(params: Map<String, String>) : Boolean {
return params.keys.containsAll(MANDATORY_PARAMS)
}
}
}
Thanks a lot!
Upvotes: 1
Views: 1892
Reputation: 89608
MANDATORY_PARAMS
is an instance property in this case. Every instance of MandatoryParametersValidator
will have its own MANDATORY_PARAMS
property, even though it will always be the same value.
Companion objects, on the other hand, are singletons (just like every other object
), and they aren't tied to any specific instance of MandatoryParametersValidator
. So to access that property, you either need to pass an instance of the class to the function inside the companion object and read the property that it has, or put your property inside the companion object.
This is just like the way that you can't access instance fields and methods from a static function in Java. What you have now is roughly equivalent to this Java code:
class MandatoryParametersValidator {
String[] MANDATORY_PARAMS = ...;
static bool mandatoryParametersHaveBeenProvided(Map<String, String> params) {
...
}
}
Upvotes: 1
Reputation: 73570
You need to do two things to get this working
Move MANDATORY_PARAMS
into the companion object. The companion object is like the static parts of the class in Java. And MANDATORY_PARAMS
would be static final
in Java.
Change the type of MANDATORY_PARAMS
from Array<String>
to List<String>
(since containsAll
requires a Collection
.)
The fixed code looks like this.
...
companion object {
val MANDATORY_PARAMS = listOf("bookingReference", "lastName")
fun mandatoryParametersHaveBeenProvided(params: Map<String, String>) : Boolean {
return params.keys.containsAll(MANDATORY_PARAMS)
}
}
}
Upvotes: 3