You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将已有父类实例的值传递给子类实例(非反射方案)

解决方案:父类实例转子类实例并传递属性

为什么强制转换行不通

你写的代码里,dog是Dog类的实例,它本质上不是Dalmatian的实例,Kotlin的类型转换as只是向编译器声明“我确认这个实例是目标类型”,但运行时会检查实际类型,不匹配就会抛出ClassCastException。所以这种强制转换的思路从根本上不可行。

优先方案:非反射实现属性传递

1. 子类添加接收父类的构造函数

直接在子类里定义构造函数接收父类实例,手动复制父类属性值,再初始化子类自身属性:

open class Dog {
    var height = -1
}

class Dalmatian: Dog() {
    var dots = -1
    
    // 新增接收Dog实例的构造函数
    constructor(dog: Dog): this() {
        // 复制父类属性
        this.height = dog.height
    }
}

fun main() {
    val dog = Dog().apply {
        height = 24
    }
    
    // 用新构造函数创建子类实例,自动继承父类属性
    val dalmatian = Dalmatian(dog).apply {
        dots = 101
    }
    
    println(dalmatian.height) // 输出24
    println(dalmatian.dots) // 输出101
}

2. 父类实现复制逻辑,子类扩展

如果父类属性较多或存在多个子类,可以在父类中编写copyTo方法,子类重写后补充自身属性的复制逻辑:

open class Dog {
    var height = -1
    
    // 父类提供属性复制方法
    open fun copyTo(dog: Dog) {
        dog.height = this.height
    }
}

class Dalmatian: Dog() {
    var dots = -1
    
    // 子类重写,补充自身属性复制
    fun copyTo(dalmatian: Dalmatian) {
        super.copyTo(dalmatian)
        dalmatian.dots = this.dots
    }
    
    // 编写从Dog实例创建自身的方法
    fun fromDog(dog: Dog): Dalmatian {
        val dal = Dalmatian()
        dog.copyTo(dal)
        return dal
    }
}

fun main() {
    val dog = Dog().apply { height = 24 }
    
    val dalmatian = Dalmatian().fromDog(dog).apply { dots = 101 }
    println(dalmatian.height) // 输出24
    println(dalmatian.dots) // 输出101
}

3. 利用数据类的copy特性(父类可改为数据类时)

如果父类可以改为数据类,它自带的copy方法能简化属性传递:

data class Dog(var height: Int = -1)

class Dalmatian(dog: Dog, var dots: Int = -1): Dog(dog.height)

fun main() {
    val dog = Dog(24)
    val dalmatian = Dalmatian(dog, 101)
    println(dalmatian.height) // 输出24
    println(dalmatian.dots) // 输出101
}

备选方案:反射实现(适合属性较多的场景)

如果父类属性数量多,手动复制过于繁琐,可以用Kotlin反射自动复制所有父类属性到子类实例:

import kotlin.reflect.full.memberProperties

open class Dog {
    var height = -1
}

class Dalmatian: Dog() {
    var dots = -1
}

fun <T: Dog> Dog.toSubclass(subclass: Class<T>): T {
    val instance = subclass.getDeclaredConstructor().newInstance()
    // 复制父类所有可变属性
    this::class.memberProperties.forEach { prop ->
        if (prop is kotlin.reflect.KMutableProperty<*>) {
            prop.set(instance, prop.get(this))
        }
    }
    return instance
}

fun main() {
    val dog = Dog().apply { height = 24 }
    
    val dalmatian = dog.toSubclass(Dalmatian::class.java).apply { dots = 101 }
    println(dalmatian.height) // 输出24
    println(dalmatian.dots) // 输出101
}

注意:反射会带来性能开销,且需要处理访问权限问题,非必要不推荐使用。

内容的提问来源于stack exchange,提问作者Developer-Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 05:25:18