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

如何检查SignalPayload子类是否实现IConvertible接口及相关问题

Let's tackle your two issues step by step, with corrected and annotated Kotlin code:

1. Check if a KClass<SignalPayload> implements IConvertible

To determine if the given KClass implements the IConvertible interface, we can use Kotlin's reflection API with IConvertible::class.isAssignableFrom(type). This checks if the target type is a subclass or implementation of IConvertible. We'll also improve instance creation to use the primary constructor directly, which is safer than relying on createInstance() for classes that might not have an explicit no-arg constructor.

2. Fix SignalChannel's type parameters and instance logic

Making SignalChannel a generic class with a type constraint that requires the type to extend both SignalPayload and IConvertible ensures full type safety. This avoids unsafe casts and guarantees that setFromPayload can be called on mPayload without runtime errors.

Here's the full corrected code:

sealed class SignalPayload {
    companion object {
        fun trueTypeInstance(type: KClass<out SignalPayload>) : SignalPayload? {
            // Check if the target type implements IConvertible
            return if (IConvertible::class.isAssignableFrom(type)) {
                // Use primary constructor to create instance (safer for data classes with defaults)
                type.primaryConstructor?.call()
            } else {
                null // Return null if the type doesn't meet the requirement
            }
        }
    }
}

object Empty : SignalPayload()
data class BadData(val message: String = "BAD") : SignalPayload() {
    override fun toString(): String {
        return message
    }
}

// Fixed class names to follow Kotlin's PascalCase convention
data class PayloadString(private var payload: String = "") : SignalPayload(), IConvertible {
    override val asBool: Boolean get() = payload.toBoolean()
    override val asInt: Int get() = payload.toIntOrNull() ?: 0
    override val asFloat: Float get() = payload.toFloatOrNull() ?: 0F
    override val asString: String get() = payload

    override fun setFromPayload(data: IConvertible) {
        payload = data.asString
    }
}

data class PayloadInt(private var payload: Int = 0) : SignalPayload(), IConvertible {
    override val asBool: Boolean get() = payload != 0
    override val asInt: Int get() = payload
    override val asFloat: Float get() = payload.toFloat()
    override val asString: String get() = payload.toString()

    override fun setFromPayload(data: IConvertible) {
        payload = data.asInt
    }
}

data class PayloadFloat(private var payload: Float = 0F) : SignalPayload(), IConvertible {
    override val asBool: Boolean get() = payload != 0F
    override val asInt: Int get() = payload.toInt()
    override val asFloat: Float get() = payload
    override val asString: String get() = payload.toString()

    override fun setFromPayload(data: IConvertible) {
        payload = data.asFloat
    }
}

data class PayloadBool(private var payload: Boolean = false) : SignalPayload(), IConvertible {
    override val asBool: Boolean get() = payload
    override val asInt: Int get() = if (payload) 1 else 0
    override val asFloat: Float get() = if (payload) 1F else 0F
    override val asString: String get() = payload.toString()

    override fun setFromPayload(data: IConvertible) {
        payload = data.asBool
    }
}

interface IConvertible {
    val asBool: Boolean
    val asInt: Int
    val asFloat: Float
    val asString: String
    fun setFromPayload(data: IConvertible)
}

interface IArriving {
    fun onNewPayload(data: SignalPayload, sender: IArriving?)
}

// Generic SignalChannel with cross-type constraint for type safety
class SignalChannel<T : SignalPayload & IConvertible>(
    val idx: Int,
    val type: KClass<T>,
    val name: String = ""
) : IArriving {
    var mPayload: SignalPayload = Empty

    override fun onNewPayload(data: SignalPayload, sender: IArriving?) {
        // Initialize mPayload if it's still in the default Empty state
        if (mPayload is Empty) {
            SignalPayload.trueTypeInstance(type)?.let {
                mPayload = it
            } ?: run {
                // Fallback to BadData if initialization fails
                mPayload = BadData("Unsupported payload type")
            }
        }

        // Only execute conversion if both payloads implement IConvertible
        if (mPayload is IConvertible && data is IConvertible) {
            (mPayload as IConvertible).setFromPayload(data)
        } else {
            mPayload = BadData("Cannot convert incoming payload")
        }
    }
}

Key Improvements:

  • Class Naming: Updated class names to follow Kotlin's PascalCase convention for consistency.
  • Reflection Safety: Used primaryConstructor?.call() instead of createInstance() to handle edge cases where classes might not have an explicit no-arg constructor.
  • Type Safety: The generic SignalChannel ensures only valid types (implementing both SignalPayload and IConvertible) can be used, eliminating unsafe casts.
  • Error Handling: Added fallback logic for failed initialization and invalid payload conversions to make the code more robust.

内容的提问来源于stack exchange,提问作者levWi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:46:51