当前位置: 首页 > 知识库问答 >
问题:

Kotlin-从主构造函数获取所有属性

申屠恺
2023-03-14

我创建了这个扩展方法,它从一个KClass获取所有属性

扩展方法

@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> KClass<T>.getProperties(): Iterable<KProperty1<T, *>> {
    return members.filter { it is KProperty1<*, *> }.map { it as KProperty1<T, *> }
}

示例用法

data class Foo(val bar: Int) {
    val baz: String = String.EMPTY
    var boo: String? = null
}

val properties = Foo::class.getProperties()

结果

val公司。演示。富。酒吧:科特林。内景

val公司。演示。富。巴兹:科特林。一串

VARcom.demo.Foo.boo:kotlin。字符串

如何修改此扩展方法以仅返回在主构造函数中声明的属性?

预期成果

val公司。演示。富。酒吧:科特林。内景

共有3个答案

赵智勇
2023-03-14
inline fun <reified T : Any> KClass<T>.getProperties(): List<KProperty<*>> {
    val primaryConstructor = primaryConstructor ?: return emptyList()
    // Get the primary constructor of the class ^

    return declaredMemberProperties.filter {
    // Get the declared properties of the class; i.e. bar, baz, boo
        primaryConstructor.parameters.any { p -> it.name == p.name } 
        // Filter it so there are only class-properties whch are also found in the primary constructor.
    }
}

总而言之,这个函数基本上获取了在类中找到的所有属性并对它们进行过滤,以便只保留在主构造函数中也找到的属性。

周翰
2023-03-14
val <T : Any> KClass<T>.constructorProperties
    get() =
        primaryConstructor?.let { ctor ->
            declaredMemberProperties.filter { prop ->
                ctor.parameters.any { param ->
                    param.name == prop.name
                    &&
                    param.type == prop.returnType
                }
            }
        } ?: emptyList()

fun <T : Any> KClass<T>.getProperties(): Iterable<KProperty1<T, *>> =
    constructorProperties

这是szymon\u prz和Peter Henry之前回答的重做,以生成在主构造函数中声明的属性列表,但不是:

  • 其他不是属性的主要构造函数参数
  • 不是主构造函数参数但具有匹配名称和不同类型的其他属性

不幸的是,它仍然会列出不是主构造函数参数但与其中一个参数具有相同名称和类型的属性。

例如:

// only parameter 'bar' is declared as a property
class Foo(val bar: Int, baz: Int, qux: Int, rod: Int) {
    val zzz = baz            // no parameter zzz 
    val qux = "##($qux)##"   // property is a String but parameter is an Int
    val rod = maxOf(0, rod)  // property and parameter are both Int
}

val ctorProps = Foo::class.constructorProperties
ctorProps.forEach { println(it.toString()) }

将产生:

Val Foo.bar:kotlin. Int

Val Foo.rod:kotlin. Int

景令秋
2023-03-14

您可以通过获取primaryConstructor然后获取valueParameters来获取构造函数参数,因为kotlin类不需要主构造函数,所以我们可以这样做

inline fun <reified T : Any> KClass<T>.getProperties(): Iterable<KParameter> {
   return primaryConstructor?.valueParameters ?: emptyList()
}

所以如果我们询问Foo类的属性

val properties = Foo::class.getProperties()
properties.forEach { println(it.toString()) }

我们会得到

parameter #0 bar of fun <init>(kotlin.Int): your.package.Foo

结果不是一个KProperty,而是一个KParameter,它可能更符合您的用例

 类似资料:
  • 问题内容: 以下是两种方法: 具有所有类属性的构造函数 优点:我必须输入确切数量的参数类型,所以如果出现错误,编译器会警告我(顺便说一句,有什么方法可以防止错误地在参数列表中切换两个Integer的问题?) 缺点:如果我有很多属性,则实例化行可能会变得很长,并且可能跨越两行或更多行 setter和默认的空构造函数 优点:我可以清楚地看到自己的设置,因此,如果我做错了什么,我可以在键入时立即查明它(

  • 我正在将我的一些Java代码转换为Kotlin,我不太明白如何实例化Kotlin代码中定义的接口。作为一个例子,我有一个接口(用Java代码定义): 然后在我的Kotlin代码中,我进一步实例化了这个接口: 而且效果很好。然而,当我将MyInterface转换为Kotlin时: 当我尝试实例化接口MyListener时,我得到了一条错误消息:-尽管在我看来除了语法之外没有什么变化。我是否误解了Ko

  • 从Kotlin开始,想要创建一个数据类

  • 无论我用什么方法尝试,无论是主构造函数还是次构造函数,我都不知道如何在kotlin中声明一个带有超类和构造函数的新类。 这是我最想做的,但它给出了一个错误,期望成员声明。 这是我认为主要构造函数的外观,但它给出了相同的错误。在Internet上搜索没有帮助,我只能找到第二个示例。 那么,用一个超类和它的一个构造函数创建一个类的所有有效方法是什么呢?

  • 我不太清楚kotlin是如何管理属性名和主构造函数参数名的。如果我写了相同的属性名和参数名,那么kotlin编译器会给出一个错误。 它给出了这个错误。 但是,当我更改属性的名称或更改主构造函数的参数名称时,代码将工作并编译。 这将工作或编译罚款。 这背后的原因是什么?为什么主构造函数的参数名和属性名不能相同?

  • 在kotlin中,如何将主构造函数中属性的setter设置为私有? 我希望属性<code>name</code>的setter是私有的,而getter是公共的,我该怎么做?