Explanation of singleton objects in Scala

2020-05-14 15:01发布

问题:

I get the coding in that you basically provide an "object SomeClass" and a "class SomeClass" and the companion class is the class declaration and the object is a singleton. Of which you cannot create an instance. So... my question is mostly the purpose of a singleton object in this particular instance.

Is this basically just a way to provide class methods in Scala? Like + based methods in Objective-C?

I'm reading the Programming in Scala book and Chapter 4 just talked about singleton objects, but it doesn't get into a lot of detail on why this matters.

I realize I may be getting ahead of myself here and that it might be explained in greater detail later. If so, let me know. This book is reasonably good so far, but it has a lot of "in Java, you do this", but I have so little Java experience that I sort of miss a bit of the points I fear. I don't want this to be one of those situations.

I don't recall reading anywhere on the Programming in Scala website that Java was a prerequisite for reading this book...

回答1:

Yes, companion singletons provide an equivalent to Java's (and C++'s, c#'s, etc.) static methods.

(indeed, companion object methods are exposed via "static forwarders" for the sake of Java interop)

However, singletons go a fair way beyond this.

  • A singleton can inherit methods from other classes/traits, which can't be done with statics.
  • A singleton can be passed as a parameter (perhaps via an inherited interface)
  • A singleton can exist within the scope of a surrounding class or method, just as Java can have inner classes
  • It's also worth noting that a singleton doesn't have to be a companion, it's perfectly valid to define a singleton without also defining a companion class.

Which helps make Scala a far more object-oriented language that Java (static methods don't belong to an object). Ironic, given that it's largely discussed in terms of its functional credentials.



回答2:

In many cases we need a singleton to stand for unique object in our software system. Think about the the solar system. We may have following classes

class Planet
object Earth extends Planet
object Sun extends Planet

object is a simple way to create singleton, of course it is usually used to create class level method, as static method in java



回答3:

Additional to the given answers (and going in the same general direction as jilen), objects play an important role in Scala's implicit mechanism, e.g. allowing type-class-like behavior (as known from Haskell):

trait Monoid[T] {
  def zero:T
  def sum(t1:T, t2:T):T
}

def fold[T](ts:T*)(implicit m:Monoid[T]) = ts.foldLeft(m.zero)(m.sum(_,_))

Now we have a fold-Function. which "collapses" a number of Ts together, as long as there is an appropriate Monoid (things that have a neutral element, and can be "added" somehow together) for T. In order to use this, we need only one instance of a Monoid for some type T, the perfect job for an object:

implicit object StringMonoid extends Monoid[String] {
  def zero = ""
  def sum(s1:String, s2:String) = s1 + s2
}

Now this works:

println(fold("a","bc","def"))  //--> abcdef

So objects are very useful in their own right.

But wait, there is more! Companion objects can also serve as a kind of "default configuration" when extending their companion class:

trait Config {
  def databaseName:String
  def userName:String
  def password:String
}

object Config extends Config {
  def databaseName = "testDB"
  def userName = "scott"
  def password = "tiger"
}

So on the one hand you have the trait Config, which can be implemented by the user however she wants, but on the other hand there is a ready made object Config when you want to go with the default settings.



回答4:

Yes, it is basically a way of providing class methods when used as a companion object.