¿Cuál es la razón de ser de tener objetos complementarios en Scala?


107

¿Existe algún caso en el que se necesite un objeto complementario (singleton) para una clase? ¿Por qué querría crear una clase, digamos Fooy también crear un objeto complementario para ella?



Consulte también stackoverflow.com/a/9806136/736957, que es una buena compilación de respuestas aquí
laughedelic

Respuestas:


82

El objeto compañero básicamente proporciona un lugar donde se pueden colocar métodos "similares a 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 complementarios son excelentes para encapsular cosas como métodos de fábrica. En lugar de tener que tener, por ejemplo, Fooy en FooFactorytodas partes, puede hacer que una clase con un objeto compañero asuma las responsabilidades de la fábrica.


61

Los objetos complementarios son útiles para almacenar estados y métodos que son comunes a todas las instancias de una clase, pero no utilizan métodos o campos estáticos . Utilizan métodos virtuales regulares que pueden anularse mediante herencia. Scala realmente no tiene nada estático. Hay muchas formas 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
También se puede encontrar una ilustración similar aquí: daily-scala.blogspot.sk/2009/09/companion-object.html
xhudik

30

... y es un buen lugar para almacenar métodos de fábrica estáticos (no ese DP) para clases acompañadas. Si nombra esos métodos de fábrica sobrecargados que se aplican (/ ... /), podrá crear / inicializar su clase

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

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

  3. con la capacidad de decidir qué clase derivada desea crear en lugar de la abstracta (acompañada)

Código de 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

No llamaría AbstractXxxxx al objeto / clase base porque no se ve mal: como crear algo abstracto. Dale a esos nombres un significado real. Considere usar clases de caso inmutables, sin método, y selle la clase base abstracta.


2
RealThingy la AlternativeThingclase debe tener un privateconstructor para obligar al usuario a usar la AbstractClassfábrica has. class AlternativeThing private(i: Int) extends AbstractClass
metch

@ [Szymon Jachim] La clase abstracta Scala no admite herencia múltiple. Entonces, ¿por qué el compilador lo permite en su caso?
user2441441

19

Además de las cosas que dijo Saem en su respuesta , el compilador de Scala también busca conversiones implícitas de tipos en los objetos complementarios correspondientes (de origen o de destino), por lo que no es necesario importar las conversiones.

Sobre la razón de los objetos singleton en la programación general en Scala dice:

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


3

Siempre veo los objetos complementarios como un puente para escribir código funcional y orientado a objetos en Scala. Muchas veces solo necesitamos funciones puras que toman alguna entrada y brindan 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 lenguaje para escribir el patrón singleton sin hacer nada. Esto es especialmente útil cuando necesita un singleton para encapsular un delegador durante 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 de Java subyacente y dejar 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 conocen como clase y objeto complementarios. Scala no tiene static como palabra clave JAVA, puede tomar como reemplazo de static con clase complementaria y objeto en Scala.

Para obtener más información detallada, consulte la clase del artículo y la palabra clave del objeto en la programación de Scala.


-1

Al principio, proporciona una clara separación de los métodos de métodos estáticos y no estáticos. También proporciona una forma sencilla de crear clases singleton.

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.