简体   繁体   中英

Unresolved reference: T

I need to create a data class:

data class MyClass(val b: Boolean,
               val s: String,
               val flags: Map<Key<T>, T>)

This does not compile due to "Unresolved reference: T"

In the flags map, I need to have Key<String>, String and Key<Int>, Int pairs, but NOT Key<String>, Int

Any ideas on how I can achieve this?

You must define the generic for the class:

data class MyClass<T>(val b: Boolean,
               val s: String,
               val flags: Map<Key<T>, T>)

You can't do this directly through the type system, you will have to use encapsulation to ensure the types of key and value are consistent. This problem exists in Java as well.

The solution given by others doesn't work, since you'd only be able to put one type of key/value into the map (the idea of having a Map<Key<T>, T> is somewhat flawed):

val map = mutableMapOf<Key<String>, String>() // what to put as generic params here?
map[Key<String>()] = "blah" // works
map[Key<Int>()] = 3 // doesn't work!
map[Key<Int>()] = "blah" // compiler error (as intended)

or:

val map = mutableMapOf<Key<*>, Any?>()
map[Key<String>()] = "blah" // works
map[Key<Int>()] = 3 // works
map[Key<Int>()] = "blah" // works, but is wrong.

You'd have to for instance write your own encapsulation around a map that ensures a key always matches a value:

class MutableKeyMap {
    private val map = mutableMapOf<Key<*>, Any?>() // private / encapsulated

    operator fun <T> get(key: Key<T>): T {
        return map[key] as T
    }

    operator fun <T> set(key: Key<T>, value: T): Unit { // Key's T must match value's type.
        map[key] = value
    }
}

(You could add an immutable super-interface if you'd like)

And then use that as a field:

data class MyClass(val b: Boolean,
               val s: String,
               val flags: MutableKeyMap)

...

val map = MutableKeyMap()
map[Key<String>()] = "blah" // works
map[Key<Int>()] = 3 // works
map[Key<Int>()] = "blah" // compiler error (as intended)

You've forgotten about this:

 data class MyClass<T>(val b: Boolean,
 // ----------------^
               val s: String,
               val flags: Map<Key<T>, T>)

For more info: Generics

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