parameter - scala implicit
Scala Objects y el aumento de singletons (3)
Pregunta de estilo general.
A medida que mejoro escribiendo código funcional, más de mis métodos se convierten en funciones puras. Encuentro que muchas de mis "clases" (en el sentido amplio de un contenedor de código) se están liberando del estado. Por lo tanto, los convierto en objetos en lugar de clases, ya que no hay necesidad de crear instancias.
Ahora, en el mundo de Java, tener una clase llena de métodos "estáticos" parece bastante extraño, y generalmente solo se usa para clases de "ayuda", como se ve con Guava y Commons- *, y así sucesivamente.
Entonces mi pregunta es, en el mundo de Scala, tener mucha lógica dentro de "objetos" y no "clases" es bastante normal, o hay otro modismo preferido.
También puede usar objetos del paquete, por ejemplo, eche un vistazo al objeto del paquete scala.math aquí https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/math/package .cala
Sí, yo diría que es normal.
Para la mayoría de mis clases, creo un objeto complementario para manejar allí una lógica de inicialización / validación. Por ejemplo, en lugar de arrojar una excepción si la validación de los parámetros falla en un constructor, es posible devolver una Option
o un Either
en el método de aplicación de los objetos complementarios:
class X(val x: Int) {
require(x >= 0)
}
// ==>
object X {
def apply(x: Int): Option[X] =
if (x < 0) None else Some(new X(x))
}
class X private (val x: Int)
En el objeto complementario, se puede agregar mucha lógica adicional, como un caché para objetos inmutables.
los objetos también son buenos para enviar señales entre instancias si no es necesario enviar mensajes también:
object X {
def doSomething(s: String) = ???
}
case class C(s: String)
class A extends Actor {
var calculateLater: String = ""
def receive = {
case X => X.doSomething(s)
case C(s) => calculateLater = s
}
}
Otro caso de uso para objetos es reducir el alcance de los elementos:
// traits with lots of members
trait A
trait B
trait C
trait Trait {
def validate(s: String) = {
import validator._
// use logic of validator
}
private object validator extends A with B with C {
// all members of A, B and C are visible here
}
}
class Class extends Trait {
// no unnecessary members and name conflicts here
}
Como mencionas en tu título, los objetos son clases simples, no clases con métodos estáticos como mencionas en el texto de tu pregunta.
Y hay algunas cosas que hacen que los objetos scala sean mejores que los estáticos AND singletons en java-world, por lo que es bastante "normal" usarlos en scala.
Por un lado, a diferencia de los métodos estáticos, los métodos de objetos son polimórficos, por lo que puede inyectar objetos fácilmente como dependencias:
scala> trait Quack {def quack="quack"}
defined trait Quack
scala> class Duck extends Quack
defined class Duck
scala> object Quacker extends Quack {override def quack="QUAACK"}
defined module Quacker
// MakeItQuack expects something implementing Quack
scala> def MakeItQuack(q: Quack) = q.quack
MakeItQuack: (q: Quack)java.lang.String
// ...it can be a class
scala> MakeItQuack(new Duck)
res0: java.lang.String = quack
// ...or it can be an object
scala> MakeItQuack(Quacker)
res1: java.lang.String = QUAACK
Esto los hace utilizables sin acoplamiento estrecho y sin promover el estado global (que son dos de los problemas generalmente atribuidos tanto a métodos estáticos como a singleton).
Luego está el hecho de que eliminan todo el repetitivo que hace que los singleton sean tan feos y de aspecto unidiomático en java. Este es un punto que a menudo se pasa por alto, en mi opinión, y parte de lo que hace que los singleton sean tan mal vistos en Java incluso cuando son apátridas y no se usan como estado global.
Además, el texto repetitivo que debe repetir en todos los singleton de Java otorga a la clase dos responsabilidades: garantizar que solo haya una instancia de sí mismo y hacer lo que se supone que debe hacer. El hecho de que scala tenga una forma declarativa de especificar que algo es un singleton alivia a la clase y al programador de romper el principio de responsabilidad única. En scala, usted sabe que un objeto es un singleton y puede razonar sobre lo que hace.