是否可以在 Kotlin 中将类属性作为函数参数传递?



我有一个

class Foo {
lateinit var property1: String
lateinit var property2: Int
lateinit var property3: Long
}

那么是否可以在这样的函数中传递类的属性呢?

fun bar(fooProperty: FooProperty) {
println(
when(fooProperty) {
Foo.property1 -> "Property1"
Foo.property2 -> "Property2"
Foo.property3 -> "Property3"
}
)
}

但是,这是无效代码。我只是想知道这是否可以实现。

是的,这是可能的,只需使用ClassName::propertyName获取对属性的引用,KProperty1<ClassName, *>作为参数类型。

因此,带有示例类的完整工作示例(稍作更改以使类编译(如下所示:

import kotlin.reflect.KProperty1
class Foo {
lateinit var property1: String
var property2: Int = 0
var property3: Long = 0
}
fun bar(fooProperty: KProperty1<Foo, *>) {
println(
when(fooProperty) {
Foo::property1 -> "Property1"
Foo::property2 -> "Property2"
Foo::property3 -> "Property3"
else -> throw IllegalArgumentException("Not a known property")
}
)
}
fun main() {
bar(Foo::property2)
}

这打印

Property2

有几个选项。最简单的方法是使用包装类 ;您甚至可以使用密封类 ,这样when就不需要else分支。使用包装类的缺点是包装类的效率远低于使用基元类型。也就是说,基元类型不能lateinit,在此用例中可能需要委托属性,因此包装类可能是一个好主意。

最好的答案可能是选项 #3 - 使用内联类。内联类应该像使用底层基元类型一样进行优化,同时提供 OOP 的全部好处(与仅使用反射不同(。这样做的缺点是它们不能密封(因此在与when一起使用时,它们需要一个else分支(,并且它们是实验性的。

请注意,问题中的代码存在许多问题,包括when表达式中缺少iselse,以及将lateinit与基元类型一起使用。

选项#1:

class Foo {
lateinit var property1: Foo.Property1
lateinit var property2: Foo.Property2
lateinit var property3: Foo.Property3

abstract class FooProperty
class Property1(val value:String):FooProperty()
class Property2(val value:Int):FooProperty()
class Property3(val value:Long):FooProperty()
}
fun bar(fooProperty: Foo.FooProperty) {
println(
when(fooProperty) {
is Foo.Property1 -> "Property1"
is Foo.Property2 -> "Property2"
is Foo.Property3 -> "Property3"
else -> error("Impossible")
}
)
}

选项#2:

class Foo {
lateinit var property1: FooProperty1
lateinit var property2: FooProperty2
lateinit var property3: FooProperty3
}
sealed class FooProperty
class FooProperty1(val value: String) : FooProperty()
class FooProperty2(val value: Int) : FooProperty()
class FooProperty3(val value: Long) : FooProperty()

fun bar(fooProperty: FooProperty) {
println(
when (fooProperty) {
is FooProperty1 -> "Property1"
is FooProperty2 -> "Property2"
is FooProperty3 -> "Property3"
}
)
}

选项#3:

inline class FooProperty1(val value:String)
inline class FooProperty2(val value:Int)
inline class FooProperty3(val value:Long)
class Foo {
var property1: FooProperty1 by Delegates.notNull()
var property2: FooProperty2 by Delegates.notNull()
var property3: FooProperty3 by Delegates.notNull()
}
fun bar(fooProperty: Any) {
println(
when(fooProperty) {
is FooProperty1 -> "Property1"
is FooProperty2 -> "Property2"
is FooProperty3 -> "Property3"
else -> error("")
}
)
}

最新更新