Existe-t-il un cas où un objet compagnon (singleton) pour une classe est nécessaire? Pourquoi voudrais-je créer une classe, dire Foo et créer un objet compagnon pour celle-ci?
Réponses
Trop de publicités?L'objet compagnon fournit fondamentalement un endroit où l'on peut mettre des méthodes «statiques». De plus, un objet compagnon, ou module compagnon, a un accès complet aux membres de la classe, y compris les membres privés.
Les objets associés sont parfaits pour encapsuler des éléments tels que les méthodes d'usine. Au lieu d'avoir Foo et FooFactory partout, vous pouvez avoir une classe avec un objet compagnon assumer les responsabilités de l'usine.
Les objets compagnon sont utiles pour stocker l'état et les méthodes communes à toutes les instances d'une classe, mais ils n'utilisent ni méthodes ni 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. Ceci peut être utilisé de nombreuses manières, 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 statique usine méthodes (pas que DP) pour accompagner les classes. Si vous le nom de ces surchargé usine méthodes s'appliquent(/.../), vous serez en mesure de créer/initialisation de vous classe
sans les "nouveaux" (pas vraiment important)
avec différents jeux de paramètres (comparer à ce que Bloch a écrit dans Efficace Java sur télescopique constructeur)
avec la capacité de décider dérivé de classe que vous souhaitez créer à la place de l'abstrait (accompagnés) un
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 ne dirais pas l'objet/classe de base AbstractXxxxx parce qu'il ne semble pas mauvais: comme la création de quelque chose d'abstrait. Donner ces noms un sens réel. Pensez à utiliser immuable, méthode moins, des classes de cas et de sceller la classe de base abstraite.
En plus des choses Saem a déclaré dans sa réponse, le compilateur Scala cherche aussi les conversions implicites de types dans le compagnon des objets (de la source ou la cible), de sorte que les conversions n'ont pas besoin d'être importés.
Sur la raison de singleton objets en général, la Programmation Scala dit:
Comme mentionné dans le Chapitre 1, une forme de Scala est plus orientées objet de Java est que les classes de Scala ne peut pas avoir des membres statiques. Au lieu de cela, Scala a objets singleton (p. 65).