Qual è la logica alla base degli oggetti complementari in Scala?

C’è un caso in cui è necessario un object compagno (singleton) per una class? Perché dovrei voler creare una class, dire Foo e anche creare un object compagno per esso?

L’object compagno fornisce fondamentalmente un posto dove si possono mettere metodi “statici”. Inoltre, un object companion o un modulo companion ha accesso completo ai membri della class, inclusi quelli privati.

Gli oggetti Companion sono grandi per incapsulare cose come i metodi di fabbrica. Invece di dover avere, ad esempio, Foo e FooFactory ovunque, è ansible avere una class con un object compagno che assuma le responsabilità della fabbrica.

Gli oggetti Companion sono utili per l’archiviazione di stati e metodi comuni a tutte le istanze di una class, ma non utilizzano metodi o campi statici . Usano metodi virtuali regolari che possono essere sostituiti tramite ereditarietà. Scala non ha davvero nulla di statico. Ci sono molti modi in cui puoi usarlo, ma ecco un semplice esempio.

 abstract class AnimalCounter { var animals = 0 def name: String def count() { animals += 1 println("%d %ss created so far".format(animals, name)) } } abstract class Animal { def companion: AnimalCounter companion.count() } object Dog extends AnimalCounter { val name = "dog" } class Dog extends Animal { def companion = Dog } object Cat extends AnimalCounter { val name = "cat" } class Cat extends Animal { def companion = Cat } 

Che produce questo risultato:

 scala> new Dog 1 dogs created so far scala> new Cat 1 cats created so far scala> new Dog 2 dogs created so far scala> new Cat 2 cats created so far 

… ed è un buon posto per memorizzare i metodi statici di fabbrica (non quello DP) per le classi accompagnate. Se dai un nome a quei metodi industriali sovraccarichi, applica (/ /) sarai in grado di creare / inizializzare la tua class

  1. senza “nuovo” (non proprio così importante)

  2. con diversi possibili set di parametri (confrontare a quello che Bloch scrive in Effective Java sul costruttore di telescoping)

  3. con la capacità di decidere quale class derivata vuoi creare al posto di quella astratta (accompagnata)

Codice di esempio:

 abstract class AbstractClass; class RealThing(s: String) extends AbstractClass; class AlternativeThing(i: Int) extends AbstractClass; object AbstractClass { def apply(s: String) = { new RealThing(s) } def apply(i: Int) = { new AlternativeThing(i) } } // somewhere else you can val vs = AbstractClass("asdf") // gives you the RealThing wrapped over string val vi = AbstractClass(123) // gives you AlternativeThing wrapped over int 

Non chiamerei l’object / la class base AbstractXxxxx perché non sembra male: come creare qualcosa di astratto. Dare a quei nomi un vero significato. Prendi in considerazione l’utilizzo di classi di casi immutabili, meno metodiche e sigilla la class base astratta.

Oltre alle cose che Saem ha detto nella sua risposta , il compilatore Scala cerca anche conversioni implicite di tipi negli oggetti corrispondenti corrispondenti (della sorgente o della destinazione), quindi le conversioni non devono essere importate.

A proposito del motivo per gli oggetti singleton in generale Programming in Scala dice:

Come accennato nel Capitolo 1, un modo in cui Scala è più orientato agli oggetti di Java è che le classi in Scala non possono avere membri statici. Invece, Scala ha oggetti singleton (pagina 65).

Vedo sempre gli oggetti complementari come un ponte per scrivere codice funzionale e orientato agli oggetti in Scala. Molte volte abbiamo solo bisogno di funzioni pure che prendono un input e forniscono un risultato di elaborazione. Mettere quelle funzioni rilevanti nell’object compagno rende facile cercare e utilizzare, sia per me stesso che per qualcuno che costruisca il mio codice.

Inoltre, è una caratteristica fornita dal linguaggio per scrivere il modello singleton senza fare nulla. Ciò è particolarmente utile quando hai bisogno di un singleton per incapsulare un delegatore per la vita di JVM. Ad esempio, scrivendo una semplice libreria client HTTP in Scala in cui è ansible incapsulare un delegatore basato sull’implementazione Java sottostante e consentire agli utenti della propria API di vivere nel mondo puro.

Se si definiscono la class e l’object nello stesso file con lo stesso nome, sono noti come class e object companion. Scala non ha statica come parola chiave JAVA, puoi usare la sostituzione di statica con la class companion e l’object in Scala.

Per ulteriori informazioni dettagliate, consultare la class dell’articolo e la parola chiave object nella programmazione scala

Inizialmente, fornisce una chiara separazione tra metodi statici e metodi non statici. Fornisce anche un modo semplice per creare classi singleton.

Può anche ereditare metodi da altre classi e / o tratti, che non possono essere eseguiti con metodi statici Java e possono essere passati come parametro.