简体   繁体   中英

Kotlin - attribute visibility to companion object

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!

You need to do two things to get this working

  1. 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.

  2. 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)
        }
    }
}

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) {
        ...
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM