« Scala for C# programmers, part 1a: mixins and traits, behind the scenes | Main | Scala for C# programmers, part 3: pass by name »
January 08, 2009
Scala for C# programmers, part 2: singletons
In C#, if you want to create a singleton object, you have to create a class, then stop evildoers creating their own instances of that class, then create and provide an instance of that class yourself. While this is hardly a Burma Railway of the programming craft, it does feel like pushing against the grain of the language. Nor is it great for maintainers, who have to be able to recognise a singleton by its spoor ("Private constructor... public static readonly field... hand me the elephant gun, Carruthers."), or for clients, who have to use a slightly clumsy multipart syntax to refer to the singleton (e.g. Universe.Instance).
What would be easier for all concerned would be if you could just declare objects as singletons. That is, instead of writing class Universe and public static readonly Universe Instance, you could just write object Universe.
And that's exactly what Scala allows you to do:
object Universe {
def contains(obj: Any): Boolean = true // duh
}
val v = Universe.contains(42)
What's going on behind the scenes here? It pretty much goes without saying that the Scala compiler is creating a new type for the singleton object. In fact it creates two types, one for the implementation and one for the interface. The interface looks like a .NET static class (actually, the .NET 1.x equivalent, a sealed class with only static members). Thus, a C# program would call the example above as Universe.contains(42).
Singleton objects are first-class citizens in Scala, so they can for example derive from classes. This is a nice way of creating special values with custom behaviour: you don't need to create a whole new type, you just define an instance and override methods in it:
abstract class Cat {
def humiliateSelf()
}
object Slats extends Cat {
def humiliateSelf() { savage(this.tail) }
}
Obviously this is a frivolous example, but "special singletons" turn out to be an important part of the functional idiom, for example for bottoming out recursion. Scala by Example (PDF) describes an implementation of a Set class which is implemented as a tree-like structure ("left subset - member - right subset"), and methods such as contains() work by recursing down to the child sets. For this to work requires an EmptySet whose implementation (state) and behaviour are quite different from non-empty sets -- e.g. contains() just returns false instead of trying to delegate to non-existent child sets. Since EmptySet is logically unique it is both simpler and more efficient to represent it as a singleton: i.e. to declare object EmptySet instead of class EmptySet.
In fact the whole thing can become alarmingly deep: Scala by Example also includes a description of Boolean as an abstract class, and True and False as singleton objects which extend Boolean and provide appropriate implementations of the ifThenElse method. And fans of Giuseppe Peano should definitely check out the hypothetical implementation of Int...
January 8, 2009 in Software | Permalink
TrackBack
TrackBack URL for this entry:
https://www.typepad.com/services/trackback/6a00d8341c5c9b53ef010536b2e93a970b
Listed below are links to weblogs that reference Scala for C# programmers, part 2: singletons:
Comments
Doesn't:
static class MySingleton { ... }
work in C#?
Of course it's not a "first class citizen" so it suffers all the other limitations you mentioned.
Posted by: Mike at Feb 8, 2010 1:58:38 AM
Static classes work for some things, but aren't objects / instances, which limits their utility. For example, a static class can't implement an interface or be used polymorphically or passed around between functions. A simple example of where you might want a singleton but can't use a static class is the null object pattern: the null object needs to implement an interface or derive from a base class, and needs to be passable as an argument.
Posted by: Ivan at Feb 8, 2010 7:07:40 AM
So, what are the differences between Scala singletons and the sealed classed in C# that you reference?
Does
object Universe {
def contains(obj: Any): Boolean = true // duh
}
do something more than this?
using System;
sealed class Universe {
public static bool Contains(object obj) { return true; } // duh
}
class MainClass {
public static void Main (string[] args) {
if (Universe.Contains(42)) { Console.WriteLine ("It sure does!"); }
}
}
Am I completely misunderstanding the Scala code?
PS. Sorry about the formatting, this is the best I could do with whitespace getting stripped out.
Posted by: Justin at Jan 27, 2012 6:44:14 AM
The basic difference is that the Scala singleton is an actual object, and its members are instance members. This means it can do things like inherit from another class, implement traits/interfaces, etc. which a C# static class cannot do. (E.g. object Universe extends Container.)
Posted by: Ivan at Jan 27, 2012 7:16:29 AM