Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access secondary constructor parameter outside constructor block in Kotlin

I am new to Kotlin and working through the tutorials that are available. However now I seem to have a problem with a secondary constructor: Parameters declared in the primary constructor can be accessed in a function, but when I try to do this with a parameter from the secondary constructor I get an error: Unresolved reference:nbr

The code:

class Test(_name: String) {
val name: String = _name

constructor(_name: String, _nbr: Int) : this(_name) {
    val nbr: Int = _nbr
}

fun printNameAndNumber() {  
    println("Name: $name")
    println("Number: $nbr")
}

}

It is clear to me that I am doing something basically wrong but who can tell me what?

like image 611
frie Avatar asked Apr 18 '18 11:04

frie


3 Answers

nbr should be a variable, because in this specific case it is optional:

class Test(_name: String) {
    val name: String = _name
    var nbr: Int? = null

    constructor(_name: String, _nbr: Int) : this(_name) {
        this.nbr = _nbr
    }

    fun printNameAndNumber() {
        println("Name: $name")
        println("Number: $nbr")
    }
}
like image 100
gil.fernandes Avatar answered Oct 20 '22 23:10

gil.fernandes


Parameters of the primary constructor are not available in member functions. Fields are. Fortunately Kotlin has a short syntax to make primary constructor parameters member properties right away.

What do you expect nbr to be when constructed using the primary constructor? I suggest you to swap your constructors, so it's clear what are properties and what are just parameters:

class Test(val name: String, val nbr: Int) {
    constructor(name: String) : this(name, 0)

    fun printNameAndNumber() {  
        println("Name: $name")
        println("Number: $nbr")
    }
}

fun main(args : Array<String>) {
    Test("Péter").printNameAndNumber()
}
like image 3
Tamas Hegedus Avatar answered Oct 20 '22 23:10

Tamas Hegedus


name is accessible because it is a member.

nbr is not accessible because it is a local (immutable) variable inside the secondary constructor.

If you declare nbr as member: putting val nbr: Int for example below the val name line, it will be accessible, however it will not compile if nbr is defined as immutable (val).

A simpler structure would be:

class Test(_name: String, _nbr: Int = 0) {
    val name: String = _name
    val nbr: Int = _nbr

    fun printNameAndNumber() {
        println("Name: $name")
        println("Number: $nbr")
    }
}

or even simpler

class Test(val name: String, val nbr: Int = 0) {
    fun printNameAndNumber() {
        println("Name: $name")
        println("Number: $nbr")
    }
}

If you want your nbr member as nullable, you couldgo with the suggestion of @gil.fernandes.

like image 1
DVarga Avatar answered Oct 21 '22 00:10

DVarga