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 ++ " ...)

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top