81
votes

I am in the processing of learning Kotlin and ran into a problem I couldn't figure out. I would like to extend the Java class RuntimeException in Kotlin and be able to use any one of three of its constructors, in different circumstances (based on what info I have at the time I want to throw an exception). In java my class would look like this:

public class PhotoLibException extends RuntimeException {

    public PhotoLibException(String message, RuntimeException ex) {
        super(message, ex);
    }

    public PhotoLibException(String message) {
        super(message);
    }

    public PhotoLibException(RuntimeException ex) {
        super(ex);
    }
}

When I try to do this in Kotlin, I used this answer as a guide: Kotlin secondary constructor however, I had a problem trying to figure out how to invoke the appropriate super constructor correctly. For example, using functions seemed to be a good approach, like this:

fun PhotoLibException(message: String): PhotoLibException {
    val ex = null
    return PhotoLibException(message, ex)
}

fun PhotoLibException(ex: Exception): PhotoLibException {
    val message = ""
    return PhotoLibException(message, ex)
}

class PhotoLibException(message: String, ex: Exception?): RuntimeException(message, ex) {
}

However, in this Kotlin example above, I am always invoking the super constructor with two args, and not invoking the constructor most appropriate to the situation. So what I have above works, but doesn't do exactly what it would do in Java where a different constructor is invoked in each situation. I also tried instantiating a new RuntimeException inside each fun above and casting it to PhotoLibException, but I wasn't allowed to do that.

Can anyone suggest how I would do this correctly in Kotlin?

2

2 Answers

154
votes

Update: Since M11 (0.11.*), you can use secondary constructors to solve this problem:

class PhotoLibException : RuntimeException {
    constructor(message: String, ex: Exception?): super(message, ex) {}
    constructor(message: String): super(message) {}
    constructor(ex: Exception): super(ex) {}
}

Currently, there's no way to call different super-constructors in different context from the same class. It will be supported in the upcoming months, though.

4
votes

Use the @JvmOverloads annotation.

class PhotoLibException: RuntimeException {
   @JvmOverloads constructor(message: String, ex: Exception?)
}