2015-08-28 15 views
9

Molte classi nella libreria standard di Scala utilizzano apply() dell'oggetto associato come fabbrica. Ciò è spesso conveniente quando si concatenano chiamate come List(List(1)). D'altra parte, è ancora possibile creare oggetti direttamente con new (new HashMap[Int, Int]()).Quando utilizzare la fabbrica di oggetti companion rispetto alla nuova parola chiave

Questa è una libreria standard. Ora, nel mio codice, quale approccio è meglio usare: fabbrica di complementi o creazione di oggetti con new?

Esistono convenzioni su quando creare una fabbrica di oggetti companion e quando utilizzare la parola chiave new?

Quali sono i vantaggi dell'utilizzo degli uni sugli altri?

+4

Perché usare "nuovo" è come indossare un cappello a cilindro o bretelle. È elegante per un certo stile, ma non molto contemporaneo. La fabbrica del compagno è un paio di jeans casual. –

risposta

3

Nella maggior parte dei casi utilizzo il metodo apply dell'oggetto companion, perché il codice sembra meno ingombrante. Tuttavia, vi è almeno un vantaggio dell'utilizzo di una fabbrica statica. Si consideri il tipo privo di fantasia MyInt che avvolge solo un Int:

class MyInt(val i: Int) 

posso ottenere istanze di MyInt chiamando il costruttore che un'istanza di un nuovo oggetto ogni volta che il costruttore viene chiamato. Se il mio programma si basa pesantemente su MyInt ciò comporta molte istanze create. Supponendo che la maggior parte del MyInt che uso sono -1, 0, e 1, dal momento che MyInt è immutabile posso riutilizzare le stesse istanze:

class MyInt(val i: Int) 

object MyInt { 
    val one = new MyInt(1) 
    val zero = new MyInt(0) 
    val minusOne = new MyInt(-1) 

    def apply(i: Int) = i match { 
    case -1 => minusOne 
    case 0 => zero 
    case 1 => one 
    case _ => new MyInt(i) 
    } 
} 

Quindi, almeno per valori immutabili non ci può essere un vantaggio tecnico di utilizzare la fabbrica statica chiamando il costruttore. Come implicazione, se si desidera esprimere in codice che viene creata una nuova istanza, utilizzare la parola chiave new. Personalmente, utilizzo la parola chiave new durante la creazione di oggetti e il metodo apply durante la creazione di valori, anche se non so se esiste una convenzione ufficiale.

+1

Mi piace l'idea con il caching del valore. La lezione appresa è che puoi facilmente cambiare l'implementazione di apply() per fare quello che vuoi ma quando usi 'new', devi sempre finire con una nuova istanza. – Mifeet

3

Non so che ci sia una raccomandazione generale di un approccio rispetto all'altro, di solito è solo una comodità non dover digitare new.

Ci sono occasioni, tuttavia, dove l'opzione del metodo di fabbrica può essere migliore. Ad esempio, se la classe ha un campo di stringa che deve essere maiuscolo, è possibile rendere il privato costruttore di serie, costringendo di istanze tramite il metodo factory che assicura il campo è sempre maiuscolo:

class A private[A] (s: String) 

object A { 
    def apply(s: String): A = new A(s.toUpperCase) 
} 

Nota: se la classe è una classe di casi, ci sono un paio di altre modifiche per far funzionare tutto questo - vedi here.

+1

Come dettaglio impl, 'private [A]' risulta in un ctor pubblico. Più consueto solo per 'privato' dal momento che significa lo stesso per Scala ma ha un ctor privato per Java. –

+0

Non ho molta esperienza con Scala, ma non è fastidioso dover scrivere il compagno extra per ogni oggetto? – Mifeet

+0

@Mifeet Le classi Case forniscono gratuitamente un oggetto companion (di solito) adatto, quindi in genere non è affatto un problema. – Shadowlands

Problemi correlati