6
6
[ ![ chat] ( https://img.shields.io/badge/discord-manifold-seagreen.svg?logo=discord )] ( https://discord.gg/9x2pCPAASn )
7
7
[ ![ GitHub Repo stars] ( https://img.shields.io/github/stars/manifold-systems/manifold?logo=github&style=flat&color=tan )] ( https://github.com/manifold-systems/manifold )
8
8
9
- The ` manifold-params ` project is a compiler plugin that implements optional parameters and named arguments for methods,
10
- constructors, and records. Use it with any Java project to add clarity and flexibility to call sites and to reduce boilerplate
11
- in class definitions .
9
+ The ` manifold-params ` project is a compiler plugin that implements binary compatible _ optional parameters and named arguments _
10
+ for methods, constructors, and records. Use it with any Java project to add clarity and flexibility to call sites and as
11
+ a refreshing alternative to method overloads and builders .
12
12
13
13
``` java
14
14
public String valueOf(char [] data,
15
15
int offset = 0 ,
16
16
int count = data. length - offset) {... }
17
17
18
- valueOf(array) // use default values for offet and count
19
- valueOf(array, 2 ) // use default value for count
20
- valueOf(array, count: 20 ) // use default value for offset
18
+ valueOf(array) // use default args for offet and count
19
+ valueOf(array, 2 ) // use default args for count
20
+ valueOf(array, count: 20 ) // use default arg just for offset by naming count argument
21
21
```
22
22
23
- Optional parameters and named arguments are fully integrated in both ** IntelliJ IDEA** and ** Android Studio** . Use the IDE's
24
- features to be more productive with optional parameters and named arguments.
23
+ Optional parameters and named arguments are fully integrated in both ** IntelliJ IDEA** and ** Android Studio** .
24
+
25
+ <!-- TOC -->
26
+ * [ Optional parameters & named arguments] ( #optional-parameters--named-arguments )
27
+ * [ Optional parameters] ( #optional-parameters )
28
+ * [ Named arguments] ( #named-arguments )
29
+ * [ Overloading and overriding] ( #overloading-and-overriding )
30
+ * [ Binary compatible] ( #binary-compatible )
31
+ * [ Notes & tidbits] ( #notes--tidbits )
32
+ * [ IDE Support] ( #ide-support )
33
+ * [ Install] ( #install )
34
+ * [ Setup] ( #setup )
35
+ * [ Building this project] ( #building-this-project )
36
+ * [ Using this project] ( #using-this-project )
37
+ * [ Binaries] ( #binaries )
38
+ * [ Gradle] ( #gradle )
39
+ * [ Maven] ( #maven )
40
+ * [ Javadoc] ( #javadoc )
41
+ * [ License] ( #license )
42
+ * [ Versioning] ( #versioning )
43
+ * [ Author] ( #author )
44
+ <!-- TOC -->
25
45
26
46
## Optional parameters
27
47
28
- An optional parameter has a default value assigned to it , much like a field or local variable with an initial value.
48
+ An optional parameter has a default value, much like a field or local variable can have an initial value.
29
49
``` java
30
50
void println(String text = " " ) {... }
31
51
```
@@ -36,29 +56,11 @@ println("flubber");
36
56
println(text: " flubber" ); // named argument syntax
37
57
```
38
58
39
- A default value may be an arbitrary expression of any complexity and can reference preceding parameters.
59
+ A default value expression may be arbitrarily complex and can reference preceding parameters.
40
60
``` java
41
61
public record Destination(Country country, String city = country. capital()) {}
42
62
```
43
63
44
- A method override automatically inherits all the super method's default parameter values. The default values are fixed in
45
- the super class and may not be changed in the overriding method.
46
- ``` java
47
- public interface Contacts {
48
- Contact add (String name , String address = null , String phone = null );
49
- }
50
-
51
- public class MyContacts implements Contacts {
52
- @Override // no default parameter values allowed here
53
- public Contact add (String name , String address , String phone ) {... }
54
- }
55
-
56
- Contacts contacts = new MyContacts ();
57
- contacts. add(" Fred" );
58
- // calling directly inherits defaults
59
- ((MyContacts )contacts). add(" Bob" );
60
- ```
61
-
62
64
If an optional parameter precedes a required parameter, positional arguments may still be used with all the parameters.
63
65
``` java
64
66
public Item(int id = - 1 , String name) {... }
@@ -101,7 +103,61 @@ configure("MyConfig",
101
103
showName: false ,
102
104
autoSave: false );
103
105
```
104
-
106
+
107
+ ## Overloading and overriding
108
+
109
+ A method override automatically inherits all the super method's default parameter values. The default values are fixed in
110
+ the super class and may not be changed in the overriding method.
111
+ ``` java
112
+ public interface Contacts {
113
+ Contact add (String name , String address = null , String phone = null );
114
+ }
115
+
116
+ public class MyContacts implements Contacts {
117
+ @Override // no default parameter values allowed here, they are strictly inherited
118
+ public Contact add (String name , String address , String phone ) {... }
119
+ }
120
+ ```
121
+
122
+ A method having optional parameters logically consists of the set of methods comprising the methods one would otherwise
123
+ write if using Java's idiomatic method overloads.
124
+ ``` java
125
+ void message(String content, int id = 0 , LocalTime timestamp = null )
126
+ ```
127
+ Logically occupies the following method signatures.
128
+ ``` java
129
+ void message(String )
130
+ void message(String , int )
131
+ void message(String , int , LocalTime )
132
+ ```
133
+ These are called the _ sub-signatures_ of the optional parameter method.
134
+
135
+ An optional parameter method automatically overrides any super type methods whose signatures are _ sub-signatures_ of the
136
+ optional parameter method. Generally, a sub-signature is one that partially matches the optional parameter method using
137
+ Java's idiomatic "telescoping" method overload analogy as described above.
138
+ ``` java
139
+ class Base {
140
+ void func () {... }
141
+ }
142
+
143
+ class Sub extends Base {
144
+ @Override
145
+ void func (int id = 0 ) {... }
146
+ }
147
+ ```
148
+ ` Sub#func(int) ` indirectly overrides ` Base#func() ` . As with full signature overriding, the compiler issues a warning for
149
+ this if ` @Override ` is not applied to ` func(int) ` . Note, a future release may include a more suitable annotation to name
150
+ specific overloaded method signatures.
151
+
152
+ Overloading is permitted with optional parameter methods, however a compiler error results if sub-signatures overlap.
153
+ ``` java
154
+ class Sample {
155
+ void func ()
156
+ void func (int alpha = 0 ) // error: clashes with func()
157
+ void func (int beta , int gamma = 0 ) // error: clashes with func(int)
158
+ }
159
+ ```
160
+
105
161
## Binary compatible
106
162
107
163
Adding new optional parameters to existing methods is binary compatible with code compiled before adding the new parameters.
@@ -123,6 +179,25 @@ size(myWidth);
123
179
size (myWidth , myHeight );
124
180
```
125
181
182
+ ## Notes & tidbits
183
+
184
+ #### Why limit named arguments to only methods with optional parameters?
185
+ Since the feature is neither part of the language nor the JVM , supporting named args for arbitrary methods would incur a
186
+ bit of perf/ space overhead for each method/ constructor/ record, which isn' t really justifiable considering modern IDEs like
187
+ IntelliJ IDEA already render positional argument names, aka "name hints", in call sites. Basically, if you want this feature,
188
+ you already have it without any direct language support. Right?
189
+
190
+ Where named arguments become invaluable is when used as a means to select optional parameters. The synergy between these
191
+ two features provides a concise, flexible, and maintainable alternative to builders and "telescoping" method/constructor
192
+ overloads.
193
+
194
+ #### Why does the named argument syntax use `:` instead of `=`?
195
+ Indeed, many languages having named arguments, such as Kotlin and Scala, use the syntax: `foo(x = 8)`. One problem with
196
+ that, however, is Java' s assignment expression clashes where `x = 8 ` may be parsed as an assignment as opposed to a mapping
197
+ of an argument. While this could be worked out, overloading the assignment operator in a prominent place like argument parsing
198
+ probably isn' t the best idea.
199
+
200
+ Perhaps the main reason is aesthetics. `x: 8` just reads more like a naming or labeling of something. Shrug.
126
201
127
202
# IDE Support
128
203
0 commit comments