Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

300
Views
Why private constructor of sealed class can be called in sub class?

Sealed class in Kotlin can have private constructor only. That means we can call the constructor only in itself:

Sealed classes are not allowed to have non-private constructors (their constructors are private by default).

// `private` and `constructor()` are redundant.
sealed class Expr private constructor()

But, when we utilize sealed class, a sub class have to inherit seald class:

// Above Kotlin 1.1
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()

As you can see the code above, sealed class's private constructor is called outside of sealed class itself. When sub class is instantiated, the constructor of parent(sealed class) will be called before sub class's own constructor is called. Is it just exception to visibility modifiers?

https://kotlinlang.org/docs/reference/visibility-modifiers.html#classes-and-interfaces

For members declared inside a class: private means visible inside this class only (including all its members);

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Consider the following code:

open class A private constructor(var name: String){
    class B : A("B")
    class C : A("C")
}

The above code compiles fine, as the constructor is called inside the class A. If a class D tries to inherit outside A, it won't compile.

class D : A("D") // Error: Cannot access '<init>': it is private in 'A'

As mentioned on the page Sealed class in Kotlin,

A sealed class can have subclasses, but all of them must be declared in the same file as the sealed class itself. (Before Kotlin 1.1, the rules were even more strict: classes had to be nested inside the declaration of the sealed class).

It seems that kotlin relaxed the requirement of nested classes only.

So, the following code works fine in 1.1+ but would fail in earlier versions:

sealed class A(var name: String)
class B : A("B")
class C : A("C")

whereas the following code would have been required in versions before 1.1, which respects the private constructor.

sealed class A (var name: String){
    class B : A("B")
    class C : A("C")
}

So, allowing private constructors of sealed classes outside the class (but within the same file) can be considered an enhancement to make the code cleaner.

over 4 years ago · Santiago Trujillo Report

0

You can figure out what's happening by taking a look at the generated bytecode (you can do this by going to Tools -> Kotlin -> Show Kotlin Bytecode and then choosing Decompile in the pane that appears.). Decompiling it to Java shows this code for the Expr class:

public abstract class Expr {
   private Expr() {
   }

   // $FF: synthetic method
   public Expr(DefaultConstructorMarker $constructor_marker) {
      this();
   }
}

So there is a non-private constructor for the Expr class generated, with a special parameter. Then, as you'd expect, if you look at the decompiled bytecode of Const for example, you'll see that it calls into this constructor:

public final class Const extends Expr {
   public Const(double number) {
      super((DefaultConstructorMarker)null);
      this.number = number;
   }

   // other fields and methods ...
}

You still can't subclass Expr from Kotlin, because the Kotlin compiler knows that it's a sealed class from the metadata in the file, and will respect that.

As for Java client code, there you can't access this same constructor yourself because the DefaultConstructorMarker is package-private in the kotlin.jvm.internal package that it's in, so even if you write out the import statement for it manually, the compiler won't allow it.

My guess is that the package-private visibility might only be enforced at compile time, and that's why the Kotlin compiler is able to output the bytecode corresponding to the snippet above (not completely sure though).

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!