Tour of Scala

Traits

Language

Traits are used to share interfaces and fields between classes. They are similar to Java 8’s interfaces. Classes and objects can extend traits, but traits cannot be instantiated and therefore have no parameters.

Defining a trait

A minimal trait is simply the keyword trait and an identifier:

traitHairColor

Traits become especially useful as generic types and with abstract methods.

traitIterator[A]{defhasNext:Booleandefnext():A}
traitIterator[A]:defhasNext:Booleandefnext():A

Extending the trait Iterator[A] requires a type A and implementations of the methods hasNext and next.

Using traits

Use the extends keyword to extend a trait. Then implement any abstract members of the trait using the override keyword:

traitIterator[A]{defhasNext:Booleandefnext():A}classIntIterator(to:Int)extendsIterator[Int]{privatevarcurrent=0overridedefhasNext:Boolean=current<tooverridedefnext():Int={if(hasNext){valt=currentcurrent+=1t}else0}}valiterator=newIntIterator(10)iterator.next()// returns 0iterator.next()// returns 1
traitIterator[A]:defhasNext:Booleandefnext():AclassIntIterator(to:Int)extendsIterator[Int]:privatevarcurrent=0overridedefhasNext:Boolean=current<tooverridedefnext():Int=ifhasNextthenvalt=currentcurrent+=1telse0endIntIteratorvaliterator=IntIterator(10)iterator.next()// returns 0iterator.next()// returns 1

This IntIterator class takes a parameter to as an upper bound. It extends Iterator[Int] which means that the next method must return an Int.

Subtyping

Where a given trait is required, a subtype of the trait can be used instead.

importscala.collection.mutable.ArrayBuffertraitPet{valname:String}classCat(valname:String)extendsPetclassDog(valname:String)extendsPetvaldog=newDog("Harry")valcat=newCat("Sally")valanimals=ArrayBuffer.empty[Pet]animals.append(dog)animals.append(cat)animals.foreach(pet=>println(pet.name))// Prints Harry Sally
importscala.collection.mutable.ArrayBuffertraitPet:valname:StringclassCat(valname:String)extendsPetclassDog(valname:String)extendsPetvaldog=Dog("Harry")valcat=Cat("Sally")valanimals=ArrayBuffer.empty[Pet]animals.append(dog)animals.append(cat)animals.foreach(pet=>println(pet.name))// Prints Harry Sally

The trait Pet has an abstract field name that gets implemented by Cat and Dog in their constructors. On the last line, we call pet.name, which must be implemented in any subtype of the trait Pet.

More resources

Contributors to this page:

close