2009-03-04 19 views
89

¿Hay algún caso en el que se necesite un objeto complementario (singleton) para una clase? ¿Por qué querría crear una clase, digamos Foo y también crear un objeto complementario para ella?¿Cuál es la razón de ser de objetos acompañantes en Scala?

+3

Vea también http://programmers.stackexchange.com/questions/179390/what-are-the-advantages-of-scalas-companion-objects-vs-static-methods – Vadzim

+0

Vea también http://stackoverflow.com/a/9806136/736957 que es una buena compilación de respuestas aquí – laughedelic

Respuesta

65

El objeto complementario proporciona básicamente un lugar donde se pueden poner métodos "estáticos". Además, un objeto complementario, o módulo complementario, tiene acceso completo a los miembros de la clase, incluidos los privados.

Los objetos acompañantes son ideales para encapsular cosas como los métodos de fábrica. En lugar de tener que tener, por ejemplo, Foo y FooFactory en todas partes, puede tener una clase con un objeto complementario que asuma las responsabilidades de la fábrica.

18

Además de las cosas que Saem dijo en his reply, el compilador de Scala también busca implicit conversions de tipos en los objetos complementarios correspondientes (de la fuente o el destino), por lo que no es necesario importar las conversiones.

Sobre la razón de objetos únicos en general Programming in Scala dice:

Como se mencionó en el Capítulo 1, una forma en que Scala es más de Java orientado a objetos es que las clases en Scala no pueden tener los miembros estáticos. En cambio, Scala tiene objetos singleton (p.65).

28

... y es un buen lugar para almacenar métodos estáticos de fábrica (no ese DP) para las clases acompañadas. Si nombra aplican los métodos de fábrica sobrecargados (/ ... /) usted será capaz de crear/inicializar la clase que

  1. sin 'nuevo' (no es tan importante)

  2. con diferentes conjuntos posibles de parámetros (en comparación con lo que Bloch escribe en Java eficaz sobre telescópico constructor)

  3. con la capacidad de decidir qué clase derivada que desea crear en lugar de lo abstracto (acompañado) uno

código Ejemplo:

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 

Yo no llamaría a la AbstractXxxxx clase de objeto/base, ya que no se ve mal: como crear algo abstracto. Dale a esos nombres un significado real. Considere usar clases de casos inmutables, de método menos y selle la clase base abstracta.

+2

La clase 'RealThing' y' AlternativeThing' debe tener un constructor 'privado' para obligar al usuario a utilizar el' AbstractClass' que tiene fábrica. 'clase AlternativeThing private (i: Int) extends AbstractClass' – metch

+1

metch, yeah. Tienes razón. –

54

Los objetos complementarios son útiles para almacenar el estado y los métodos que son comunes a todas las instancias de una clase pero no usan métodos estáticos o campos. Usan métodos virtuales regulares que pueden ser anulados a través de la herencia. Scala realmente no tiene nada estático. Hay muchas maneras de usar esto, pero aquí hay un ejemplo 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 
} 

que produce esta salida:

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

similar ilustración se puede encontrar también aquí: http://daily-scala.blogspot.sk/2009/09/companion-object.html – xhudik

3

Siempre veo compañero de objetos como un puente escribir tanto código funcional y orientado a objetos en Scala. Muchas veces solo necesitamos funciones puras que toman algunas entradas y proporcionan un resultado de procesamiento. Poner esas funciones relevantes en el objeto complementario facilita la búsqueda y el uso, tanto para mí como para alguien que se basa en mi código.

Además, es una característica proporcionada por el idioma para escribir el patrón singleton sin hacer nada. Esto es especialmente útil cuando necesita un singleton para encapsular un delegador durante toda la vida de JVM. Por ejemplo, escribir una biblioteca de cliente HTTP simple en Scala donde puede encapsular un delegador basado en la implementación subyacente de Java y permitir que los consumidores de su API vivan en un mundo puro.

0

Si define la clase y el objeto en el mismo archivo con el mismo nombre, se les conoce como clase acompañante y objeto. Scala no tiene estática como palabra clave JAVA, puede tomar como reemplazo de estática con clase acompañante y objeto en Scala.

Para obtener información más detallada consulte el artículo class and object keyword in scala programming

0

En un primer momento, que proporciona una clara separación de estática vs métodos no estáticos methods.Also proporcionar una forma sencilla de crear la clase Singleton.

También puede heredar métodos de otras clases y/o rasgos, lo que no se puede hacer con los métodos estáticos de Java. Y se puede pasar como un parámetro.

Cuestiones relacionadas