Last active
July 13, 2016 08:41
-
-
Save akirillov/178edb406e6a7368eebdf942f92d4ff3 to your computer and use it in GitHub Desktop.
Example of stackable traits in Scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Payload = Array[Byte] | |
trait Driver { | |
def send(payload: Payload) | |
} | |
//a component which depends on Driver interface | |
class Sender(val driver: Driver){ | |
def send(message: String) = driver.send(message.getBytes) | |
} | |
object Sender{ | |
def apply(driver: Driver): Sender = new Sender(driver) | |
} | |
//3rd-party implementation of the Driver | |
class NetworkDriver extends Driver{ | |
override def send(payload: Payload): Unit = { | |
println("..transferring..") | |
Thread.sleep(50) | |
} | |
} | |
//now developers decided to log the payload | |
trait PayloadLogging extends Driver { | |
abstract override def send(payload: Payload): Unit ={ | |
println(s"sending the payload: ${payload.mkString}") | |
super.send(payload) | |
} | |
} | |
//and measure the time spent in method | |
trait TimeLogging extends Driver { | |
abstract override def send(payload: Payload): Unit ={ | |
val start = System.currentTimeMillis() | |
super.send(payload) | |
print(s"time spent: ${System.currentTimeMillis() - start}ms") | |
} | |
} | |
//legacy implementation | |
Sender(new NetworkDriver).send("hello") | |
/*output: | |
..transferring.. | |
*/ | |
//mixing in payload logging | |
Sender(new NetworkDriver with PayloadLogging).send("hello") | |
/*output: | |
sending payload: 104101108108111 | |
..transferring.. | |
*/ | |
//mixing in payload and time logging | |
Sender(new NetworkDriver with PayloadLogging with TimeLogging).send("hello") | |
/*output: | |
sending payload: 104101108108111 | |
..transferring.. | |
time spent: 56ms | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Writer { | |
def write(msg: String) | |
} | |
class ConsoleWriter extends Writer { | |
override def write(msg: String): Unit = println(msg) | |
} | |
trait UppercaseFilter extends Writer { | |
abstract override def write(msg: String): Unit = { | |
super.write(msg.toUpperCase) | |
} | |
} | |
trait AdFilter extends Writer { | |
abstract override def write(msg: String): Unit = { | |
super.write(msg.replace("ad", "[ad blocked]")) | |
} | |
} | |
class Publisher(val writer: Writer){ | |
def publish(msg: String) = writer.write(msg) | |
} | |
object Publisher{ | |
def apply(writer: Writer): Publisher = new Publisher(writer) | |
} | |
Publisher(new ConsoleWriter).publish("my awesome ad") | |
/*output: | |
my awesome ad | |
*/ | |
Publisher(new ConsoleWriter with UppercaseFilter).publish("my awesome ad") | |
/*output: | |
MY AWESOME AD | |
*/ | |
Publisher(new ConsoleWriter with UppercaseFilter with AdFilter).publish("my awesome ad") | |
/*output: | |
MY AWESOME [AD BLOCKED] | |
*/ | |
Publisher(new ConsoleWriter with AdFilter with UppercaseFilter).publish("my awesome ad") | |
/*output: | |
MY AWESOME AD | |
ad replacement is case sensistive, so after UppercaseFilter is Applied | |
there's no 'ad' anymore | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment