8.7. Ensuring a Trait Can Only Be Added to a Type That Has a Specific Method

Problem

You only want to allow a trait to be mixed into a type (class, abstract class, or trait) that has a method with a given signature.

Solution

Use a variation of the self-type syntax that lets you declare that any class that attempts to mix in the trait must implement the method you specify.

In the following example, the WarpCore trait requires that any classes that attempt to mix it in must have an ejectWarpCore method:

trait WarpCore {
  this: { def ejectWarpCore(password: String): Boolean } =>
}

It further states that the ejectWarpCore method must accept a String argument and return a Boolean value.

The following definition of the Enterprise class meets these requirements, and will therefore compile:

class Starship {
  // code here ...
}

class Enterprise extends Starship with WarpCore {
  def ejectWarpCore(password: String): Boolean = {
    if (password == "password") {
      println("ejecting core")
      true
    } else {
      false
    }
  }
}

A trait can also require that a class have multiple methods. To require more than one method, just add the additional method signatures inside the block:

trait WarpCore {
  this: {
    def ejectWarpCore(password: String): Boolean
    def startWarpCore: Unit
  } =>
}

class Starship

class Enterprise extends Starship with WarpCore {
  def ejectWarpCore(password: String): Boolean = {
    if (password == "password") { println("core ejected"); true } else false
  }
  def startWarpCore { println("core started") }
}

Discussion

This ...

Get Scala Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.