Unresolved reference in a generic method

I am very new to Kotlin. I have a problem accessing fields of a variable passed as a parameter in a generic method of a class derived from an abstract base class.
Given:
(1) a class, whose fields I can’t access:

package com.pds.service.model
import kotlinx.serialization.Serializable
@Serializable
data class BaseDefaults(val pdsType: String, val setName: String, 
                        val coverages: MutableMap<String, String>, 
                        var policyDeductible: String, 
                        val discounts: MutableMap<String, String>) 

(2) A base abstract class containing generic method:

package com.pds.service.model
import kotlinx.serialization.Serializable
@Serializable
abstract class DeltaOperation<S>() {

    abstract fun <S> applyOperation(defaults: S) : S

    fun updatePropertiesMap(baseProperties: MutableMap<String, String>, 
                            deltaProperties: Map<String, String>) {
        for ((targetName, targetValue) in deltaProperties) {
            val coverage = baseProperties[targetName]

            if (coverage == null) {
                baseProperties[targetName] = targetValue
            } else {
                if (targetValue.isEmpty()) {
                    baseProperties.remove(targetName)
                }
                else {
                    baseProperties.replace(targetName, targetValue)
                }
            }
        }
    }
}

(3) I get “Unresolved reference” errors trying to access defaults.coverages, defaults.policyDeductible and defaults.discounts of BaseDefaults in the implementation of the abstract method in the following class:

package com.pds.service.model
import kotlinx.serialization.Serializable

@Serializable
class BaseDefaultsDeltaOperation(
    val coverages: Map<String, String>? = null,
    val policyDeductible: String? = null,
    val discounts: Map<String, String>? = null
) : DeltaOperation<BaseDefaults>() {

 override fun <BaseDefaults> applyOperation(defaults: BaseDefaults) : BaseDefaults {

        // process coverages
        if (coverages != null) updatePropertiesMap(defaults.coverages, coverages)

        // process policy deductible
        if (policyDeductible != null) defaults.policyDeductible = policyDeductible

        // process discounts
        if (discounts != null) updatePropertiesMap(defaults.discounts, discounts)

        return defaults
    }
}

What am I doing wrong? Thank you.

Please first of all ensure that all of your code ia surrounded by triple backticks like this
```
// Code goes here
```
Which looks like this when done properly:

// Code goes here

OK, I placed ``` around the source. I tried explicitly smart-casting defaults into BaseDefaults, but that doesn’t help. If I change the code to:

if ((coverages != null) && (defaults is BaseDefaults) ) updatePropertiesMap(defaults.coverages, coverages)

compiler responds that “check for instance is always true”, which makes sense, but still reports Unresolved reference on coverage field of defaults.coverage. If I type defaults. (typing ‘.’ to trigger smart completion then none of coverages, policyDeductibe or discounts are listed as accessible members of defaults object.

The problem is that you have declared applyOperation generic.

abstract class DeltaOperation<S>() {

    // Here you declare S again, so it is no longer the same S that the class is parameterized with
    //           |||
    //           vvv
    abstract fun <S> applyOperation(defaults: S) : S

As a consequence, you also had to declare it generic in the subclass - which you did:

class BaseDefaultsDeltaOperation() : DeltaOperation<BaseDefaults>() {
    // Here you declare BaseDefaults as a generic type parameter. 
    // That means that method parameter and return type do not refer
    // to the data class BaseDefaults, but instead refer to this type parameter
    //           ||||||||||||||
    //           vvvvvvvvvvvvvv
    override fun <BaseDefaults> applyOperation(defaults: BaseDefaults) : BaseDefaults

Instead, you should simply removed <S> from the declaration of applyOperation:

abstract class DeltaOperation<S>() {

    // Now S refers to the type variable of the class
    abstract fun applyOperation(defaults: S) : S
1 Like

This worked after I also removed the type specification from the overriding method:

override fun <BaseDefaults> applyOperation(defaults: BaseDefaults) : BaseDefaults {

became:

override fun applyOperation(defaults: BaseDefaults) : BaseDefaults {

Thank you for your help!