科特林OVERRIDE_BY_INLINE [英] OVERRIDE_BY_INLINE in Kotlin

查看:237
本文介绍了科特林OVERRIDE_BY_INLINE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Kotlin中使用inline函数实现接口时:

When implementing an interface in Kotlin with an inline function:

interface Foo {
    fun qux(fn: () -> Unit)
}

open class Bar : Foo {
    final override inline fun qux(fn: () -> Unit){TODO()}
}

IDE(可能还有编译器)抱怨以下消息:

the IDE (and possibly the compiler) complains with this message:

Override by an inline function

要禁止显示此消息,我必须使用@Suppress("OVERRIDE_BY_INLINE")批注.怎么了?

To suppress this message, I have to use the @Suppress("OVERRIDE_BY_INLINE") annotation. What is wrong?

我已经知道的:

  • 对于普通的内联函数,kotlinc将内联函数的所有用法内联,但仍将编译该函数的非内联版本,以便可以从Java调用它(并且可能是出于向后兼容性或其他原因)
  • 不可能内联虚拟方法.内联只是意味着将所有代码复制到调用者中",但是对于调用抽象/接口方法,该实现是在运行时根据所涉及对象的实际类确定的,因此无法知道要复制到哪个实现中功能.

但是,调用最终函数时并非如此.在上面的示例中,当我调用bar.qux()时,编译器可以确保仅使用此特定实现,并且可以安全地内联.它是否覆盖Foo.qux方法无关紧要-调用foo.qux将使用第1点中提到的非内联版本,而调用bar.qux可以安全地内联.

However, this isn't the case when invoking a final function. In the example above, when I invoke bar.qux(), the compiler can ensure that only this particular implementation will be used, and can safely inlined. It is irrelevant with whether it overrides the Foo.qux method -- calling foo.qux will use the non-inline version mentioned in point 1, and calling bar.qux can inline safely.

该警告是否仅是为了确保开发人员意识到这一点?还是有副作用?

Is this warning there only to make sure developers are aware of this? Or are there side effects?

推荐答案

我知道这已经很晚了,但这就是原因.您说对了:

I know this is pretty late, but here's why. You got this right:

不可能内联虚拟方法.

It is impossible to inline a virtual method.

但是您应该考虑,虽然Bar.foo在可能会被覆盖(不能被覆盖)的意义上不是虚拟的,但是在可以决定在运行时运行它的意义上,它是虚拟的.考虑下面的示例,该示例是您自己构建的:

But you should consider that, while Bar.foo is not virtual in the sense that it could be overridden (it can't be), it is virtual in the sense that a decision can be made to run it at runtime. Consider the following example which builds on your own:

interface Foo {
    fun qux(fn: () -> Unit)
}

open class Bar : Foo {
    final override inline fun qux(fn: () -> Unit){TODO()}
}

class Baz : Foo {
    override fun qux(fn: () -> Unit) = TODO()
}

fun main() {
    var foo: Foo = Bar()
    foo.qux { }          // calls Bar.qux
    foo = Baz()
    foo.qux { }          // calls Foo.qux
}

在这里,最初调用Bar.qux,但是第二次调用Baz.qux.因此,不能内嵌每个调用.那么,为什么这是警告而不是编译器错误,例如当我们使用inline修饰符声明open fun时?请考虑以下内容:

Here, Bar.qux is invoked initially, but Baz.qux is invoked the second time. So, not every call can be inlined. So why is this a warning and not a compiler error, like when we declare an open fun with the inline modifier? Consider the following:

val bar: Bar = Bar()
bar.qux { }

在这种情况下,编译器可以安全地将变量bar上的所有对qux的调用内联,因为它被声明为Bar.即使类是如您的示例中打开的那样,由于方法本身是final,所以任何派生类型都将始终使用该qux.所以这句话,

In this case, the compiler can safely inline all calls to qux on the variable bar because it's declared as a Bar. Even if the class is open as in your example, since the method itself is final, any derived type will always use exactly that qux. So this statement,

在上面的示例中,当我调用bar.qux()时,编译器可以确保仅使用此特定实现,并且可以安全地内联.

In the example above, when I invoke bar.qux(), the compiler can ensure that only this particular implementation will be used, and can safely inlined.

仅当编译器静态知道bar的类型为实际的Bar时,

才为true.当它是open时,这是一个错误,因为它们中的 none 都可以被内联,这绝对不是所需的行为;当它被覆盖时,这是一个警告,因为其中只有 some 可以内联,这可能不是所需的行为.

is true only when the compiler statically knows the type of bar to be an actual Bar. It's an error when it's open because none of them can be inlined which definitely isn't the desired behavior, it's a warning when it's an override because only some of them can be inlined, which might not be the desired behavior.

可在play.kotlinlang.org上获得此示例

这篇关于科特林OVERRIDE_BY_INLINE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆