Qual è la logica alla base dell'avere oggetti associati in Scala?


Risposte:


82

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, Fooe FooFactoryovunque, puoi fare in modo che una classe con un oggetto compagno si assuma le responsabilità della fabbrica.


61

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

1
illustrazione simile può essere trovata anche qui: daily-scala.blogspot.sk/2009/09/companion-object.html
xhudik

30

... 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

  1. senza "nuovo" (non proprio così importante)

  2. con diversi possibili set di parametri (confronta con quanto scrive Bloch in Java Effective sul costruttore telescopico)

  3. 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.


2
RealThinge la AlternativeThingclasse dovrebbe avere un privatecostruttore per forzare l'utente a usare la AbstractClassfabbrica has. class AlternativeThing private(i: Int) extends AbstractClass
metch

@ [Szymon Jachim] La classe astratta Scala non supporta l'ereditarietà multipla. Allora perché il compilatore lo consente nel tuo caso?
user2441441

19

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


3

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.


0

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


-1

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.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.