如何在类上使用 Kotlin 扩展函数?

5

我有一个关于扩展函数的问题,它可以帮助简化我的代码。基本上,我有一些对类名hashCode的转换,我想要一个扩展函数来执行这些转换。

例如:

获取名称hashCode:StateA :: class.java.name.hashCode(),其中StateA是一个简单的类。

我想要像这样的扩展函数:

    fun Class<*>.transformName(): String {
       var hashString = this.javaClass.name.hashCode()

       //Do my stuff on that hashString

       return hashString
    }

但是这似乎不起作用。 当我使用StateA.transformName()应用扩展函数时,该函数会出现未解决的引用错误。
我尝试了各种方法,例如将函数应用于StateA :: class 或使hashString等于 this :: class.java.name.hashCode(),但都无效。 有什么提示吗?

1
您已经在类类型上创建了扩展,而StateA不是类的一种类型。StateA::class.java是一个有效的类类型对象。 - Jeel Vankhede
1
StateA::class.java.transformName() 可以工作。 - Neo
我现在明白了。是的,它可以工作。函数中的字符串将会像 this.name.hashCode() - M'aiq the Coder
1个回答

9

StateA.transformName()语法中,无法真正实现该方法,因为StateA仅单独指向类内的伴生对象。因此,要获得该语法,您需要在每个要对其使用扩展的类中拥有一个伴生对象。

您可以采用非常通用的方式,首先获取描述您的类的KClass。这将使您获得一个对象(即KClass实例),然后您可以在其上调用扩展:

fun KClass<*>.transformName() {
    val clazz: Class<*> = this.java
    clazz.name.hashCode()
}

StateA::class.transformName()

另一种更简洁的方法是使用一个通用函数,像这样,其中 reified 关键字允许您在函数内部访问用作泛型类型参数的具体类:

inline fun <reified T> transformName() {
    val clazz: Class<*> = T::class.java
    clazz.name.hashCode()
}

transformName<StateA>()

现在我明白了,谢谢。我认为这三种解决方案都很好。我想我会采用在每个类中创建一个伴生对象(就像你说的那样),并像StateA.transformName()这样简单地使用它。我会记录一些东西以确保它不会引起任何问题,但其他两种解决方案在代码实践方面也非常棒。非常感谢您,先生! - M'aiq the Coder
或者也不是。如果我再仔细想一下,使用reified的最后一个解决方案更加简洁。我认为仅仅为了某个函数而添加一些无用的伴生对象并不是一个好的实践。 - M'aiq the Coder
1
在类中添加伴生对象以像这样放置扩展并不是一种不好的做法(例如,这就是为什么 kotlin.Boolean 有一个伴生对象),但是是的,为多个类执行此操作可能会很繁琐,只是为了让它们与此扩展一起使用。 - zsmb13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接