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.