Calling super within the body of a constructor

Is there any way to do something like this in Kotlin?

open class ParentClass(test: Int) {

    var test: Int = 0

    init  {
        this.test = test + 1
    }

}

class ChildClass : ParentClass {
    
    constructor() {
        super(1)
    }
    
}

I basically want to call super from within the constructor body, so that I can do some calculations on a variable before I pass it into the parent constructor.

This is the closest I’ve come to solving this, and it doesn’t look fantastically elegant.

open class ParentClass(test: Int) {

    var test: Int = 0

    init  {
        this.test = test + 1
    }

}

class ChildClass(test: Int = ChildClass.doSomething()) : ParentClass(test) {

    companion object {
        fun doSomething() : Int {
            return 1
        }
    }

}
2 Likes

I too would like a way to call super in the body of the constructor.

1 Like
class ChildClass : ParentClass {
    
    constructor() : super(1)
    
}
1 Like

I think it would be a good idea, if you have to prepare something for the super class, for example in a current Exersise from school, I have to create a sub-class of BufferedReader which needs the following Parameters for constructor:

@Contract(pure = true)  
public BufferedReader(     @NotNull  java.io.Reader in,
    int sz )

My class only takes filename and parameters but not an Reader as input, so before calling the super I would like to check if the file exists, handle other possible problems, create a File and create the Reader before calling the super method.

The closest I got is this, but I don’t think its the best solution

import java.io.BufferedReader
import java.io.File
import java.io.FileNotFoundException
import java.io.Reader

class GNSSSimulatur(private val filename: String, private val sleep: Int, private val filter: String): BufferedReader(
    createFileReader(filename),10){
    companion object {
        private fun createFileReader(_filename: String): Reader {
            val file = File(_filename)
            if (!file.exists()) throw FileNotFoundException(_filename)
            return file.reader()
        }
    }
}

Allowing code to run before the superclass is problematic. For these use cases where creating an object requires additional steps, validation, or decoupled logic to be run, I’d recommend learning the creational design patterns.

This is made even better in Kotlin in that there is no new keyword, making factory methods usage identical to constructors.

Constructors running to initialize the object assume their parents’ methods and members are available to them and initialized. Doing much more than setting up the class can be a code smell.

Here’s an alternative that uses a factory method and takes advantage of Kotlin’s features to make it look like it’s just the normal constructor–note that you could put this logic anywhere else to avoid coupling it to the class (ex. another file, as a member of some context class, a top level function, etc)

import java.io.BufferedReader
import java.io.File
import java.io.FileNotFoundException
import java.io.Reader

class GNSSSimulatur private constructor(
        private val fileReader: Reader, 
        private val sleep: Int, 
        private val filter: String
    ) : BufferedReader(fileReader, 10) {
    
    companion object {
        // Factory method. Plenty of other ways to do this.
        operator fun invoke(filename: String, sleep: Int, filter: String) : GNSSSimulatur {
            val file = File(filename)
            if (!file.exists()) throw FileNotFoundException(filename)
            return GNSSSimulatur(
                fileReader = file.reader(),
                sleep = sleep,
                filter = filter
            )
        }
    }
}


fun main() {
    // Should fail since this is in Kotlin Playground and you can't access files.
    val sim = GNSSSimulatur("filename", 100, "filter")
    // Notice how it looks like a normal constructor.
}
1 Like