Java n'a pas de ** fonctionnalité d'argument par défaut **, j'ai donc résumé une implémentation alternative.
TL;DR Je pense qu'il n'y a pas de problème s'il est mis en œuvre avec la politique suivante.
Nombre d'arguments que vous souhaitez définir par défaut | Solution |
---|---|
~ 4 | Surcharge |
5 ~ | Modèle de constructeur |
L'argument par défaut dans cet article est si la valeur n'est pas définie comme argument réel lors de l'appel de la méthode. Au lieu de cela, c'est un mécanisme pour initialiser avec la valeur par défaut. (Je pense que c'est une syntaxe qui est principalement introduite dans les langues modernes)
Voici un exemple des arguments par défaut écrits en Groovy.
def foo(a = 0, b = "undefined") {
println "a = $a, b = $b"
}
foo(23, "hoge") // => a = 23, b = hoge
foo() // => a = 0, b = undefined
Vous pouvez facilement l'implémenter avec le modèle que vous voyez le plus souvent.
static void foo(int a, String b) {
System.out.println("a = " + a + ", b = " + b);
}
static void foo(int a) { foo(a, "undefined"); } //Seul l'argument b est l'argument par défaut
static void foo(String b) { foo(0, b); } //Seul l'argument a est l'argument par défaut
static void foo() { foo(0, "undefined"); } //Argument a,Les deux b sont des arguments par défaut
public static void main(String[] args) {
foo(23, "hoge"); // => a = 23, b = hoge
foo(23); // => a = 23, b = undefined
foo("hoge"); // => a = 0, b = hoge
foo(); // => a = 0, b = undefined
}
Dans l'exemple, les arguments déclarés dans foo (int a, String b)
sont de types différents, donc
La surcharge vous permet de définir des valeurs par défaut pour tous les arguments.
Si les arguments a et b sont du même type, il n'est pas possible de déclarer "argument par défaut uniquement pour l'argument a" et "argument par défaut uniquement pour l'argument b" en même temps.
Dans ce cas, il n'y a pas d'autre choix que de l'implémenter avec le modèle Builder décrit plus loin ou en passant Null.
La partie qui devient un argument de longueur variable a une restriction selon laquelle elle est le dernier des arguments de méthode, Si rien n'est spécifié dans le dernier argument, un tableau vide (longueur = 0) sera passé automatiquement. Par conséquent, dans de tels cas, il n'est pas nécessaire de surcharger.
static void foo(String a, int... b) {
int bSum = IntStream.of(b).sum();
System.out.println("a = " + a + ", sum = " + bSum);
}
public static void main(String[] args) {
foo("hoge", 23, 42); // => a = hoge, sum = 65
foo("hoge"); // => a = hoge, sum = 0
}
Outre la surcharge, il existe un modèle couramment utilisé qui utilise le modèle Builder pour définir les arguments par défaut. La surcharge est agréable car vous pouvez facilement définir la valeur par défaut, mais si le nombre d'arguments devient important Le code sera plus facile à lire si vous le remplacez par le modèle Builder. Selon la règle de SonarQube, il est souhaitable que le nombre d'arguments soit de 4 ou moins comme seuil. Java: Methods should not have too many parameters | SonarQube - Rules
Dans l'exemple, il est écrit pour définir la valeur par défaut dans le modèle Builder pour la méthode avec deux arguments.
import lombok.Builder;
import lombok.Value;
public class BuilderPattern {
static void foo(Foo foo) {
System.out.println("foo = " + foo);
}
public static void main(String[] args) {
var specifiedFoo = Foo.builder().a(23).b("hoge").build();
var defaultFoo = Foo.builder().build();
foo(specifiedFoo); // => foo = Foo(a=23, b=hoge)
foo(defaultFoo); // => foo = Foo(a=0, b=undefined)
}
}
@Value
@Builder
class Foo {
@Builder.Default
Integer a = 0;
@Builder.Default
String b = "undefined";
}
Vous pouvez faire la même chose avec le modèle Builder avec Map, mais si vous voulez le faire, je pense qu'il est préférable de l'écrire avec Builder.
static void foo(Map<Foo, Object> params) {
var a = (int) params.getOrDefault(Foo.A, 0);
var b = (String) params.getOrDefault(Foo.B, "undefined");
System.out.println("a = " + a + ", b = " + b);
}
public static void main(String[] args) {
foo(Map.of(Foo.A, 23, Foo.B, "hoge")); // => a = 23, b = hoge
foo(Map.of()); // => a = 0, b = undefined
}
enum Foo {
A, B
}
Comme je l'ai écrit dans l'explication de la surcharge, lorsque les arguments déclarés sont du même type, Dans certains cas, il n'était pas possible de définir une valeur par défaut pour chaque argument. La solution de contournement consiste à définir une valeur par défaut dans la méthode. Cependant, il n'est pas possible de déterminer quelle variable a la valeur par défaut en se basant uniquement sur la signature de la méthode. Les utilisateurs de méthode doivent regarder Javadoc ou l'implémentation de la méthode, qui est un modèle qu'ils ne veulent pas beaucoup utiliser.
static void foo(String a, Integer b, Integer c) {
b = Objects.requireNonNullElse(b, 0);
c = Objects.requireNonNullElse(c, 0);
System.out.println("a = " + a + ", b = " + b + ", c = " + c);
}
public static void main(String[] args) {
foo("hoge", 23, 42); // => a = hoge, b = 23, c = 42
foo("hoge", null, null); // => a = hoge, b = 0, c = 0
}
En tant que problème avec le modèle de passage nul mentionné ci-dessus "Il n'est pas possible de déterminer quelle variable a la valeur par défaut en se basant uniquement sur la signature de la méthode." Il est facile de se demander, "Eh bien, peut-être que le type facultatif peut être utilisé?", Mais cela semble être assez critiqué. Parce que le type facultatif est un mécanisme pour indiquer à l'appelant que la valeur renvoyée à l'origine par la méthode peut être nulle. Si vous utilisez le type facultatif pour l'argument, le code devient plus redondant et le nombre de codes sans signification augmente. Par conséquent, le style d'écriture suivant est strictement interdit.
static void foo(String a, Optional<Integer> bOpt) {
var b = bOpt.orElse(0);
System.out.println("a = " + a + ", b = " + b);
}
public static void main(String[] args) {
foo("hoge", Optional.of(23)); // => a = hoge, b = 23
foo("hoge", Optional.empty()); // => a = hoge, b = 0
foo("hoge", null); // => NullPointerException
}
Java optional parameters | Stack Overflow Java: Methods should not have too many parameters | SonarQube - Rules Why should Java 8's Optional not be used in arguments | Stack Overflow
Recommended Posts