如何在通用函数中访问对象属性?代码,我目前对error: unresolved reference: name
提出过要求。我该如何运作?
有where
个关键字,但我没有找到太多有关它的信息。
fun <T> foo(t:T): String{
return t.name
}
foo(object {
val name = "Foo"
})
相当于C ++:
struct {
int name{10};
}a;
template<typename T>
int foo(T&t) {
return t.name;
}
foo(a);
答案 0 :(得分:1)
以下是使用反射在Kotlin中进行操作的示例(注意:此处您甚至不需要使用该函数的泛型信息):
fun foo(t : Any) = with(t::class.java.getDeclaredField("name")) {
isAccessible = true
get(t) as String
}
with
并不是必需的。您当然可以完全不同。只是想展示一下在Kotlin中的样子。
我在评论中说了一种reified
类型,但实际上您在这里不需要。
要解决问题的最大问题是,您有一个匿名类型,该类型基本上将可能的解决方案缩小为“使用反射”;-)
如果您具有如下类型/接口:
interface Nameable {
val name : String
}
然后您可以将foo
方法更改为:
fun foo(t : Nameable) = t.name
并调用它会导致:
foo(object : Nameable {
override val name = "Foo"
}
但是,它仍然不是C ++模板,如果想要完全动态,并且必须在创建匿名类型等时使用它们,则必须创建许多适当的接口。 >
答案 1 :(得分:0)
如果要访问某些特定类型的成员,则应在类型参数上应用上限。 可以这样实现:
fun <T : MyTypeThatHasNameProperty> foo(t: T): String{
return t.name
}
答案 2 :(得分:0)
不能。 T
可以是运行时任何类型的实例。因此您无法访问该属性。
尽管如此,您可以做类似的事情
fun <T : SomeType> foo(t: T): String {
return t.name
}
open class SomeType(val name: String)
foo(SomeType("value"))
编辑:
如果您真的想使用non-named object
来实现这一点,那么我可以想到这样的事情。
fun <T : BaseType> foo(t: T): String {
return t.name
}
interface BaseType {
val name: String
}
foo(object :BaseType {
override val name = "value"
})
答案 3 :(得分:0)
有可能在泛型中使用Kotlin reified type parameters。
foo(object {
val name = "Foo"
})
inline fun <reified T> foo(t: T): String =
T::class.declaredMembers.find { it.name == "name" }!!
.call(t) as String
第二种选择是直接从::class
获得t
fun <T: Any> foo(t: T): String =
t::class.declaredMembers.find { it.name == "name" }!!.call(t) as String
第三个选择是为您提供通用参数上限:
foo( NameProvider {
val name = "Foo"
})
interface NameProvider {
val name: String
}
fun <T: NameProvider> foo(t: T): String = t.name