Temporary exile

Fun With Case Classes in Scala

Recently, I have been messing around with the Scala programming language. In particular, I am seriously considering purchasing the Lift Book (buy it for me and I’ll cook you something) because the Lift framework itself is so neat.  Though I’d like to see a few small features added to the language, I am very impressed with Scala and look forward to using it more. In particular, Scala’s notion of pattern matching is a very powerful feature. One of the things that enables pattern matching to be used so widely is Scala’s case class feature. The concept of case classes could easily be underestimated in it’s usefulness and certainly overestimated in it’s complexity by someone new to pattern matching. In fact, case classes are, at the very least, an excellent way to compose objects to be used as record types and, when combined with pattern matching case classes provide some truly wonderful options for processing data. So what is a case class? Well, quite simply, defining a class as a case class lets Scala automatically give that class a number of useful helper methods. Among them are a toString() method and getters for each of the object’s properties which is why case classes make excellent record types. So, let’s have an example of an Animal class which inherits from an abstract class called Creatures.

abstract class Creature
case class Animal(name: String, food: String, legs: Int) extends Creature

What we’ve got here is just what it looks like, an abstract class called Creature and a one-line declaration of a case class called Animal with three fields. Why an abstract class? Well what if you want to add creatures later on? Flexibility is good. So the fields: name and food are both of type String while the field legs is of type Int. So far, this shouldn’t be too tough to understand as we’re just creating a class with a couple of instance variables. The cool part is that because it’s a case class, Scala automatically gives it a toString() method and getters for the properties. Let’s see how it works:

val panda = Animal("Panda", "Bamboo", 4)

You can see that the getter methods are there and working! Running this snippet should print out the following:


The last line is the printable representation returned by toString(). Also, notice that there are getters defined but not setters in accordance with the functional programming paradigm. Ok, great. So now we’ve seen that case classes give you neat stuff. What now? Let’s continue with another example.

val chicken = Animal("Chicken", "Grain", 2)
val cow = Animal("Cow", "Grass", 4)
val bison = Animal("Bison", "Grass", 4)

var herd = List(chicken, cow, bison)

In the above snippet, it’s clearly visible that we’ve got three tasty food animals and we’ve made a list of them called herd. So, now we want to sort through this herd in some interesting ways. Yes these are toy applications but we’re doing it to illustrate concepts here. Give me a list of every animal in the herd which is a quadruped.

herd.filter(a => a.legs == 4)

This returns a List[Animal] containing the bison and the cow. This illustrates how one can use a lambda with a getter to filter the list, but what about pattern matching? In this example, we use pattern matching to iterate through the herd and print what kind of animals are in it based on their legs.

for (a < - herd) a.legs match {
  case 4 => println("Quadruped")
  case 2 => println("Biped")
  case _ => println("Malformed animal")

Now, we see how we can build up a list detailing what kind of animals are in the herd based on legs and food type.

herd.map(a => a match {
  case Animal(p, "Grass", 4) => "Grazing quadruped"
  case Animal(p, f, 4) => "Non-grazing quadruped"
  case Animal(p, "Grass", n) => "Non-quadruped grazer"
  case _ => "Niether a quadruped nor a grazer"

This returns a List[String] which looks like this:

List(Niether a quadruped nor a grazer, Grazing quadruped, Grazing quadruped)

Cool, eh? Hopefully this helps to illustrate a few of the many neat things that can be done with case classes in Scala. In fact, unless there is a reason not to, I have been declaring all of my classes as case classes because of all the good stuff you get for free. Furthermore, it shouldn’t be hard to imagine how this could be used to process large numbers of records in only a few lines. Let’s say you had a bunch of records which corresponded to purchase orders. You could use pattern matching to collect those purchase orders which were not yet filled. Perhaps, from that list, you could use Scala’s native XML processing capabilities to generate a report document and then do interesting things from there.

Buy online ED pills USA Buy Cheapest online Cialis Buy Cheapest Cialis online Buy Cialis now 25 mg Viagra Buy Levitra doctor online Cheap mexico Cialis Cheap Cialis online uk