Invocazione incatenata in Java 7?
-
06-07-2019 - |
Domanda
Stavo solo leggendo una presentazione in anteprima di Java 7 (pdf) e c'era una diapositiva su Invocazione incatenata . Ecco l'esempio usato nella diapositiva:
// Construction with setters
DrinkBuilder margarita = new DrinkBuilder();
margarita.add("tequila");
margarita.add("orange liqueur");
margarita.add("lime juice");
margarita.withRocks();
margarita.withSalt();
Drink drink = margarita.drink();
// Construction with chained invocation
Drink margarita = new DrinkBuilder()
.add("tequila")
.add("orange liqueur")
.add("lime juice")
.withRocks()
.withSalt()
.drink();
E ho sentimenti contrastanti al riguardo. Non si dovrebbero concatenare troppe invocazioni di metodi in un'unica istruzione. D'altra parte, scrivere margarita.this ()
e margarita.that ()
non è neanche troppo conveniente.
Ora vengo a Java dal mondo di Delphi. E a Delfi c'è il con
costrutto linguistico. Questo è apprezzato da pochi e detestato da molti (o è il contrario?). Trovo con
più elegante dell'idea di invocazione concatenata (che credo funzioni sulla base del metodo void
che restituisce il riferimento all'oggetto su cui è stata invocata - e questa è la parte che non mi piace, poiché void
dovrebbe restituire niente ).
Gradirei la funzionalità del linguaggio with
adottata da Java, quindi il codice di esempio potrebbe essere scritto in questo modo:
Drink margarita = null;
with (new DrinkBuilder()) {
add("tequila");
add("orange liqueur");
add("lime juice");
withRocks();
withSalt();
margarita = drink();
}
Sono l'unico che preferirebbe questa soluzione all'invocazione incatenata? Qualcun altro ritiene che con
possa essere un'estensione utile del linguaggio Java? (Mi ricorda la domanda di qualcuno sulla necessità di " Java ++ " ...)
Soluzione
l'istruzione with può essere tradotta in Java usando classi anonime con inizializzatore:
Drink margarita = new DrinkBuilder() {{
add(“tequila”);
add(“orange liqueur”);
add(“lime juice”);
withRocks();
withSalt();
}}.drink();
gli svantaggi dell'utilizzo di questo idioma sono ben documentati qui .
Chained Invocation è un alias per Method Chaining. Questo è un linguaggio ben noto e funziona con qualsiasi versione di Java:
class Chained {
public Chained withFoo() {
// ...
return this;
}
public Chained withBar() {
// ...
return this;
}
}
una proposta per JDK 7 è che consente il metodo di concatenamento anche per il tipo di ritorno vuoto :
class ChainedJava7 {
public void withFoo() {
// ...
}
public void withBar() {
// ...
}
}
Altri suggerimenti
Questo potrebbe interessarti.
Mi piace abbastanza con
le istruzioni di quel modulo ma preferisco la versione VB di esse:
With testObject
.Height = 100
.Text = "Hello, World"
.ForeColor = System.Drawing.Color.Green
End With
Poiché ogni attributo nel blocco With
deve ancora essere preceduto da un .
sai che stai facendo riferimento a una proprietà Object e non, diciamo, a una variabile locale , riducendo eventuali collisioni dello spazio dei nomi.
Se prendiamo il tuo esempio:
with (new DrinkBuilder()) {
add(“tequila”);
add(“orange liqueur”);
add(“lime juice”);
withRocks();
withSalt();
margarita = drink();
}
non c'è modo semplice per dire se withSalt ()
è un metodo di DrinkBuilder
o un metodo nella classe locale. Se consenti solo i metodi dell'oggetto con
nel blocco with
, penso che diventeranno molto meno utili.
Non sono un fan di questo uso di con
; Preferisco di gran lunga la Python con
istruzione . Sono d'accordo con te sul fatto che void
dovrebbe significare void
, comunque. Nell'esempio che fornisci, se una persona vuole davvero essere in grado di concatenare le invocazioni di metodi, dovrebbe semplicemente cambiare i tipi di ritorno sui propri metodi in modo che siano concatenabili.
Forse le molte molte chiamate a un oggetto sono il segnale che è necessario spostare un po 'di codice?
Joshua Bloch in Java efficace L'articolo # 2 raccomanda vivamente l'uso di un Costruttore quando hai un costruttore con molti argomenti. Uno dei motivi è che può essere scritto per garantire che l'oggetto costruito sia sempre in uno stato coerente. Evita inoltre di avere "costruttori telescopici" complessi " nella classe dell'oggetto costruito. Ancora un altro è che se si desidera che l'oggetto creato sia immutabile (ad esempio, per la sicurezza del thread), non può avere metodi setter.