【问题标题】:Kotlin how to make sure that generic parameter is superclass of receiver classKotlin如何确保泛型参数是接收器类的超类
【发布时间】:2018-06-08 08:09:26
【问题描述】:

我尝试实现快速字段访问器功能,同时也想确保指定的类(字段的真正所有者)是接收者类型的超类,因此我写如下:

inline fun <A : B, reified B: Any> A.getProperty (name: String): Any {
    return B::class.java.getDeclaredField(name).apply { isAccessible = true }.get(this)
}

但这让我在调用期间毫无意义地编写接收器类型:

// in SubClass
getProperty<SubClass, BaseClass>("fieldThatIsInBaseClass")

如果在当前类中定义了字段,令我惊讶的是它甚至不需要参数:

// in BaseClass
getProperty("fieldThatIsInBaseClass")

我也尝试将字段类型参数添加到函数中,但这会破坏上面的代码,并且在每种情况下都必须指定所有参数:

inline fun <A : B, reified B: Any, T> A.getProperty (name: String): T {
    @Suppress("UNCHECKED_CAST")
    return B::class.java.getDeclaredField(name).apply { isAccessible = true }.get(this) as T
}

以及这如何破坏事物的示例:

// in a class Example which declares the field
getProperty<Example, Example, Int>("someIntField")

类中定义字段的理想语法应该是:

getProperty<Int>("someIntField")

对于扩展某些基类的类:

getProperty<BaseClass, Int>("fieldThatIsInBaseClass")

这样的事情可能吗?

【问题讨论】:

  • 标题中有“子类”,问题中有“超类”,第二个可能是正确的。
  • @AlexeyRomanov 谢谢,已修复

标签: generics reflection kotlin


【解决方案1】:

你为什么需要A?如果换成B:

inline fun <reified B: Any> B.getProperty (name: String): Any {
    return B::class.java.getDeclaredField(name).apply { isAccessible = true }.get(this)
}

它还将接受B 的任何子类型。

【讨论】:

  • 如果B 中未定义字段,恐怕这会抛出java.lang.NoSuchFieldException。这就是反射的问题。对于getDeclaredField,必须使用定义该字段的类。为了解决这个问题,我们可以使用 getField,但这找不到 privateprotected 字段,这是该示例的重点。
  • "如果 B 中未定义字段,恐怕这会引发 java.lang.NoSuchFieldException。"那么您的原始代码也会如此,不是吗?您仍然应该将其用作aSubClassInstance.getProperty&lt;BaseClass&gt;(...)
  • 不,如果我调用它(在子类中):getProperty&lt;SubClass, BaseClass&gt;("fieldThatIsInBaseClass") 那将转换为BaseClass::class.java.getDeclaredField("fieldThatIsInBaseClass").apply { isAccessible = true }.get(this),所以它是有效的。我测试了原始代码,它可以工作,但是语法不必要地冗长
  • 对,你把它称为getProperty&lt;BaseClass&gt;("fieldThatIsInBaseClass"),它翻译成完全相同的东西。
  • Ops... 好的,我说服了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-16
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多