【问题标题】:Kotlin implement a method from an interface that's already present in super classKotlin 从超类中已经存在的接口实现方法
【发布时间】:2019-07-16 02:56:43
【问题描述】:

假设我有这个界面:

interface Things {
  fun size(): Int
}

我想继承 List 并实现这个接口。

class Cars : ArrayList<String>, Things {}

我得到一个编译错误:

继承的平台声明冲突:以下声明具有 相同的 JVM 签名 (size()I): fun(): Int 定义在 Things fun size(): Int 在 Things 中定义

我可以通过将 size 合约更改为 var 隐式 getter 来绕过编译错误:

interface Things {
    var size: Int
}

然后我得到一个冗长而复杂的错误,看起来像一个运行时错误 (IllegalStateException),但似乎在 Kotlin 编译时发生:shrug:

我怀疑我知道为什么会发生这种情况 - ArrayList 已经有 int size() 并且 Kotlin 现在尝试添加另一个相同的签名,但即使我是对的(10% 的机会?)它也无济于事很多。

我还要提到它允许我将get 作为Things 接口的一部分,列表对此感到满意。我猜operator 运算符让我们这只是不同的足以滑动?

所以无论如何,没有 IDE 错误,但是当我构建时,我得到了这个:

java.lang.IllegalStateException: Backend Internal error: Exception during code generation
Cause: Concrete fake override public open fun <set-size>(<set-?>: kotlin.Int): kotlin.Unit defined in org.blah.Stuff[PropertySetterDescriptorImpl@673f2280] should have exactly one concrete super-declaration: []
File being compiled at position: file:///blah/Stuff.kt
The root cause was thrown at: bridges.kt:122
    at org.jetbrains.kotlin.codegen.CompilationErrorHandler.lambda$static$0(CompilationErrorHandler.java:24)
    at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generate(PackageCodegenImpl.java:76)
    at org.jetbrains.kotlin.codegen.DefaultCodegenFactory.generatePackage(CodegenFactory.kt:96)
    at org.jetbrains.kotlin.codegen.DefaultCodegenFactory.generateModule(CodegenFactory.kt:67)
    at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.doGenerateFiles(KotlinCodegenFacade.java:47)
    at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:39)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:476)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:164)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:166)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:56)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:84)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:42)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:104)
    at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:349)
    at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:105)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:237)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.access$compileIncrementally(IncrementalCompilerRunner.kt:37)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner$compile$2.invoke(IncrementalCompilerRunner.kt:79)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:91)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.execIncrementalCompiler(CompileServiceImpl.kt:579)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.access$execIncrementalCompiler(CompileServiceImpl.kt:102)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:455)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:102)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:1005)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:102)
    at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:138)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:1047)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:1004)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:454)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:346)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Concrete fake override public open fun <set-size>(<set-?>: kotlin.Int): kotlin.Unit defined in org.blah.Stuff[PropertySetterDescriptorImpl@673f2280] should have exactly one concrete super-declaration: []
    at org.jetbrains.kotlin.backend.common.bridges.BridgesKt.findConcreteSuperDeclaration(bridges.kt:122)
    at org.jetbrains.kotlin.backend.common.bridges.BridgesKt.generateBridges(bridges.kt:59)
    at org.jetbrains.kotlin.codegen.JvmBridgesImplKt.generateBridgesForFunctionDescriptorForJvm(JvmBridgesImpl.kt:92)
    at org.jetbrains.kotlin.codegen.FunctionCodegen.generateBridges(FunctionCodegen.java:1041)
    at org.jetbrains.kotlin.codegen.ClassBodyCodegen.generateBridges(ClassBodyCodegen.java:138)
    at org.jetbrains.kotlin.codegen.ClassBodyCodegen.generateBody(ClassBodyCodegen.java:116)
    at org.jetbrains.kotlin.codegen.MemberCodegen.generate(MemberCodegen.java:129)
    at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:302)
    at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:286)
    at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateClassesAndObjectsInFile(PackageCodegenImpl.java:118)
    at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateFile(PackageCodegenImpl.java:137)
    at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generate(PackageCodegenImpl.java:68)
    ... 44 more


> Task :app:buildInfoGeneratorDebug 

我缺少的任何东西。我大部分时间都在 Java 中度过,但参加 Kotlin 派对却迟到了。任何解决方法、替代方案……或者这是已知的事情?

TYIA

【问题讨论】:

  • 当我创建一个玩具示例class C: A(), B { override fun f() { super&lt;A&gt;.f() } } 时,它会编译。我猜这个问题与ArrayList 是一个Java 类有关。但老实说,我不明白原因(你说得对,因为ArrayList 有自己的size(),但我的玩具例子也是)。 jvm name clash 的解决方法是显式指定 Jvm 名称,但 Kotlin 似乎不允许接口方法使用此属性。

标签: kotlin


【解决方案1】:

问题是因为 kotlin 有 List 的扩展 val 属性:size

第一个错误表明你有两个不同的 kotlin “事物”(方法和属性),它们在 jvm 中是相同的。第二个错误是因为您在ArrayList 中有 val 实现,并且在接口中有 var 字段,所以您的类Cars 需要同时实现setter 和getter 但只实现getter (来自List val size)。

解决方案很简单:只需将你的接口属性更改为val size: Int

【讨论】:

  • 答案不仅有效,而且您简短清晰的解释很容易理解。非常感谢
猜你喜欢
  • 2020-02-04
  • 1970-01-01
  • 2019-01-24
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-04
  • 2019-09-11
相关资源
最近更新 更多