首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型擦除有困难

类型擦除有困难
EN

Stack Overflow用户
提问于 2022-01-20 21:14:35
回答 1查看 111关注 0票数 2

我有这样的事情:

代码语言:javascript
复制
import kotlin.reflect.KClass

class Quantity<T> { 
    /* ... */ 
}

class Field<T : Any> { 
    val type: KClass<T> get() = TODO("This is initialized, don't worry about implentation details, just know that fields know their type.")

    fun initValue(value: T) {
        /* Do something very useful */
    }

    /* Other methods */

    class Template<T : Any> {
        fun initFieldWithValue(value: T): Field<T> {
            return Field<T>().apply {
                this.initValue(value)
            }
        }
    }
}


class ComponentClass(
    val fieldsTemplates: Map<String, Field.Template<*>>
) {
    inner class Instance(field: Map<String, Field<*>>)

    fun new(fieldValues: Map<String, Quantity<*>>): Instance {
        val fields = mutableMapOf<String, Field<*>>()
        for ((fieldName, template) in fieldsTemplates) {
            fields[fieldName] = fieldsTemplates
                .getValue(fieldName)    
                .initFieldWithValue(fieldValues.getValue(fieldName) /* Here a type error */)
        }
        return Instance(fields)
    }
}

正如您可能猜到的那样,这是作为一种“运行时方式”来创建属于自己的字段的类(Field<T>类),每个类都具有一个类型化值(由Quantity<T>表示)。

问题是,这段代码无法编译,因为在创建未来的fieldValues方法中的Instance的不同字段时,从new中检索的数量不能保证是填充到的字段所需的类型。

问题是,我需要检查,因为用Field<Quantity<String>>填充Quantity<Int>显然不是一个好主意,但是由于类型擦除,我无法确保传入的数量是好类型。

知道吗?还有一个想法:Field知道它们的类型是什么,这要归功于它们的type属性,但不幸的是,我不能对Quantity类做同样的事情.

EN

回答 1

Stack Overflow用户

发布于 2022-01-20 22:36:35

您的initFieldWithValue函数强制执行参数的类型,以匹配模板/字段已知的类型。但是在您的new函数中,模板是一个Template<*>,因为您从一个集合中检索它,其中的值就是这种类型。

泛型的目的是加强编译时间检查,以便在引擎盖下安全和自动地进行转换。这只有在编译时知道您的类型时才有用。在这种情况下,在编译时不知道类型,所以泛型会阻止代码编译。这就是泛型应该做的事情:如果编译器不能检查它们的类型是否匹配,就阻止代码编译。

如果希望编译此代码,则应更改initFieldWithValue,使其不强制使用泛型。您可以手动检查类型,如果错误,可以抛出错误或提前退出。这将取决于您的代码在其他地方,以确保您没有混合和匹配类型。

下面是一个可以工作的版本的示例。它的类型检查需要Kotlin反射库。如果您只针对JVM,则可以使用Java方法来进行此检查。

代码语言:javascript
复制
class Template<T : Any> {
    val type: KClass<T> get() = TODO()

    /**
     * @throws IllegalStateException if [value] is not of the same type 
     * as this Template's [type]. 
     */
    fun initFieldWithValue(value: Any): Field<T> {
        if (!value::class.isSubclassOf(type)) {
            error("Invalid value type for Field type of $type")
        }
        return Field<T>().apply {
            @Suppress("UNCHECKED_CAST") // we manually checked it above
            initValue(value as T)
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70793469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档