I was surprised and disappointed to see the default modifier for classes is now public. As it said in the blog post, this seems like a controversial choice given Kotlin's aim to be a safe language.
First, I want to make sure that I’m understanding it correctly. Is a public class always visible to code in other modules? That is less safe than the new Java module system where a package must be exported for its public classes to be visible in other modules. If Kotlin supported a similar system of explicit exports from modules then public visibility would seem like a sensible default. But if public classes are automatically visible to the whole world then this change means a loss of encapsulation for anyone who doesn’t think carefully about visibility and declare their classes as internal. Which is almost everyone.
One of the points in the blog used to explain the change is that most Java codebases contain mostly public classes. I suspect this is because the default class templates in IDEs have a public modifier and no-one changes the templates or the classes they generate. The result is that Java code is full of packages that unnecessarily expose their internal implementation to the world. This shows the power of defaults and is somewhere Kotlin could be better than Java by choosing safer defaults. As it stands Kotlin will be as bad as Java 8 and worse than Java 9.
FWIW, I’ve edited my code templates in IDEA to use package scope for classes and interfaces. If I make something public it is a conscious design decision. I suspect an analysis of my code would show up a lot more non-public classes than average. That isn’t because I obsessively think about API design and make my code private, it’s because I lazily accept the defaults like most developers, I’m just using different defaults.
I’ve been re-reading some of the old threads on this subject and one of the suggestions was that classes could be internal by default and that properties, methods and constructors could be public. That seems like a better balance of safety and convenience. Within a single module an internal class is the same as a public class. Modules are normally fairly large, so for the many projects that only contain a single module the effect of default internal classes will be the same as default public classes. If a project is large enough to contain multiple modules it’s probably good for you to think about visibility and which parts of your API you want to expose to other modules.
Is there a problem with that approach I’ve missed?