const val MaxLength = 9 //Example number
fun Add (x : Int, private pos: Int = MaxLength) {...}
would work exactly like:
const val MaxLength = 9 //Example number
private fun Add (input: Int, pos:Int) {...}
fun Add (x : Int) = Add(input, MaxLength)
I could have written it as: fun Add (input: Int, pos: Int = MaxLength), but then I expose my pos parameter.
Visibility modifiers on default parameters would work similarly to how visibility modifiers work on properties with custom getters/setters: Default parameter visibility must be the same or less permissive than function visibility.
Don’t think there are any. The only question is, should this also support protected and internal and if yes how would you be allowed to combine those.
It might be confusing then if a parameter on the right has a broader visibility than one on the left:
fun foo(a: Int, private b: Int = 42, c: Int = 5) {}
The private on b would require at least the same restriction on the parameters to its right, namely c, and thus make the above declaration equivalent to:
private fun foo(a: Int, b: Int, c: Int) { ... }
private fun foo(a: Int, b: Int) = foo(a, 42, 5)
fun foo(a: Int) = foo(a, 42, 5)
For some reason I forgot that those parameters need to have default values.
One thing this might lead to confusion with is the constructor though.
class Foo(private val a: Int, val b: Int)
still would lead to a public constructor taking 2 arguments. In this case the private means that the property is private. This would lead to basically the same syntax with 2 different meanings. In one case the visibility modifier is creating additional overloads of the function and in case of the primary constructor it doesn’t.
My point was not about a syntax problem, but a semantic problem. What would you expect my function to be equivalent to in current Kotlin?
fun foo(a: Int, private b: Int = 42, c: Int = 5) {}
If you can’t know about b from the outside, and you want to provide c because it’s public, it seems the only way to call foo from outside would be with named parameters, or we would need 2 overloads of foo with 2 Int parameters, which AFAIK is not possible. Did I miss something here?
This is I believe, what @Wasabi375 also mentioned.
fun foo(a: Int, private b: Int = 42, c: Int = 5) {}
would be
fun foo(a:Int, c: Int = 5) = foo(a, 42, c)
private fun foo(a: Int, b: Int = 42, c: Int = 5) {}
EDIT: okay I just got the issue. If you were to call the function within the class, which one would it call. The private or the public function.
I suppose a way would be to keep visibility modified default paramters as the last few arguments ordered by permissibility.
Another way, though it might be confusing semantically, would be that the public function is only callable from outside the class. Whereas the private function is the only one callable from inside the class.
I think @icecubez reply was correct that it would be only one overload. And that would only be if they want to support the privateness of that parameter when calling from Java. Kotlin itself would not necessarily need it, but I could be wrong. I would have no problem if it only generated the overloads if you added @JvmOverloads.
No @Wasabi375 was talking about the fact in this proposal private controls whether the parameter can be passed, but in constructors it controls visibility of the generated property and those dual meanings could be confusing.
I think you are. As far as I know @JvmOverloads is only used to handle default parameters. Java itself does not have this concept so you create the overloads for those parameters.
I don’t think however there is a way to create functions multiple visibility modifiers on byte code level so I guess the overloads will be created in any case. It might be possible to define the overloads as inline (in case of protected and internal).
that Kotlin just generated the one method and simply called the full method passing the default, but I am wrong. That wouldn’t work in complex cases where the default value is more complex. I see that it generates a static synthetic bridge method that in Java looks like this:
// $FF: synthetic method
// $FF: bridge method
public static void a$default(Foo var0, int var1, int var2, int var3, Object var4) {
if ((var3 & 2) != 0) {
var2 = 5;
}
var0.a(var1, var2);
}
That seems to tell me that there is a performance penalty with default values for parameters.