`java.lang.StackOverflowError` при доступе к свойству Kotlin - PullRequest
0 голосов
/ 11 апреля 2019

Я получил этот (надуманный) пример из «Программирования Kotlin» Пакта об использовании вторичного конструктора с наследованием.

Редактировать: из ответа ясно, что проблема в поле поддержки.Но книга не привела эту идею, просто с неправильным примером.

open class Payment(val amount: Int) 

class ChequePayment : Payment { 
    constructor(amount: Int, name: String, bankId: String) :  super(amount) { 
        this.name = name
        this.bankId = bankId 
    }

    var name: String
        get() = this.name
    var bankId: String
        get()  = this.bankId
} 


val c = ChequePayment(3, "me", "ABC")    
println("${c} ${c.amount} ${c.name}")

Когда я запускаю ее, эта ошибка показывается.

$ kotlinc -script class.kts 2>&1 | more
java.lang.StackOverflowError
    at Class$ChequePayment.getName(class.kts:10)
    at Class$ChequePayment.getName(class.kts:10)
    at Class$ChequePayment.getName(class.kts:10)

Кажется, строка 10быть бесконечной рекурсией, как ее решить?

Ответы [ 2 ]

6 голосов
/ 11 апреля 2019

У вас есть рекурсия в вашем коде:

class ChequePayment : Payment { 
    constructor(amount: Int, name: String, bankId: String) :  super(amount) { 
        this.name = name
        this.bankId = bankId 
    }

    var name: String
        get() = this.name // recursion: will invoke getter of name (itself)
    var bankId: String
        get()  = this.bankId // recursion: will invoke getter of bankId (itself)
} 

Если вам не нужна пользовательская логика для вашего геттера, просто оставьте свои свойства так:

var name: String
var bankId: String

Они будутиметь метод получения по умолчанию, который ничего не делает, кроме как возвращает значение поля поддержки.

Примечание: Код, как он есть, может / должен быть реорганизован для этого:

class ChequePayment(amount: Int, var name: String, var bankId: String) : Payment(amount) {
    // ...
}

При этом используется основной конструктор, и он намного менее избыточен.

3 голосов
/ 11 апреля 2019

Чтобы получить доступ к вспомогательному полю, вы должны использовать ключевое слово field вместо this.name см. https://kotlinlang.org/docs/reference/properties.html#backing-fields

this.name ссылается на геттер, который ссылается на this.name, который является бесконечной рекурсией, как вы уже отметили. В коде:

var name: String
    get() = field
var bankId: String
    get()  = field

Примечание: Android Studio и Idea справедливо будут жаловаться, что в этом случае вам не нужен геттер. Таким образом, вы можете упростить еще больше:

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