gst*_*low 2 java polymorphism inheritance extension-methods kotlin
我有以下无法更改的 java 类
interface Parent...
class Child1Class implements Parent...
class Child2Class implements Parent...
class GrandChild1Class extends Child1Class ...
...
Run Code Online (Sandbox Code Playgroud)
现在我编写 Kotlin 应用程序。
我想向所有层次结构添加一些功能。
fun Parent.foo(){ println("Parent.foo")
Run Code Online (Sandbox Code Playgroud)
但我想要有特殊的行为GrandChild1Class
fun GrandChild1Class.foo(){ println("GrandChild1Class.foo")
Run Code Online (Sandbox Code Playgroud)
但如果我写:
val grandChild1: Parent = GrandChild1Class()
grandChild1.foo()
Run Code Online (Sandbox Code Playgroud)
我看到Parent.foo是因为引用类型
但我希望看到GrandChild1Class.foo
有没有办法实现这种事情的多态行为?
不会。Kotlin 将扩展函数实现为静态 Java 方法,扩展函数的接收者是 Java 方法的第一个参数。
fun String.foo() { }
Run Code Online (Sandbox Code Playgroud)
变成
public static void foo(String $this$foo) { }
Run Code Online (Sandbox Code Playgroud)
当然,静态方法是静态调度的,所以不存在多态性。
简单的解决方法是仅使用 . 检查类型when。
fun Parent.foo() = when(this) {
is GrandChild1Class -> println("GrandChild1Class.foo")
// other cases...
// remember to put "more specific" cases first!
else -> println("Parent.foo")
Run Code Online (Sandbox Code Playgroud)
JVM 中唯一可以动态分派方法的指令是invokeinferface、invokevirtual和invokedynamic。前两个都要求在调用该方法的实例的类/接口中声明该方法,这是扩展方法无法做到的。即在 Kotlin 中声明fun String.foo()不可能foo向java.lang.String.
Kotlin 编译器理论上可以使用invokedynamic. 它将找到所有适用的扩展方法,执行一些重载解析,并返回CallSite与它找到的特定扩展方法相对应的方法。在实践中,这需要大量的设计来弄清楚确切的行为应该是什么,以及对编译器进行重大更改,并破坏源代码兼容性。
| 归档时间: |
|
| 查看次数: |
71 次 |
| 最近记录: |