Table of Contents
- Using a Scala trait like a Java interface
- Extending Scala traits
- Abstract and concrete fields in traits
- Using a Scala trait like a Java abstract class
- Using traits as simple mixins
- Limiting which classes can use a trait
- Adding a trait to an object instance
- Extending Java interfaces like Scala traits
- Summary
This page contains a collection of Scala trait examples. I created many of these examples when I was writing the Scala Cookbook. Unlike the Cookbook — where I explain these examples in great detail — on this page I’m just sharing many of the examples so you can use this as a Scala trait reference page. (The Cookbook actually contains more examples than this page.)
Without any more introduction, here are the examples.
Using a Scala trait like a Java interface
A trait can be used just like a Java interface. As with interfaces, just define the methods in your trait that you want extending classes to implement:
trait BaseSoundPlayer {
def play
def close
def pause
def stop
def resume
}
Extending Scala traits
If a class implements one trait it will use the extends keyword:
class Mp3SoundPlayer extends BaseSoundPlayer {
def play {}
def close {}
def pause {}
def stop {}
def resume {}
}
One trait can extend another trait:
trait Mp3BaseSoundFilePlayer extends BaseSoundFilePlayer {
def getBasicPlayer:BasicPlayer
def getBasicController:BasicController
def setGain(volume: Double)
}
If a class extends a trait but does not implement the methods defined in that trait, it must be declared abstract:
// must be declared abstract because it does not implement BaseSoundPlayer methods
abstract class JavaSoundPlayer extends BaseSoundPlayer {
def play {}
def close {}
}
If a class implements multiple traits, it will extend the first trait (or a class, or abstract class), and then use with for other traits:
abstract class Animal {
def speak
}
trait WaggingTail {
def startTail
def stopTail
}
trait FourLeggedAnimal {
def walk
def run
}
class Dog extends Animal with WaggingTail with FourLeggedAnimal {
// implementation code here ...
}
Abstract and concrete fields in traits
In a trait, define a field with an initial value to make it concrete, otherwise give it no initial value to make it abstract:
trait PizzaTrait {
var numToppings: Int // abstract
val maxNumToppings = 10 // concrete
}
In the class that extends the trait, you’ll need to define the values for the abstract fields, or make the class abstract. The Pizza class demonstrates how to override the numToppings field:
class Pizza extends PizzaTrait {
var numToppings = 0 // override not needed
}
trait PizzaTrait {
var numToppings: Int // abstract
val maxNumToppings = 10 // concrete
}
Using a Scala trait like a Java abstract class
You can use Scala traits like abstract classes in Java. In the following example, an implementation is provided for the speak method in the Pet trait, so implementing classes don’t have to override it. The Dog class chooses not to override it, while the Cat class does:
trait Pet {
def speak { println("Yo") } // concrete implementation of a speak method
def comeToMaster // abstract
}
class Dog extends Pet {
// don't need to implement 'speak' if you don't want to
def comeToMaster { ("I'm coming!") }
}
class Cat extends Pet {
// override 'speak'
override def speak { ("meow") }
def comeToMaster { ("That's not gonna happen.") }
}
If a class extends a trait without implementing its abstract methods, it must be defined abstract. Because FlyingPet does not implement comeToMaster, it is defined abstract:
abstract class FlyingPet extends Pet {
def fly { ("I'm flying!") }
}
Using traits as simple mixins
To implement a simple mixin, define the methods you want in your trait, then add the trait to your class using extends or with. In the following example we define a Tail trait:
trait Tail {
def wagTail { println("tail is wagging") }
}
This trait can be used with an abstract Pet class to create a Dog:
abstract class Pet (var name: String) {
def speak // abstract
def ownerIsHome { println("excited") }
}
class Dog (name: String) extends Pet (name) with Tail {
def speak { println("woof") }
}
A Dog can now use the methods defined by both the abstract Pet class, as well as the Tail trait:
object Test extends App {
val zeus = new Dog("Zeus")
zeus.ownerIsHome
zeus.wagTail
zeus.speak
}
Limiting which classes can use a trait
You can limit a trait so it can only be added to classes which extend a specific subclass. To do this, use the “trait [TraitName] extends [SubclassName]” syntax. For instance, in the following example the Starship and WarpCore both extend the common superclass StarfleetComponent, so the WarpCore trait can be mixed into the Starship class:
class StarfleetComponent trait WarpCore extends StarfleetComponent class Starship extends StarfleetComponent with WarpCore
However, in the following example, the Warbird can’t extend the WarpCore trait because Warbird and WarpCore don’t share the same superclass:
class StarfleetComponent trait WarpCore extends StarfleetComponent class RomulanStuff class Warbird extends RomulanStuff with WarpCore // won't compile
A trait inheriting a class is not a common occurrence, and in general the following approach is preferred.
You can mark your traits so they can only be used by subclasses of a certain type. To do this, begin your trait with the “this: LimitingType =>” statement, as shown here:
trait MyTrait {
this: LimitingType =>
// more code here ...
For instance, to make sure a WarpCore can only be used in a Starship, mark the WarpCore trait like this:
trait WarpCore {
this: Starship =>
}
Now this code will work:
class Starship class Enterprise extends Starship with WarpCore
But other attempts like this will fail:
class RomulanShip class Warbird extends RomulanShip with WarpCore // this won't compile
Adding a trait to an object instance
This next example shows that you can add a trait to an instance of a class (an object):
class DavidBanner
trait Angry {
println("You won't like me ...")
}
object Test extends App {
val hulk = new DavidBanner with Angry
}
Extending Java interfaces like Scala traits
You can extend Java interfaces like Scala traits. In your Scala application, just use the extends and with keywords to implement your Java interfaces:
// java
public interface Animal {
public void speak();
}
public interface Wagging {
public void wag();
}
public interface Running {
public void run();
}
// scala
class Dog extends Animal with Wagging with Running {
def speak { println("Woof") }
def wag { println("Tail is wagging!") }
def run { println("I'm running!") }
}
| this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
Summary
I hope these Scala trait examples have been helpful. I’ll try to keep adding more to these examples as time goes on.