Предупреждение «Утечка this» в конструкторе »должно относиться как к финальным классам, так и к открытым? - PullRequest
0 голосов
/ 20 декабря 2018

В Kotlin, если у вас есть класс open, который ссылается на this в его конструкторе или init блоке, вы (совершенно справедливо) получаете предупреждение компилятора:

Утечка 'this'в конструкторе неконечного класса

Причина этого объясняется здесь .

Мой вопрос: почему это не сообщили, когда урок окончательный?Если this используется в блоке init до того, как этот блок будет завершен, объект все еще не находится в полностью построенном состоянии, поэтому разве предупреждение не должно применяться и там?

Это может даже привести кситуация, когда свойство val изменяется во время выполнения.Возьмите этот код в качестве примера:

class Listener {
    fun onCreated(leaker: Leaker) = println("Listener hears that leaker created with a value of ${leaker.myVal}")
}

class Leaker(listener: Listener) {
    val myVal: Int

    init {
        listener.onCreated(this)
        myVal = 1
        println("Leaker knows that it's been created with a value of $myVal")
    }
}

Использование этих объектов следующим образом:

Leaker(Listener())

приведет к следующему выводу:

Listener hears that leaker created with a value of 0
Leaker knows that it's been created with a value of 1

Обратите внимание, что myVal первоначально сообщается как 0, затем как 1.

Как видно, Leaker передает свой экземпляр в Listener до того, как Leaker будет полностью построен.Listener может получить доступ к свойству myVal до его инициализации, поэтому у него будет значение по умолчанию (в данном случае 0, так как это целое число).Позже Listener затем изменяет значение этого свойства (на 1 в этом примере).Это означает, что программа ведет себя так, как будто val изменился.

Должен ли компилятор предупредить вас об этом?

1 Ответ

0 голосов
/ 02 мая 2019

tl; dr: https://youtrack.jetbrains.com/issue/KT-22044 хорошо подходит для этой проблемы.

Я процитирую то, что говорит проверка Intellij IDEA под названием «Утечка this» в конструкторе »об этом:

Эта проверка сообщает об опасных операциях внутри конструкторов, включая:

  • Доступ к неконечному свойству в конструкторе
  • Вызов не финальной функциив конструкторе
  • Использование this в качестве аргумента функции в конструкторе неконечного класса

Эти операции опасны, поскольку ваш класс может быть унаследован, ипроизводный класс еще не инициализирован в данный момент.Типичный пример:

abstract class Base {
    val code = calculate()
    abstract fun calculate(): Int
}

class Derived(private val x: Int) : Base() {
    override fun calculate() = x
}

fun testIt() {
    println(Derived(42).code) // Expected: 42, actual: 0
}

Я думаю, что, тем не менее, должно быть предупреждение, поскольку вы смогли получить доступ к неинициализированной переменной.Причина: компилятор уже запрещает прямой доступ к неинициализированным переменным, т. Е. Следующее не будет компилироваться:

class Demo {
  val some : Int
  init {
    println(some) // Variable 'some' must be initialized

, но косвенный доступ к нему компилируется и показывает значение по умолчанию типа переменной:

class Demo2 {
  val some : Int
  val someString : String
  init {
    fun Demo2.indirectSome() = some
    fun Demo2.indirectSomeString() = someString
    println(indirectSome()) // prints 0
    println(indirectSomeString()) // prints null; and yes.. this can lead to NullPointerExceptions

и там у нас также есть "утечка", в основном доступ к some, прежде чем он должен; -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...