kotlin, how to keep the class constructor internal (but class is visible in outside)

1.4k Views Asked by At

In a android lib, having a public class in java which has default package level constructors

public class UserInformationException extends Exception {

    private static final String ERROR_MESSAGE = "User information wrong!!";

    UserInformationException(String msg) {
        super(msg);
    }

    UserInformationException() {
        super(ERROR_MESSAGE);
    }

This class is visible from other app (or outside the package), but the other part cannot create instance of it.

After converting this class into kotlin (using the internal modifier to restrict to visible only to this module is fine here)

class UserInformationException internal constructor(msg: String = ERROR_MESSAGE) : Exception(msg) {
    companion object {
        private const val ERROR_MESSAGE = "User information wrong!!"
    }
}

Looks like the kotlin internal constructor become public and be able to create the instance from it. The decompiled java code here:

public final class UserInformationException extends Exception {
   private static final String ERROR_MESSAGE = "User information wrong!!";
   @NotNull
   public static final UserInformationException.Companion Companion = new UserInformationException.Companion((DefaultConstructorMarker)null);

   public UserInformationException(@NotNull String msg) {
      Intrinsics.checkNotNullParameter(msg, "msg");
      super(msg);
   }

   // $FF: synthetic method
   public UserInformationException(String var1, int var2, DefaultConstructorMarker var3) {
      if ((var2 & 1) != 0) {
         var1 = "User information wrong!!";
      }

      this(var1);
   }

   public UserInformationException() {
      this((String)null, 1, (DefaultConstructorMarker)null);
   }

   public static final class Companion {
      private Companion() {
      }

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

Question: how to create class with (equivalent java package level visibility - the kotlin's internal to the module is fine) internal constructor only constructor?

1

There are 1 best solutions below

3
On

You may simply do

data class MyPublicClass internal constructor(val property: String)

Every one can see it but only the current module can construct it.

Kotlin can not create package private visibility code. This is a language design choise. There are also no annotations available to tell the compiler wich visibiltiy should be choosen for this use case.