Skip to content

Commit c4b828c

Browse files
committed
Add README
1 parent a4b5edd commit c4b828c

1 file changed

Lines changed: 124 additions & 0 deletions

File tree

README.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# scijava-optional
2+
3+
Helpers for emulating named and default arguments in builder-like classes.
4+
5+
The scenario is that certain methods take optional parameters, subsets of which can overlap.
6+
For example, `FactoryA` should take `FactoryAOptions` and
7+
`FactoryB` should take `FactoryBOptions`, where both `FactoryAOptions` and `FactoryBOptions`
8+
expose an optional parameter "`int a`" with the same meaning and default values.
9+
10+
To maintain convenience and type-safety, both `FactoryAOptions` and `FactoryBOptions` should expose
11+
a method `a(int)` to set the optional parameter. But `FactoryAOptions::a` should return an `FactoryAOptions`,
12+
and `FactoryBOptions::a` should return an `FactoryBOptions` to allow chaining more parameters of
13+
`FactoryAOptions` and `FactoryBOptions` respectively, while retaining the type of the builder.
14+
15+
Using scijava-optional, this can be achieved as follows:
16+
17+
Each subset of optional parameters ("`int a`" in the above example) is implemented as two interfaces,
18+
one exposing methods to set the parameters, one exposing methods to retrieve parameter values.
19+
20+
For setting:
21+
```java
22+
interface OptionA<T extends OptionA<T>> extends Options<T> {
23+
default T a(int a) {
24+
return add("a", a);
25+
}
26+
}
27+
```
28+
where the `a()` method records the parameter value (with key `"a"`) via the
29+
`add()` method of the `Options` super-interface.
30+
31+
For getting:
32+
```java
33+
interface ValueA extends Values {
34+
...
35+
default int a() {}
36+
return value( "a", 0 );
37+
}
38+
}
39+
```
40+
where the `a()` method returns the parameter value (with key `"a"` and default value `0`)
41+
via the `value()` method of the `Values` super-interface.
42+
43+
Finally, the implementation of `FactoryAOptions` derives from `AbstractOptions` and all desired
44+
subsets of options
45+
```java
46+
public class FactoryAOptions
47+
extends AbstractOptions< FactoryAOptions >
48+
implements OptionA< FactoryAOptions >, ...
49+
{
50+
static class FactoryAValues
51+
extends AbstractValues
52+
implements ValueA, ...
53+
{
54+
...
55+
public FactoryAValues(FactoryAOptions options) {
56+
super( options );
57+
}
58+
}
59+
60+
public final FactoryAValues values = new FactoryAValues(this);;
61+
62+
// =======================================================================
63+
64+
// If in-place modification of the options builder is desired,
65+
// the following methods should be left out.
66+
67+
public FactoryAOptions() {
68+
super();
69+
}
70+
71+
private FactoryAOptions(FactoryAOptions that) {
72+
super(that);
73+
}
74+
75+
@Override
76+
public FactoryAOptions copyOrThis() {
77+
return new FactoryAOptions(this);
78+
}
79+
80+
// =======================================================================
81+
82+
// The following is not necessary, but can be overridden like this
83+
// to make it show up more nicely in IDE auto-complete
84+
85+
@Override
86+
public FactoryAOptions a(int a) {
87+
return OptionA.super.a(a);
88+
}
89+
}
90+
```
91+
The parameter values are exposed through inner class `FactoryAValues` that derives from `AbstractValues`
92+
and all desired subsets of option values.
93+
94+
The only thing that has been omitted from the above example is the parts that provide a nice `toString` implementation
95+
for the values. This is be achieved by
96+
```java
97+
interface ValueA extends Values {
98+
default void buildToString(AbstractValues.ValuesToString sb) {
99+
sb.append("a", a());
100+
}
101+
102+
default int a() {
103+
return value("a", 0);
104+
}
105+
}
106+
```
107+
and
108+
```java
109+
static class FactoryAValues
110+
extends AbstractValues
111+
implements ValueA, ...
112+
{
113+
@Override
114+
public String toString() {
115+
final ValuesToString sb = new ValuesToString();
116+
ValueA.super.buildToString(sb);
117+
return sb.toString();
118+
}
119+
120+
public FactoryAValues(FactoryAOptions options) {
121+
super(options);
122+
}
123+
}
124+
```

0 commit comments

Comments
 (0)