"lateinit var overrides lateinit var"

"lateinit var overrides lateinit var"

假设我有这样的设置:

abstract class FooTest {

    open lateinit var softAssertions: SoftAssertions

    ... reusable auxiliary functions ...
}
@ExtendWith(SoftAssertionsExtension::class)
class BarTest: FooTest(){

    @InjectSoftAssertions
    override lateinit var softAssertions: SoftAssertions

    ... actual test cases ...
    
}

IntelliJ 为 BarTest 中的 softAssertions 提供了非常有用的警告:

lateinit var overrides lateinit var

是的是的..?继续,你的意思是什么?

我最终意识到 FooTest 中的 lateinit var 确实应该是 abstract val,而不是 - 这消除了警告 - 但即便如此,我想知道.. . 是否有关于 lateinit var 覆盖 lateinit var 我应该知道但不知道并且 IntelliJ 想告诉我但没有告诉我的事情?

基本上它只是警告你,它认为这个覆盖可能不是故意的,因为它没有看到任何有用的东西。通常,您不能覆盖变量,但 Kotlin 中的变量是属性(即它们具有 getters 和 setters)。所以从技术上讲,您正在覆盖 getters/setters,但为什么您需要这样做,因为您没有更改它们的实现。

Kotlin 中 属性 覆盖的一个很好的例子是:

abstract class FooTest {
    open val softAssertions: SoftAssertions
}

然后

@ExtendWith(SoftAssertionsExtension::class)
class BarTest: FooTest(){

@InjectSoftAssertions
override lateinit var softAssertions: SoftAssertions

... actual test cases ...
}

在这种情况下,您将用 var(同时具有 getter 和 setter)覆盖 val(只有 getter)。

原因描述in the issue which added the inspection:

It seems suspicious that an instance of A2 [BarTest in your case] will have two fields for the single property and the one from A1 [FooTest] remains effectively unused.

...

why do we consider suspicious just a case with lateinit properties? I'd say here that any case where one property with backing field overrides another property with backing field is suspicious.

Properties with backing fields in general can have custom setters, so overriding them can make sense in some situations. On the contrary, lateinit properties never have custom setters, thus overriding them makes the overridden property backing fields always unused.

这两个不同的支持字段也可以带来有趣的事情,例如 'isInitialized' property of a lateinit variable is false when it is overridden as a var by another class

在重写 属性 具有与您的情况类似的注释的情况下添加异常可能是有意义的。