我有以下不能更改的Java类

interface Parent...
class Child1Class implements Parent...
class Child2Class implements Parent...
class GrandChild1Class extends Child1Class ...
...

现在我在写Kotlin应用程序.

我想为所有的层次 struct 添加一些功能.

fun Parent.foo(){ println("Parent.foo")

但我想在GrandChild1Class岁时有特殊的行为举止

fun GrandChild1Class.foo(){ println("GrandChild1Class.foo")

但如果我写道:

val grandChild1: Parent = GrandChild1Class()
grandChild1.foo()

我看到Parent.foo是因为引用类型

但我预计会看到GrandChild1Class.foo

有没有办法实现这类事情的多态行为?

推荐答案

不是的.Kotlin将扩展函数实现为静态Java方法,扩展函数的接收方是Java方法的第一个参数.

fun String.foo() { }

vbl.成为

public static void foo(String $this$foo) { }

当然,静态方法是statically个分派的,所以不存在多态.

简单的解决办法是只需用when判断类型.

fun Parent.foo() = when(this) {
    is GrandChild1Class -> println("GrandChild1Class.foo")
    // other cases...
    // remember to put "more specific" cases first!
    else -> println("Parent.foo")

JVM中唯一可以动态分派方法的指令是invokeinferfaceinvokevirtualinvokedynamic.前两者都要求在方法被调用的实例的类/接口中声明方法,而扩展方法无法做到这一点.也就是说,在Kotlin中声明fun String.foo()不可能将foo方法添加到java.lang.String.

Kotlin编译器理论上可以使用invokedynamic.它将找到所有适用的扩展方法,执行一些重载解析,并返回与它找到的特定扩展方法相对应的CallSite.在实践中,这将需要大量的设计来确定确切的行为应该是什么,以及对编译器进行重大更改,并 destruct 源代码兼容性.

Java相关问答推荐

try Dockerize Maven应用程序,但发布版本21不支持"

Javascript在边界中心调整ImageView大小

JDK22执行repackage of goal org. springframework. boot:spring—boot—maven—plugin:3.2.3:repackage failed:unsupported class file major version 66—>

有关手动创建的包的问题

Java FX中的河内之塔游戏-在游戏完全解决之前什么都不会显示

连接Quarkus中的两个异步操作

我无法获取我的Java Spring应用程序的Logback跟踪日志(log)输出

如何在EXCEL单元格中添加形状和文本

使用多个RemoteDatabase对象的一个线程

在执行流和相关操作时,使用Java泛型为2个方法执行相同的操作,但对象不同

Kotlin Val是否提供了与Java最终版相同的可见性保证?

基于配置switch 的@Controller的条件摄取

无法使用Freemarker从XML中读取重复的标记值

带有可选部分的Java DateTimeForMatter

寻找Thread.sky()方法的清晰度

如何对存储为字符串的大数字数组进行排序?

org.springframework.web.HttpRequestMethodNotSupportedException:请求方法';帖子';不支持

[jdk21][Foreign Function&;Memory API]MemoryLayout::varHandle通过可变数组进行 struct 化的问题

声纳覆盖范围为 0%,未生成 jacoco.xml

一条Java记录可以保存多少个字段?