Kotlin @JvmStatic和伴随对象中的意外覆盖

dim*_*eng 5 swing kotlin

我正在使用Kotlin制作Swing外观。为了创建UI,Swing需要具有createUI带有以下签名的静态方法:

class ButtonUI: BasicButtonUI() {
    ...
    companion object {
        @JvmStatic fun createUI(p0: JComponent): ComponentUI {
           ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在Swing代码中通过反射调用它:

m = uiClass.getMethod("createUI", new Class[]{JComponent.class});
Run Code Online (Sandbox Code Playgroud)

不幸的是,由于以下原因,上面的代码无法由kotlin编译器编译:

Error:(88, 9) Kotlin: Accidental override: The following declarations have the same JVM signature (createUI(Ljavax/swing/JComponent;)Ljavax/swing/plaf/ComponentUI;):
    fun createUI(c: JComponent): ComponentUI
    fun createUI(p0: JComponent!): ComponentUI!
Run Code Online (Sandbox Code Playgroud)

有这种情况的解决方法吗?

hol*_*ava 5

这是一个 kotlin错误 KT-12993。不幸的是,该错误尚未修复。如果您想让 kotlin 实现您的 ui 逻辑,只需使用实现您的ButtonUI或在和 kotlin之间切换即可解决问题。例如,您应该在和 kotlin之间定义一个对等点。

java代码如下:

public class ButtonUI extends BasicButtonUI {
    private ButtonUIPeer peer;

    public ButtonUI(ButtonUIPeer peer) {
        this.peer = peer;
    }

    @Override
    public void installUI(JComponent c) {
        peer.installUI(c, () -> super.installUI(c));
    }

    // override other methods ...


    public static ComponentUI createUI(JComponent c) {
        // create the peer which write by kotlin 
        //                        |
        return new ButtonUI(new YourButtonUIPeer());
    }
}


interface ButtonUIPeer {
    void installUI(Component c, Runnable parentCall);
    //adding other methods for the ButtonUI
}
Run Code Online (Sandbox Code Playgroud)

kotlin 代码如下:

class YourButtonUIPeer : ButtonUIPeer {
    override fun installUI(c: Component, parentCall: Runnable) {
      // todo: implements your own ui logic
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您有六个以上的方法要实现,您可以使用代理设计模式将请求委托给ButtonUI在 kotlin 中实现的目标(许多 IDE 支持为字段生成委托方法)。例如:

public class ButtonUIProxy extends BasicButtonUI {
    private final BasicButtonUI target;
    //1. move the cursor to here ---^
    //2. press `ALT+INSERT`
    //3. choose `Delegate Methods` 
    //4. select all public methods and then click `OK`

    public ButtonUIProxy(BasicButtonUI target) {
        this.target = target;
    }

    public static ComponentUI createUI(JComponent c){
        // class created by kotlin     ---v
        return new ButtonUIProxy(new ButtonUI());
    }
}
Run Code Online (Sandbox Code Playgroud)