Y a-t-il un cas où un objet compagnon (singleton) pour une classe est nécessaire? Pourquoi voudrais-je créer une classe, par exemple, Foo
et créer également un objet compagnon pour elle?
Y a-t-il un cas où un objet compagnon (singleton) pour une classe est nécessaire? Pourquoi voudrais-je créer une classe, par exemple, Foo
et créer également un objet compagnon pour elle?
Réponses:
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, Foo
et FooFactory
partout, vous pouvez demander à une classe avec un objet compagnon d'assumer les responsabilités d'usine.
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
... 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
sans 'nouveau' (pas vraiment important)
avec différents ensembles de paramètres possibles (comparez à ce que Bloch écrit dans Effective Java à propos du constructeur télescopique)
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.
RealThing
et la AlternativeThing
classe doit avoir un private
constructeur pour forcer l'utilisateur à utiliser la AbstractClass
fabrique has. class AlternativeThing private(i: Int) extends AbstractClass
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).
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.
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
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.