MST

星途 面试题库

面试题:Kotlin复杂泛型约束与变型设计

设计一个Kotlin泛型框架,用于处理不同类型的数据计算。要求有一个泛型接口`DataProcessor<T>`,其中`T`有多个上界约束,包括`Number`以及一个自定义的`Calculable`接口。再定义一个泛型类`ProcessorImpl<U>`实现`DataProcessor<U>`接口,`U`要满足`in`变型。在`ProcessorImpl`类中实现一个方法`process`,根据`U`的类型进行不同的数值计算逻辑(例如`U`为`Int`时做加法,`U`为`Double`时做乘法等)。请完整实现该框架,并说明`in`变型在此处的意义及使用场景。
42.2万 热度难度
编程语言Kotlin

知识考点

AI 面试

面试题答案

一键面试
// 自定义Calculable接口
interface Calculable

// 泛型接口DataProcessor,T有多个上界约束
interface DataProcessor<T : Number & Calculable> {
    fun process(): Number
}

// 泛型类ProcessorImpl实现DataProcessor接口,U满足in变型
class ProcessorImpl<in U : Number & Calculable> : DataProcessor<U> {
    override fun process(): Number {
        return when (U::class) {
            Int::class -> {
                (this as? ProcessorImpl<Int>)?.let {
                    // 这里假设存在两个Int值进行加法计算
                    val num1 = 10
                    val num2 = 20
                    num1 + num2
                }?: 0
            }
            Double::class -> {
                (this as? ProcessorImpl<Double>)?.let {
                    // 这里假设存在两个Double值进行乘法计算
                    val num1 = 10.0
                    val num2 = 20.0
                    num1 * num2
                }?: 0.0
            }
            else -> 0
        }
    }
}

in变型在此处的意义及使用场景

  • 意义in变型表示逆变。在ProcessorImpl<in U>中,U是逆变类型参数。这意味着ProcessorImpl可以接受U及其所有子类型作为参数类型。例如,如果有ProcessorImpl<Number>,那么也可以使用ProcessorImpl<Int>ProcessorImpl<Double>,因为IntDouble都是Number的子类型。
  • 使用场景:当泛型类主要用于消费(接收参数)而不是生产(返回值)泛型类型的数据时,适合使用in变型。在上述代码中,ProcessorImpl类中的process方法并没有返回与U类型相关的特定值,而是返回Number类型的值,这符合消费泛型类型数据的场景。使用in变型增强了代码的灵活性和可复用性,允许在需要ProcessorImpl<Number>的地方传入ProcessorImpl<Int>ProcessorImpl<Double>等具体实现。