如何从枚举在 Kotlin 中创建编译时常量?

How to create compile-time constant in Kotlin from enum?

我有一个注释要求 defaultValue 是编译时常量。我从下面的 enum 中提取 defaultValue

enum class RaceType {
    MARATHON,
    SPRINT;

    companion object {
        fun apply(type: RaceType): RaceDto {
            return when (type) {
                MARATHON -> MarathonDto()
                SPRINT -> SprintDto()
            }
        }
    }
}

我的 dto 如下:

interface RaceDto {
}

data class MarathonDto: RaceDto

data class SprintDto: RaceDto

当我使用注释时 @QraphQLArgument(defaultValue = RaceType.SPRINT.name) Kotlin 要求 RaceType.SPRINT.name 是编译时常量。

注释实现本身:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface GraphQLArgument {
    String NONE = "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
    String NULL = "\n\t\t\n\t\t\n\ue000\ue001\ue002\ue003\n\t\t\t\t\n";

    String name();

    String description() default "";

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";

    Class<? extends DefaultValueProvider> defaultValueProvider() default JsonDefaultValueProvider.class;
}

我查看了与该主题相关的 similar questions but don't see a way how it can be resolved. I also found article,但到目前为止没有任何效果。

旁注:我无法更改注释,因为它来自库,我也无法更改库。

总而言之,有没有一种方法可以使 Kotlin 中的 enum 编译时常量在注释中使用?

is there a way to make from enum compile-time constant in Kotlin to use in an annotation?

没有,因为正式 enums .

但是请考虑 sealed classes:

sealed class RaceType {
    object MARATHON: RaceType() {
        const val name = "MARATHON" // copy-paste is required here until https://youtrack.jetbrains.com/issue/KT-16304
    }
    object SPRINT: RaceType()

    companion object {
        fun apply(type: RaceType): RaceDto {
            return when (type) { // the check is in compile time, because of sealed class
                MARATHON -> MarathonDto()
                SPRINT -> SprintDto()
            }
        }
    }
}

仍然需要一小部分复制粘贴。请投票 kotlin compiler bug or follow this thread

但是,据我了解,不幸的是,这并不能解决 @QraphQLArgument(defaultValue = RaceType.SPRINT.name) 的问题,因为 class 的名称与值不同。换句话说,对于密封的 classes,您需要编写代码将输入字符串转换为它们。