SOF*_*OFe 12 oop inline kotlin
在Kotlin中使用inline
功能实现接口时:
interface Foo {
fun qux(fn: () -> Unit)
}
open class Bar : Foo {
final override inline fun qux(fn: () -> Unit){TODO()}
}
Run Code Online (Sandbox Code Playgroud)
IDE(可能还有编译器)抱怨以下消息:
Override by an inline function
Run Code Online (Sandbox Code Playgroud)
要取消显示此消息,我必须使用@Suppress("OVERRIDE_BY_INLINE")
注释。怎么了?
我已经知道的:
但是,调用最终函数时并非如此。在上面的示例中,当我调用时bar.qux()
,编译器可以确保仅使用该特定实现,并且可以安全地内联。它是否覆盖该Foo.qux
方法无关紧要-调用foo.qux
将使用第1点中提到的非内联版本,并且调用bar.qux
可以安全地内联。
只是为了确保开发人员意识到这一警告吗?还是有副作用?
我知道这已经很晚了,但这就是原因。你猜对了:
内联虚方法是不可能的。
但是您应该考虑到,虽然Bar.foo
它不是虚拟的,因为它可以被覆盖(它不能),但它是虚拟的,因为它可以决定在运行时运行它。考虑以下基于您自己构建的示例:
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
}
Run Code Online (Sandbox Code Playgroud)
这里,Bar.qux
最初被调用,但Baz.qux
第二次被调用。因此,并非每个调用都可以内联。那么为什么这是一个警告而不是一个编译器错误,就像我们open fun
用inline
修饰符声明 an 一样?考虑以下:
val bar: Bar = Bar()
bar.qux { }
Run Code Online (Sandbox Code Playgroud)
在这种情况下,编译器可以安全地内联qux
对变量的所有调用,bar
因为它被声明为Bar
. 即使类在您的示例中是开放的,由于方法本身是final
,任何派生类型将始终使用完全相同的qux
。所以这个声明,
在上面的例子中,当我调用 bar.qux() 时,编译器可以确保只使用这个特定的实现,并且可以安全地内联。
仅当编译器静态地知道 的类型为bar
实际Bar
. 这是一个错误,open
因为它们都不能被内联,这绝对不是所需的行为,当它被覆盖时是一个警告,因为只有其中一些可以被内联,这可能不是所需的行为。
这个例子可以在 play.kotlinlang.org 上找到