How to use 'Duck Typing' (Structural Types) in Scala

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 19.3, “How to use 'Duck Typing' (Structural Types) in Scala.”

Problem

You’re used to “Duck Typing” (structural types) from another language like Python or Ruby, and want to use this feature in your Scala code.

Solution

Scala’s version of “Duck Typing” is known as using a structural type. As an example of this approach, the following code shows how a callSpeak method can require that its obj type parameter have a speak() method:

def callSpeak[A <: { def speak(): Unit }](obj: A) {
    // code here ...
    obj.speak()
}

Given that definition, an instance of any class that has a speak() method that takes no parameters and returns nothing can be passed as a parameter to callSpeak. For example, the following code demonstrates how to invoke callSpeak on both a Dog and a Klingon:

class Dog { def speak() { println("woof") } }
class Klingon { def speak() { println("Qapla!") } }

object DuckTyping extends App {
    def callSpeak[A <: { def speak(): Unit }](obj: A) {
        obj.speak()
    }
    callSpeak(new Dog)
    callSpeak(new Klingon)
}

Running this code prints the following output:

woof
Qapla!

The class of the instance that’s passed in doesn’t matter at all. The only requirement for the parameter obj is that it’s an instance of a class that has a speak() method.

Discussion

The structural type syntax is necessary in this example because the callSpeak method invokes a speak method on the object that’s passed in. In a statically typed language, there must be some guarantee that the object that’s passed in will have this method, and this recipe shows the syntax for that situation.

Had the method been written as follows, it wouldn’t compile, because the compiler can’t guarantee that the type A has a speak method:

// won't compile
def callSpeak[A](obj: A) {
    obj.speak()
}

This is one of the great benefits of type safety in Scala.

It may help to break down the structural type syntax. First, here’s the entire method:

def callSpeak[A <: { def speak(): Unit }](obj: A) {
    obj.speak()
}

The type parameter A is defined as a structural type like this:

[A <: { def speak(): Unit }]

The <: symbol in the code is used to define something called an upper bound. This is described in detail in Recipe 19.5, “Make Immutable Collections Covariant”. As shown in that recipe, an upper bound is usually defined like this:

class Stack[A <: Animal] (val elem: A)

This states that the type parameter A must be a subtype of Animal.

However, in this recipe, a variation of that syntax is used to state that A must be a subtype of a type that has a speak method. Specifically, this code can be read as, “A must be a subtype of a type that has a speak method. The speak method (or function) can’t take any parameters and must not return anything.”

To demonstrate another example of the structural type signature, if you wanted to state that the speak method must take a String parameter and return a Boolean, the structural type signature would look like this:

[A <: { def speak(s: String): Boolean }]

As a word of warning, this technique uses reflection, so you may not want to use it when performance is a concern.

The Scala Cookbook

This tutorial is sponsored by the Scala Cookbook, which I wrote for O’Reilly:

You can find the Scala Cookbook at these locations:

Add new comment

The content of this field is kept private and will not be shown publicly.

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.