Trait Basics

  • Traits and Java interfaces
  • Traits as Mixins - "orthogonal" functionality

Traits as interfaces

FILE : traits1.StarterTraits1Demo

As a standard Java 7 Interface

Scala:

trait StandardJava7Interface{
  def methodToImplement(arg:String):Unit
}

Java:

public interface jug.lodz.workshops.starter.traits1.StandardJava7Interface {
  public abstract void methodToImplement(java.lang.String);
}

As an interface with default method (Java8)

Scala implements this as a static method in interface (possible from java 8)

trait StandardJava8Interface{
  def methodToImplement(arg:String):Unit={
    println(s"hello $arg")
  }
}

Instead of default methods scala implements body in static methods - performacne reasons : http://www.scala-lang.org/blog/2016/07/08/trait-method-performance.html

public interface jug.lodz.workshops.starter.traits1.StandardJava8Interface {
  public static void methodToImplement$(jug.lodz.workshops.starter.traits1.StandardJava8Interface, java.lang.String);
  public void methodToimplement(java.lang.String);
  public static void $init$(jug.lodz.workshops.starter.traits1.StandardJava8Interface);
}

As an Interface with fields

Similarly to previous one - Scala implements this as a static method in interface (possible from java 8).

With possibility of adding fields we can now add fully independent orhogonal functionality like logging.

Scala:

trait Logger{
  def debug(message:String):Unit
  def info(message:String):Unit
}

class ConsoleLogger extends Logger{
  override def debug(message: String): Unit = println(s"[DEBUG] : $message")
  override def info(message: String): Unit = println(s"[INFO] : $message")
}

trait HasLogger{
    val logger= new ConsoleLogger
}

class SomeClass extends HasLogger

Decompiled:

Compiled from "StarterTraits1Demo.scala"
public class jug.lodz.workshops.starter.traits1.SomeClass implements jug.lodz.workshops.starter.traits1.HasLogger {
  public jug.lodz.workshops.starter.traits1.ConsoleLogger logger();
  public void jug$lodz$workshops$starter$traits1$HasLogger$_setter_$logger_$eq(jug.lodz.workshops.starter.traits1.ConsoleLogger);
  public jug.lodz.workshops.starter.traits1.SomeClass();
}

Self aware types

FILE: traits1.SelfAwareTypesDemo

Self aware types allow us to join two independent types family. In the example below we can create special DateLogger when know that trait will be mixed into Clock family

trait Clock{
  def currentDate:String
}

trait DateLogger extends BaseLogger { this:Clock =>
  override def debug(message: String): Unit = super.debug(message + " at "+ currentDate)
}

Exact clock implementation is hidden.

Exercise

FILE : jug.lodz.workshops.starter.traits1.exercises.StarterTraits1ExerciseSpec

1) Implement Event Store

Complete account trait so it stores events in First-In-Last-Out order.

2) Use self-aware type to add date to stored event

There is a second type hierarchy created -> Calendar . Mix it with event store to create DateStore trait which adds current date to events

results matching ""

    No results matching ""