Quelle est la raison d'avoir des objets compagnons dans Scala?

Réponses:

82

L'objet compagnon fournit essentiellement un endroit où l'on peut mettre des méthodes «statiques». En outre, un objet compagnon, ou module compagnon, a un accès complet aux membres de la classe, y compris les membres privés.

Les objets compagnons sont parfaits pour encapsuler des éléments tels que les méthodes d'usine. Au lieu d'avoir à avoir, par exemple, Fooet FooFactorypartout, vous pouvez demander à une classe avec un objet compagnon d'assumer les responsabilités d'usine.

Saem
la source
61

Les objets compagnons sont utiles pour stocker des états et des méthodes communs à toutes les instances d'une classe, mais ils n'utilisent pas de méthodes ou de champs statiques . Ils utilisent des méthodes virtuelles régulières qui peuvent être remplacées par héritage. Scala n'a vraiment rien de statique. Il existe de nombreuses façons de l'utiliser, mais voici un exemple simple.

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
}

Qui produit cette sortie:

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
Craig P. Motlin
la source
1
une illustration similaire peut être trouvée également ici: daily-scala.blogspot.sk/2009/09/companion-object.html
xhudik
30

... et c'est un bon endroit pour stocker des méthodes d'usine statiques (pas que DP) pour les classes accompagnées. Si vous nommez ces méthodes d'usine surchargées apply (/ ... /), vous pourrez créer / initialiser votre classe

  1. sans 'nouveau' (pas vraiment important)

  2. avec différents ensembles de paramètres possibles (comparez à ce que Bloch écrit dans Effective Java à propos du constructeur télescopique)

  3. avec la possibilité de décider quelle classe dérivée vous souhaitez créer au lieu de la classe abstraite (accompagnée)

Exemple de code:

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

Je n'appellerais pas l'objet / la classe de base AbstractXxxxx parce que cela n'a pas l'air mauvais: comme créer quelque chose d'abstrait. Donnez à ces noms une vraie signification. Envisagez d'utiliser des classes de cas immuables, sans méthode, et scellez la classe de base abstraite.

Szymon Jachim
la source
2
RealThinget la AlternativeThingclasse doit avoir un privateconstructeur pour forcer l'utilisateur à utiliser la AbstractClassfabrique has. class AlternativeThing private(i: Int) extends AbstractClass
metch
@ [Szymon Jachim] La classe abstraite Scala ne prend pas en charge l'héritage multiple. Alors, pourquoi le compilateur le permet-il dans votre cas?
user2441441
19

En plus de ce que Saem a dit dans sa réponse , le compilateur Scala recherche également des conversions implicites de types dans les objets compagnons correspondants (de la source ou de la cible), donc les conversions n'ont pas besoin d'être importées.

À propos de la raison des objets singleton dans la programmation générale dans Scala dit:

Comme mentionné dans le chapitre 1, une des façons dont Scala est plus orientée objet que Java est que les classes de Scala ne peuvent pas avoir de membres statiques. Au lieu de cela, Scala a des objets singleton (p. 65).

Fabian Steeg
la source
3

Je vois toujours les objets compagnons comme un pont pour écrire du code fonctionnel et orienté objet dans Scala. Plusieurs fois, nous avons juste besoin de fonctions pures qui prennent des entrées et fournissent un résultat de traitement. Mettre ces fonctions pertinentes dans l'objet compagnon facilite la recherche et l'utilisation, pour moi-même ainsi que pour quelqu'un qui construit au-dessus de mon code.

De plus, c'est une fonctionnalité fournie par le langage pour écrire le motif singleton sans rien faire. Ceci est particulièrement utile lorsque vous avez besoin d'un singleton pour encapsuler un délégant pour la durée de vie de JVM. Par exemple, écrire une bibliothèque client HTTP simple dans Scala où vous pouvez encapsuler un délégateur basé sur l'implémentation Java sous-jacent et laisser les consommateurs de votre API vivre dans un monde pur.

Gaurav Abbi
la source
0

Si vous définissez une classe et un objet dans le même fichier avec le même nom, ils sont appelés classe et objet compagnon. Scala n'a pas de mot-clé statique comme JAVA, vous pouvez remplacer le statique par une classe et un objet compagnon dans Scala.

Pour plus d'informations, veuillez consulter la classe d' article et le mot-clé d'objet dans la programmation scala

FOD
la source
-1

Au début, il fournit une séparation claire entre les méthodes statiques et non statiques, ainsi qu'un moyen simple de créer une classe singleton.

Il peut également hériter des méthodes d'autres classes et / ou traits, ce qui ne peut pas être fait avec les méthodes statiques Java et peut être passé en paramètre.

vipin
la source