Having 'internal' as the default access modifier


#1

Hello,

I’ve read somewhere that the plan for access modifiers in Kotlin (public, private, etc.) is that the default access modifier will be ‘internal to the current compilation module’.

However, I also noticed that this page

http://confluence.jetbrains.net/display/Kotlin/Modules+and+Compilation

which says that the modules concept is being redesigned. Does this include the idea of having things be ‘internal’ access by default?

I always thought the design in Java of having things be package private by default was a bad choice, and to my mind the obvious default in a language that has properties is ‘public’. In my experience, ‘package private’ is somewhat common in Java for class definitions (although much less common than ‘public’) but virtually unheard of for methods or fields. Indeed, on more than one occassion I’ve come accross professional Java developers that did not know that the default access level in Java is ‘package private’. Although it’s perhaps not surprising, as I also write Java for a living, and I’ve only seen it (deliberately) used a handful of times for methods or fields.

Cheers

Tom


#2

I also don't like internal as the default. It means that any "real" code I'll write will be shock-full of noisy public and private modifiers. :-(

I like the C# default of private on class members. http://msdn.microsoft.com/en-us/library/ms173121.aspx


#3

Since classes are final by default, I think it would be more consistent (and arguably better from a design standpoint) for methods to be private by default.


#4

+1


#5

I think having private the default isn't a bad choice, certainly loads better than module-internal, and for C# private makes sense.

However, Scala choose public as default, and I think that makes sense for the kind of features it has, and for Kotlin too. In particular, consider this simple data class.

data class Person(val firstname: String, val surname: String, val age: Int)

Should these properties be private by default? It’s kind of hard to argue they should for a data class like this there would be no point to the class if they are private. So do you have different rules for constructor-parameters-as-properties than for normal properties? Do you force users to write ‘public’ in front of all their constructor-properties?

What about properties and methods in traits … the only sensible default is ‘public’ by default. To my mind, I like the simplicity of saying “The default is always public” rather than “It’s public in this case and that case, but private in this other case”.

As I say, Scala has public by default and it works very nicely in Scala. Since ‘val’ is the default, there is rarely much need to make fields private, so the most common access modifier you see in practice is definitely public.

Cheers

Tom


#6

My point was that internal as the default means I'll have to litter my code with BOTH private and public if I'm feeling paranoid.

So it doesn’t matter for me whether public or private is the default for class members.
I think you have a very sane point in that public should be default in languages like Kotlin.


#7

We already have 'internal' visiblity by default now.

Public by default is not a good idea, because public members are part of API.

Good architecture rules say that API must be as small as it is possible. Making everything public by default makes it too easy to add something to API while you don’t mean to. If you miss it, you’ll have to either support it or remove it, breaking compilation. Also, accidental public members makes classes harder to understand when you are trying to use them.

Private by default is not that bad, but there is a problem that private members are not visible from everywhere from your code, which is a problem for small modules (where you’d rather not think about visibility at all) or prototypes.


#8

Yup, I noticed that Kotlin has internal as the default modifier :)

So I think internal as the default is a bad idea. Looking at how the default of ‘package private’ for methods and fields has worked out in Java, I believe it has not worked out very well. Firstly ‘internal’ to the compilation unit is somewhat of a confusing concept for methods. Remember that the scope of a method is already limited by the scope of the class it is in. If the class is hidden, the public methods are also hidden. Thus the meaning of package private (or ‘internal’) for a method or property is really:

Even if you can see this class, then you can’t call this method, unless you happen to be in the same package/module as this class.


This is a very strange and unusual set of access requirements and is very rarely what people intended. Indeed because package private is so rarely used in Java, people in my workplace generally feel the need to specifically annotate it’s use. That is, on the rare occasion someone actually does want a package-private method they normally end up doing this:

/* package */ void myPackagePrivateMethod() { …


In other words, because the default of package private is confusing and unusual, people want to annotate their code with a keyword when they actually want to use it. To my mind this is a clear indication that the default is wrong.

I take your point on public APIs but in my opinion there are two possible solutions to this:

  1. Make classes be ‘module internal’ by default, but methods and properties be public by default. That way something is not going to be a part of their API unless the user specifically annotates their class to say that it should.
  2. Make the default be private by default for methods, properties and classes.


Personally I don’t think public by default is a big problem. While it is true that in theory someone might accidentally make a method a part of their public API, I’ve not seen that be a problem in practice in Scala code (which is public by default). I have also seen people make things public in Java when they didn’t mean to. Ultimately people need to think about what is public and what is private, having a default of internal doesn’t automatically solve this issue.


Your point is taken on having private as the default, private as default would force people working in small codebases to write access modifiers. But this might be a good idea anyway. Indeed, another of my concerns with internal as default is that it creates a strong distinction between a project that is a single module (leave off all the access modifiers) and a larger multi-module project (you need to have public access modifiers). Kotlins modules are pretty large units, many interesting programs may start life as a single module and later become multi-module … at which point you need to go back and add modifiers to every public method in every public class. It’s also really bad for training: that what you should do in the small is not the same as what you should do in the large.

The same training issue exists in Java as well with it’s package-privae, and as a result Java training religously teaches people to always put in their access modifiers, whatever the size of their code. I suspect a similar thing would happen for Kotlin as well, entirely negating the argument that private-as-default is bad for coding in the small.

So whilst I can see some arguments for a default of ‘internal’, I think it all comes at quite a high cost in my opinion. You end up having to put lots of ‘public’ and ‘private’ modifiers throughout your code, coding in the large is different from coding in the small, and worse still you end up with a default that is a very unusual case, so much so that when people actually do want that in Java they feel the need to annotate their intention …


#9

Internal accessor is less expected than any other, because you need to think hard before set it. Also private and public is widely applicable and have to many letters. And so i don't want write them both.

Public or private by default? Tom Shackell says the right words. But there is some problem, public can’t be. Because for this accessors we need to write full type, it is kotlin agreement. Another problem, constructor parameters. They of course have to be public. Traits? it is something new to me, no ideas for now.

At all, I prefer private.


#10

FWIW, I use package scope all the time in Java. I think *very* carefully before I make anything public. It would be a terrible thing if the default visibility were public. I think you can make a good argument for any of private, package or internal scope to be the default.

I think it’s interesting that “package” seems to be available as an explicit modifier in Java 8:

http://hg.openjdk.java.net/lambda/lambda/langtools/rev/d78663601eb9

Maybe there shouldn’t be a default visibility and a modifier should be mandatory. That way there’s no doubt.


#11

So in my experience, people tend to use package-private in Java in two common and one uncommon circumstance.

Common case 1: being lazy and using package-private when they really mean private.

If you’re not too fussy, you can just assume that package-private is the same as private. I don’t think this is a great idea, and again it sort of indicates that package-private isn’t a good default.

Common case 2: package-private method in a package-private class.

In a class that is package-private, a package-private method is the same as a public one. So this is basically the same as using public.

Uncommon case: A package-private method in a public class

This is the only one that really uses package-private correctly and where no other modifier would do. It’s also very unusual. Since it generally means you have something that is largely private, but you want to leak the internal details to other classes in the same package. Probably because they are doing something funky. Occasionally this is useful for doing something similar to C++ ‘friend’ classes, but … it can also indicate bad class design.

Interestingly the consensus on this board seems to be that people are preferring private-by-default. Personally I think that’s a pretty reasonable choice, although as noted, there are one or two interesting questions around constructor-properties and trait methods.


#12

Issue http://youtrack.jetbrains.com/issue/KT-3240

Everyone can vote

Thanks, B7W


#13

My uses are almost all case 2. You're right that having public methods on a package scoped class is the same as having package scoped methods. But why would you do that? That seems odd to me and doesn't communicate the intent very clearly to someone reading the code.


#14

I guess that varies from person to person. Personally I generally like to think in terms of two very simple access modifiers, for both classes and methods:

  public - this item is visible outside.
  private - this item is only visible inside.

These are two very simple ideas that can be applied everywhere. A public class is visible outside the package, a private one is visible only inside the package. A public method is visible outside the class, a private one is only visible inside. It makes for a really nice, clean, simple mental model of accessibility that is difficult to misunderstand. In contrast package-private is quite a bit more complex to understand. Therefore even in package private classes I still explictly declare methods public.

I suspect that most people do the same, I work as a Java software developer for IBM, and very very rarely do I see anyone use package private for methods, even in package private classes. Almost everything is always declared either public, private or protected.