C'è un caso in cui è necessario un oggetto associato (singleton) per una classe? Perché dovrei creare una classe, ad esempio, Foo
e creare anche un oggetto associato?
C'è un caso in cui è necessario un oggetto associato (singleton) per una classe? Perché dovrei creare una classe, ad esempio, Foo
e creare anche un oggetto associato?
Risposte:
L'oggetto compagno fondamentalmente fornisce un posto dove si possono mettere metodi "statici". Inoltre, un oggetto companion, o modulo companion, ha pieno accesso ai membri della classe, compresi quelli privati.
Gli oggetti companion sono ottimi per incapsulare cose come i metodi di fabbrica. Invece di dover avere, ad esempio, Foo
e FooFactory
ovunque, puoi fare in modo che una classe con un oggetto compagno si assuma le responsabilità della fabbrica.
Gli oggetti companion sono utili per memorizzare stati e metodi comuni a tutte le istanze di una classe ma non utilizzano metodi o campi statici . Usano metodi virtuali regolari che possono essere sovrascritti tramite ereditarietà. Scala non ha davvero nulla di statico. Ci sono molti modi per 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 output:
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 metodi di fabbrica statici (non quello DP) per le classi accompagnate. Se assegni a questi metodi di fabbrica sovraccaricati il nome (/ ... /) sarai in grado di creare / inizializzare la tua classe
senza "nuovo" (non proprio così importante)
con diversi possibili set di parametri (confronta con quanto scrive Bloch in Java Effective sul costruttore telescopico)
con la possibilità di decidere quale classe derivata si vuole creare invece 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'oggetto / classe base AbstractXxxxx perché non sembra male: come creare qualcosa di astratto. Dai a quei nomi un significato reale. Prendi in considerazione l'utilizzo di classi case immutabili, prive di metodi, e sigilla la classe base astratta.
RealThing
e la AlternativeThing
classe dovrebbe avere un private
costruttore per forzare l'utente a usare la AbstractClass
fabbrica has. class AlternativeThing private(i: Int) extends AbstractClass
Oltre a quanto detto da Saem nella sua risposta , il compilatore Scala cerca anche conversioni implicite di tipi nei corrispondenti oggetti associati (dell'origine o della destinazione), quindi le conversioni non devono essere importate.
Sul motivo degli oggetti singleton in generale La programmazione 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. Scala ha invece oggetti singleton (p. 65).
Vedo sempre gli oggetti companion come un ponte per scrivere codice sia funzionale che orientato agli oggetti in Scala. Molte volte abbiamo solo bisogno di funzioni pure che richiedono un input e forniscono un risultato di elaborazione. Mettere queste funzioni rilevanti nell'oggetto companion rende facile cercare e usare, per me e per qualcuno che sta costruendo sopra il mio codice.
Inoltre, è una funzionalità fornita dal linguaggio per scrivere il pattern singleton senza fare nulla. Ciò è particolarmente utile quando è necessario un singleton per incapsulare un delegante per la vita di JVM. Ad esempio, scrivere una semplice libreria client HTTP in Scala in cui è possibile incapsulare un delegatore basato sull'implementazione Java sottostante e consentire ai consumatori della tua API di vivere in un mondo puro.
Se definisci classe e oggetto nello stesso file con lo stesso nome, sono noti come classe e oggetto companion. Scala non ha static come parola chiave JAVA, puoi prendere in sostituzione di static con la classe e l'oggetto companion in Scala.
Per informazioni più dettagliate, controllare la classe articolo e la parola chiave oggetto nella programmazione scala
In un primo momento, fornisce una chiara separazione dei metodi statici e non statici e fornisce anche un modo semplice per creare classi singleton.
Può anche ereditare metodi da altre classi e / o tratti, cosa che non può essere eseguita con metodi statici Java e può essere passato come parametro.