2

Why does this not compile?

class test
{
  constructor() {
      var a = Date().day
      this(a)
  }

  constructor(a:Int) {
  }
}

error is: Expression 'this' of type 'test' cannot be invoked as a function. The function 'invoke()' is not found.

The suggested fix is to add this:

private operator fun invoke(i: Int) {}

Why?

3 Answers 3

8

First, both of these constructors are secondary constructors. A primary constructor is one which is located outside of the body of the class.

Second, as described in the documentation, the correct syntax to call another constructor is as follows:

class Test {
    constructor() : this(1) { }

    constructor(a: Int) { }
}
Sign up to request clarification or add additional context in comments.

3 Comments

What if you need to do some calculations before calling the secondary constructor such as: class test { constructor() { var a = Date().day this(a) } constructor(a:Int) { } }
You can't do this. This is a JVM restriction. If this was possible, the object would exist in an uninitialized state during the execution of var a = Date(), and this is not allowed.
wait... depending on what you calculate, you can, e.g. you may write: constructor() : this(Date().day) or maybe I just didn't understand your question correctly ;-) If it's a more complex calculation but you start from a new instance somewhere, you may use something like constructor() : this(ComplexObject().let { /* complex function leading to Int */ })
1
class test constructor(){ // primary constructor (The primary constructor is part of the class header: it goes after the class name (and optional type parameters))

    constructor(a: Int) : this() { // secondary constructor

    }
}

If you class have define primary constructor, secondary constructor needs to delegate to the primary constructor. See here.

I think primary constructor can not be called from secondary constructor.

You can think like this: secondary calls primary and primary calls secondary => endless loop => not possible

In your case, there are 2 secondary constructor, so you can do like

class test {

    constructor() : this(Date().day) // I see it quite like Java here https://stackoverflow.com/questions/1168345/why-do-this-and-super-have-to-be-the-first-statement-in-a-constructor

    constructor(a: Int) {
    }
}

Comments

-2

Couple of things are wrong here:

  • Classes should always use camel-case for their names (test -> Test)
  • You cannot call another constructor as you tried to (calling this(1) inside of the other constructors body)

I think what you actually want is a being a property and alternatively initialize it with a default value. You could do it like this

class Test(val a: Int) {
    constructor() : this(1) // notice how you can omit an empty body
}

or even better, like this:

class Test(val a: Int = 1) // again an empty body can be omitted.

Edit:

If you need to do some calculations, as asked in the comment below Yole's answer:

class Test(val day: Int) {
    // you can use any expression for initialization
    constructor(millis: Long) : this(Date(millis).day) 
}

or if things get more complicated:

class Test(var day: Int) {
    // pass something (i.e. 1) to the primary constructor and set it properly in the body
    constructor(millis: Long) : this(1) { 
        // some code
        day = // initialize day
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.