SlideShare a Scribd company logo
1 of 96
Download to read offline
Baking

Delicious

Modularization

cala
in S

Derek Wyatt
Twitter: @derekwyatt
Email: derek@derekwyatt.org

Thursday, December 12, 13
odularity
Oriented M
Object
OOD gives us...

Thursday, December 12, 13
odularity
Oriented M
Object
OOD gives us...

Thursday, December 12, 13

private
Inheritance
Clanc erfaces
I sist s&ro ses
ubl e p tlas
p
Cected
Composition
act
str
Ab
odularity
Oriented M
Object
OOD gives us...

C++ gave us...

Thursday, December 12, 13

private
Inheritance
Clanc erfaces
I sist s&ro ses
ubl e p tlas
p
Cected
Composition
act
str
Ab

ht?
R ig
...
l

Ev i
Multiple Inheritance
lain
st P
Ju
d Problem
he Diamon
T
is
Thursday, December 12, 13

A

B

is

A

A

C
d Problem
he Diamon
T
A

is

is

A

A

C

A

is

Thursday, December 12, 13

D

is
A

B
d Problem
he Diamon
T
A
A

is

is

A

?

B

A

is

Thursday, December 12, 13

D

C
is
A

Who initializes A?
d Problem
he Diamon
T
A
is

A

D

C
is
A

A

Thursday, December 12, 13

?

B
is

They can’t both do it!

is

l d
s it initiaoizeoes C
B need
S d

A

Who initializes A?
d Problem
he Diamon
T
A
is

A

Thursday, December 12, 13

D

C
is
A

A

Enter: Virtual Inheritance

?

B
is

They can’t both do it!

is

l d
s it initiaoizeoes C
B need
S d

A

Who initializes A?
d Problem
he Diamon
T
A
is

A

?
A

D

C
is
A

B
is

They can’t both do it!

is

l d
s it initiaoizeoes C
B need
S d

A

Who initializes A?

Enter: Virtual Inheritance
Convincing the world for decades that
Multiple Inheritance is BAD
Thursday, December 12, 13
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance

Thursday, December 12, 13
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out

Thursday, December 12, 13
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out
Implementing multiple interfaces and extending one abstract class
is not equivalent

Thursday, December 12, 13
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out
Implementing multiple interfaces and extending one abstract class
is not equivalent
Implementing the multiple interfaces is work

Thursday, December 12, 13
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out
Implementing multiple interfaces and extending one abstract class
is not equivalent
Implementing the multiple interfaces is work
and
ose e
mp gat
Sharing code amongst implementations is hard Co le
de

Thursday, December 12, 13
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out
Implementing multiple interfaces and extending one abstract class
is not equivalent
Implementing the multiple interfaces is work
and
ose e
mp gat
Sharing code amongst implementations is hard Co le
de
Inconsistencies show up very quickly and maintenance is a pain
Thursday, December 12, 13
Inheritance
to Multiple
’s Solution
Java

L
I
A
F
#

Multiple Inheritance

The powers that be just went and tossed it out

Implementing multiple interfaces and extending one abstract class
is not equivalent
Implementing the multiple interfaces is work
and
ose e
mp gat
Sharing code amongst implementations is hard Co le
de
Inconsistencies show up very quickly and maintenance is a pain
Thursday, December 12, 13
nheritance
to Multiple I
a’s Solution
Scal

Thursday, December 12, 13
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

Thursday, December 12, 13
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

Scala integrates inheritance with mixin functionality

Thursday, December 12, 13
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

Scala integrates inheritance with mixin functionality
Traits provide the construct for mixins
trait
trait
trait
class

Thursday, December 12, 13

A
B extends A
C extends A
D extends B with C
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

trait
trait
trait
class

A
B extends A
C extends A
D extends B with C

AnyRef
A

Translates to

B
C
D

Thursday, December 12, 13

Initialize

Scala integrates inheritance with mixin functionality
Traits provide the construct for mixins

Any
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

trait
trait
trait
class

A
B extends A
C extends A
D extends B with C

A

Translates to

If a conflict exists between B and C with respect
to A, then C wins.
Thursday, December 12, 13

AnyRef

B
C
D

Initialize

Scala integrates inheritance with mixin functionality
Traits provide the construct for mixins

Any
Origins of the Cake
Dependency Injection and Modularity

Persistence

REST
Persistence

PicRetriever

Database
Persistence

Persistence
Randomizer
def randomPic: Future[Pic]

HashMap

Randomizer

Random
Randomizer

Specifier

Thursday, December 12, 13

Test

Test
Origins of the Cake
Dependency Injection and Modularity

Persistence

REST
Persistence

PicRetriever

Database
Persistence

Persistence
Randomizer
def randomPic: Future[Pic]

HashMap

Randomizer

Random
Randomizer

Specifier

Thursday, December 12, 13

Test

Test
Origins of the Cake
Dependency Injection and Modularity

Persistence

REST
Persistence

PicRetriever

ce on
lian
re re
Decla modules
hese
t

Database
Persistence

Persistence
Randomizer
def randomPic: Future[Pic]

HashMap

Randomizer

Random
Randomizer

Specifier

Thursday, December 12, 13

Test

Test
Origins of the Cake
Dependency Injection and Modularity

Persistence

REST
Persistence

PicRetriever

ce on
lian
re re
Decla modules
hese
t

Persistence

Persistence
Randomizer
def randomPic: Future[Pic]

new PicRetriever extends Database
with Random
Choos

e concrete
implementa
tions
Thursday, December 12, 13

Database
HashMap

Test

Randomizer

Random
Randomizer

Specifier

Test
Origins of the Cake

REST

Dependency Injection and Modularity
PicRetriever

ce on
lian
re re
Decla modules
hese
t

Persistence

Persistence
Database

Randomizer

Randomizer
Random

Persistence

iever
Retr
Pic
the Persistence
es in
Test
mix
HashMap
face
ter
in
the
and
tion
enta
plem
im

def randomPic: Future[Pic]

new PicRetriever extends Database
with Random
Choos

e concrete
implementa
tions
Thursday, December 12, 13

Randomizer

Specifier

Test
The Basic Cupcake
trait Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

Thursday, December 12, 13

trait Randomizer {
def nextInt(upperBound: Int): Int = ???
}
The Basic Cupcake
trait Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

trait Randomizer {
def nextInt(upperBound: Int): Int = ???
}

cRe
Pi

ever
tri

lare
Dec
ype
elf t
s

class PicRetriever { this: Persistence with Randomizer =>
def randomPic: Future[Pic] = ???
}
object PicRetriever {
def production: PicRetriever = new PicRetriever
with Persistence with Randomizer
}

Thursday, December 12, 13
The Basic Cupcake
trait Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

trait Randomizer {
def nextInt(upperBound: Int): Int = ???
}

cRe
Pi

ever
tri

lare
Dec
ype
elf t
s

class PicRetriever { this: Persistence with Randomizer =>
def randomPic: Future[Pic] = ???
}

Define factory method that
makes construction simpler

object PicRetriever {
def production: PicRetriever = new PicRetriever
with Persistence with Randomizer
}

Thursday, December 12, 13
The Basic Cupcake
trait Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

trait Randomizer {
def nextInt(upperBound: Int): Int = ???
}

cRe
Pi

ever
tri

lare
Dec
ype
elf t
s

class PicRetriever { this: Persistence with Randomizer =>
def randomPic: Future[Pic] = ???
}

Define factory method that
makes construction simpler

object PicRetriever {
def production: PicRetriever = new PicRetriever
with Persistence with Randomizer
}

You could derive new Persistence and Randomizer traits and
instantiate accordingly. Not great, but it does get the job done.
Thursday, December 12, 13
ng a Layer
Addi
The lack of an “interface” requires overrides in the derivations

Thursday, December 12, 13
ng a Layer
Addi
The lack of an “interface” requires overrides in the derivations
We can add that layer, making derivations easier to write

Thursday, December 12, 13
ng a Layer
Addi
The lack of an “interface” requires overrides in the derivations
We can add that layer, making derivations easier to write
trait
def
def
}
trait
val
def
def
}

Persistence {
pic(idx: Int): Future[Pic]
totalPics: Future[Int]
Database extends Persistence {
dbUrl: String
pic(idx: Int): Future[Pic] = ???
totalPics: Int = ???

Thursday, December 12, 13

trait
def
}
trait
def
}

Randomizer {
nextInt(upperBound: Int): Int
RealRandomizer extends Randomizer {
nextInt(upperBound: Int): Int = ???
ng a Layer
Addi
The lack of an “interface” requires overrides in the derivations
We can add that layer, making derivations easier to write
trait
def
def
}
trait
val
def
def
}

Persistence {
pic(idx: Int): Future[Pic]
totalPics: Future[Int]
Database extends Persistence {
dbUrl: String
pic(idx: Int): Future[Pic] = ???
totalPics: Int = ???

trait
def
}
trait
def
}

Randomizer {
nextInt(upperBound: Int): Int
RealRandomizer extends Randomizer {
nextInt(upperBound: Int): Int = ???

object PicRetriever {
def production: PicRetriever = new PicRetriever
with Database with RealRandomizer
}
Thursday, December 12, 13
Eliminating Naming Conflicts

Thursday, December 12, 13
Eliminating Naming Conflicts
There’s nothing to stop you from tromping all over your names

Thursday, December 12, 13
Eliminating Naming Conflicts
There’s nothing to stop you from tromping all over your names
It’s a good idea to give namespaces to the mixed-in modules
trait PersistenceComponent {
val persistence: Persistence
trait Persistence {
def pic(idx: Int): Future[Pic]
def totalPics: Future[Int]
}
}

Thursday, December 12, 13

trait RandomizerComponent {
val randomizer: Randomizer
trait Randomizer {
def nextInt(upperBound: Int): Int
}
}
Eliminating Naming Conflicts
There’s nothing to stop you from tromping all over your names
It’s a good idea to give namespaces to the mixed-in modules
trait PersistenceComponent {
val persistence: Persistence
trait Persistence {
def pic(idx: Int): Future[Pic]
def totalPics: Future[Int]
}
}

trait RandomizerComponent {
val randomizer: Randomizer
trait Randomizer {
def nextInt(upperBound: Int): Int
}
}

g can be
Everythin
th another
solved wi
indirection
layer of
Thursday, December 12, 13
Eliminating Naming Conflicts
There’s nothing to stop you from tromping all over your names
It’s a good idea to give namespaces to the mixed-in modules
trait PersistenceComponent {
trait RandomizerComponent {
val persistence: Persistence
val randomizer: Randomizer
trait Persistence {
trait Randomizer {
def pic(idx: Int): Future[Pic]
def nextInt(upperBound: Int): Int
def totalPics: Future[Int]
}
}
}
}
class PicRetriever { this: PersistenceComponent with RandomizerComponent =>
// ...
}
object PicRetriever {
def production: PicRetriever = new PicRetriever with ProdPersistence
with ProdRandomizer {
val persistence = new Persistence { }
val randomizer = new Randomizer { }
}
Thursday, December 12, 13
he Test
aming t
T

Thursday, December 12, 13
he Test
aming t
T

ze
ndomi
Ra

r

t
ponen
Com

ds
exten
p
{
erCom zer
izer
miz
om
i
do
stRan r: Random tends Rand
Te
e
rait
t
domiz omizer ex
i
an
nt =
val r estRand
I
Int):
t T
:
trai
Int
Bound
r
:
val i tInt(uppe
ex
def n
}
}

Thursday, December 12, 13

{
he Test
aming t
T

ze
ndomi
Ra

r

t
ponen
Com

{

ds
exten
p
{
erCom zer
izer
miz
om
i
do
{
stRan r: Random tends Rand
Te
ponent
om
trait andomize mizer ex
tenceC
i
is
nt =
val r estRando
s Pers
I
nd
p exte mponent
Int):
t T
:
Com
trai
{
Int
Bound
stence istenceCo
i:
per
tence
ersi
is
up
tP
val
tInt(
it Tes stence: Pers extends Pers
ex
tra
))
def n
cs(idx
persi
ence
pi
st
val
uture( ize)
tPersi r[Pic]
es
= F
}
.s
rait T s: Vecto
[Pic]
t
ture
e(pics
u
r
c
val pi idx: Int): F [Int] = Futu
}
(
ef pic Pics: Future
d
l
f tota
de

}
}

Thursday, December 12, 13
he Test
aming t
T

ze
ndomi
Ra

r

t
ponen
Com

{

ds
exten
p
{
erCom zer
izer
miz
om
i
do
{
stRan r: Random tends Rand
Te
ponent
om
trait andomize mizer ex
tenceC
i
is
nt =
val r estRando
s Pers
I
nd
p exte mponent
Int):
t T
:
Com
trai
{
Int
Bound
stence istenceCo
i:
per
tence
ersi
is
up
tP
val
tInt(
it Tes stence: Pers extends Pers
ex
tra
))
def n
cs(idx
persi
ence
pi
st
val
uture( ize)
tPersi r[Pic]
es
= F
}
.s
rait T s: Vecto
[Pic]
t
ture
e(pics
u
r
c
val pi idx: Int): F [Int] = Futu
}
(
ef pic Pics: Future
d
l
f tota
de

}

object TestPicRetriever
}
{
def test(num: Int, images
: Vector[Pic]): PicRetri
ever =
new PicRetriever with Te
stPersistenceComp
with TestRandomizerComp
{
val persistence = new Te
stPersistence { val pics
= images }
val randomizer = new Test
Randomizer { val i = num
}
}

Thursday, December 12, 13
he Test
aming t
T

ze
ndomi
Ra

r

t
ponen
Com

{

ds
exten
p
{
erCom zer
izer
miz
om
i
do
{
stRan r: Random tends Rand
Te
ponent
om
trait andomize mizer ex
tenceC
i
is
nt =
val r estRando
s Pers
I
nd
p exte mponent
Int):
t T
:
Com
trai
{
Int
Bound
stence istenceCo
i:
per
tence
ersi
is
up
tP
val
tInt(
it Tes stence: Pers extends Pers
ex
tra
))
def n
cs(idx
val pic = loadPic(“pic1”) rsi
pe
ence
pi
st
val
uture( ize)
tPersi r[Pic]
es
]
val retriever = TestPicRetriever.test(0, Vector(pic))= F pics.s
}
rait T s: Vecto
t
re[Pic ture(
u
Await.result(retriever.randomPic,:1.second)t should be (pic)
l pic
t): Fu nt] = Fu
va
In
}
I
(idx
pic
uture[
F
def
lPics:
ta
def to
}
object TestPicRetriever
}
{
def test(num: Int, images
: Vector[Pic]): PicRetri
ever =
new PicRetriever with Te
stPersistenceComp
with TestRandomizerComp
{
val persistence = new Te
stPersistence { val pics
= images }
val randomizer = new Test
Randomizer { val i = num
}
}

Thursday, December 12, 13
nough Analogues... Modularity!
E

Thursday, December 12, 13
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract

Thursday, December 12, 13
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract
Abstract types and constraints can solve the problem with greater flexibility

Thursday, December 12, 13
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract
Abstract types and constraints can solve the problem with greater flexibility
trait PersistenceLike {
def pic(idx: Int): Future[Pic]
def totalPics: Future[Int]
}

Thursday, December 12, 13

trait RandomizerLike {
def nextInt(upperBound: Int): Int
}
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract
Abstract types and constraints can solve the problem with greater flexibility
trait PersistenceLike {
def pic(idx: Int): Future[Pic]
def totalPics: Future[Int]
}

trait RandomizerLike {
def nextInt(upperBound: Int): Int
}

trait PicRetriever {
type Persistence <: PersistenceLike
type Randomizer <: RandomizerLike
val persistence: Persistence
val randomizer: Randomizer
}

Thursday, December 12, 13

// ...
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract
Abstract types and constraints can solve the problem with greater flexibility
trait PersistenceLike {
def pic(idx: Int): Future[Pic]
def totalPics: Future[Int]
}

Abstract types define
enough to work with for the
PicRetriever, but allow for
further specification later
Thursday, December 12, 13

trait RandomizerLike {
def nextInt(upperBound: Int): Int
}

trait PicRetriever {
type Persistence <: PersistenceLike
type Randomizer <: RandomizerLike
val persistence: Persistence
val randomizer: Randomizer
}

// ...
Use Case... Configuration

Thursday, December 12, 13
Use Case... Configuration
Let’s say you want to declare a method for configuring objects

trait
class
val
val
}
class
val
val
}
class
val
val
}

Thursday, December 12, 13

Config
DBConfig extends Config {
dbHost: String
dbPort: Int
RandomizerConfig extends Config {
randomSeed: Int
randomScale: Int
RESTConfig extends Config {
restHost: String
restPort: Int
Use Case... Configuration
Let’s say you want to declare a method for configuring objects
You want generality, so you can’t pass multiple configs
abstract class Component(config: Config)

Thursday, December 12, 13

trait
class
val
val
}
class
val
val
}
class
val
val
}

Config
DBConfig extends Config {
dbHost: String
dbPort: Int
RandomizerConfig extends Config {
randomSeed: Int
randomScale: Int
RESTConfig extends Config {
restHost: String
restPort: Int
Use Case... Configuration
Let’s say you want to declare a method for configuring objects
You want generality, so you can’t pass multiple configs
abstract class Component(config: Config)

trait Config
class DBConfig extends Config {
val dbHost: String
class Database(config: Config) extends Component(config) ort: Int
val dbP {
require(config.isInstanceOf[DBConfig])
}
}
class RandomizerConfig extends Config {
val randomSeed: Int
val randomScale: Int
class Randomizer(config: Config) extends Component(config) {
}
require(config.isInstanceOf[RandomizerConfig]) ss RESTConfig extends Config {
cla
}
val restHost: String
val restPort: Int
}
class REST(config: Config) extends Component(config) {
require(config.isInstanceOf[RESTConfig])
}
Thursday, December 12, 13
Use Case... Configuration
Let’s say you want to declare a method for configuring objects
You want generality, so you can’t pass multiple configs

d
an

e,
af
s
n
,U
g
ly
in
g
U
oy
n
n
A

abstract class Component(config: Config)

trait Config
class DBConfig extends Config {
val dbHost: String
class Database(config: Config) extends Component(config) ort: Int
val dbP {
require(config.isInstanceOf[DBConfig])
}
}
class RandomizerConfig extends Config {
val randomSeed: Int
val randomScale: Int
class Randomizer(config: Config) extends Component(config) {
}
require(config.isInstanceOf[RandomizerConfig]) ss RESTConfig extends Config {
cla
}
val restHost: String
val restPort: Int
}
class REST(config: Config) extends Component(config) {
require(config.isInstanceOf[RESTConfig])
}
Thursday, December 12, 13
ring through Inverse Generality
Configu

Database
Config

Thursday, December 12, 13

REST
Config

Randomization
Config
ring through Inverse Generality
Configu
Config

sA
I
Database
Config

Thursday, December 12, 13

IsA
REST
Config

IsA
Randomization
Config
ring through Inverse Generality
Configu
Config

sA
I
Database
Config

Thursday, December 12, 13

IsA
REST
Config

Empty generalization

IsA
Randomization
Config
ring through Inverse Generality
Configu
Database
Config

Randomization
Config

REST
Config

Da

REST

iz
m

ti
a

n
o

CONFIG OBJECT
ba
do
s
ta

e

an
R

Highly Specific
and Type safe
Thursday, December 12, 13
Thickly Typed Objects

Thursday, December 12, 13

❊
Kinda stolen from Daniel Spiewak
Thickly Typed Objects
trait ConfigComponent {
type Config
def config: Config
}

Thursday, December 12, 13

❊
Kinda stolen from Daniel Spiewak

Declare a way to
configure things
Thickly Typed Objects
trait ConfigComponent {
type Config
def config: Config
}

❊
Kinda stolen from Daniel Spiewak

Declare a way to
configure things

trait DBComponent extends PersistenceComponent with ConfigComponent {
type Config <: DBConfig
val persistence = new DB
class DB extends Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

}

trait DBConfig {
val dbHost: String
val dbPort: Int
}

Thursday, December 12, 13
Thickly Typed Objects
trait ConfigComponent {
type Config
def config: Config
}

❊
Kinda stolen from Daniel Spiewak

Declare a way to
configure things

trait DBComponent extends PersistenceComponent with ConfigComponent {
type Config <: DBConfig
val persistence = new DB
class DB extends Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

}

trait DBConfig {
val dbHost: String
val dbPort: Int
}

Thursday, December 12, 13

Define how to configure
this component
Thickly Typed Objects
trait ConfigComponent {
type Config
def config: Config
}

❊
Kinda stolen from Daniel Spiewak

Declare a way to
configure things

Repeat for REST and
Randomizer

trait DBComponent extends PersistenceComponent with ConfigComponent {
type Config <: DBConfig
val persistence = new DB
class DB extends Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

}

trait DBConfig {
val dbHost: String
val dbPort: Int
}

Thursday, December 12, 13

Define how to configure
this component
Typed Objects Continued
Thickly
class TheFinalThing extends DBComponent with RandomizerComponent
with RESTComponent {
type Config = DBConfig with RESTConfig with RandomzierConfig

}

object config extends DBConfig with RESTConfig
with RandomzierConfig {
val dbHost = “dbhost1”
val dbPort = 56872
val restHost = “resthost1”
val restPort = 8080
val randomSeed = System.currentTimeMillis.toInt
val randomScale = 6
}
// etc...

Thursday, December 12, 13
Typed Objects Continued
Thickly
class TheFinalThing extends DBComponent with RandomizerComponent
with RESTComponent {
type Config = DBConfig with RESTConfig with RandomzierConfig

}

object config extends DBConfig with RESTConfig
with RandomzierConfig {
val dbHost = “dbhost1”
val dbPort = 56872
val restHost = “resthost1”
val restPort = 8080
val randomSeed = System.currentTimeMillis.toInt
val randomScale = 6
}
// etc...

Thursday, December 12, 13

The config object now
conforms to the types
requested by everything
that’s been mixed in.
Typed Objects Continued
Thickly
class TheFinalThing extends DBComponent with RandomizerComponent
with RESTComponent {
type Config = DBConfig with RESTConfig with RandomzierConfig

}

object config extends DBConfig with RESTConfig
with RandomzierConfig {
val dbHost = “dbhost1”
val dbPort = 56872
val restHost = “resthost1”
val restPort = 8080
val randomSeed = System.currentTimeMillis.toInt
val randomScale = 6
}
// etc...

Thursday, December 12, 13

The config object now
conforms to the types
requested by everything
that’s been mixed in.
Each Component can access the fields of
their slice of the config object without the
need for casting. The compiler already
knows it’s right.
n and Frustration
ai
P

Thursday, December 12, 13
n and Frustration
ai
P
Cakes generally involve abstract

Thursday, December 12, 13

vals
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”

Thursday, December 12, 13
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an interesting initialization problem

Thursday, December 12, 13
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an interesting initialization problem
trait A {
val s: String
val t: String = s.substring(0, 2)
}
trait B {
val s: String = “What?”
}

Thursday, December 12, 13
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an interesting initialization problem
trait A {
val s: String
val t: String = s.substring(0, 2)
}
trait B {
val s: String = “What?”
}

Thursday, December 12, 13

class C extends A with B
val c = new C
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an interesting initialization problem
trait A {
val s: String
val t: String = s.substring(0, 2)
}
trait B {
val s: String = “What?”
}

Thursday, December 12, 13

class C extends A with B
val c = new C
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an interesting initialization problem
trait A {
val s: String
val t: String = s.substring(0, 2)
}
trait B {
val s: String = “What?”
}

Thursday, December 12, 13

PE
N

!!
!!!
!
class C extends A with B
val c = new C
Null Pointer Exceptions?!

Thursday, December 12, 13
Null Pointer Exceptions?!
We’re not used to these any more

Thursday, December 12, 13
Null Pointer Exceptions?!
We’re not used to these any more
They’re an artifact of initialization order and usage

Thursday, December 12, 13
Null Pointer Exceptions?!
We’re not used to these any more
They’re an artifact of initialization order and usage

A
B
C
Thursday, December 12, 13
Null Pointer Exceptions?!
We’re not used to these any more
They’re an artifact of initialization order and usage

Thursday, December 12, 13

Initialization Order

A
B
C
Null Pointer Exceptions?!
We’re not used to these any more
They’re an artifact of initialization order and usage

Thursday, December 12, 13

Initialization Order

A
B
C

A is referencing ‘s’
Null Pointer Exceptions?!
We’re not used to these any more
They’re an artifact of initialization order and usage

Thursday, December 12, 13

Initialization Order

A
B
C

A is referencing ‘s’
‘s’ hasn’t been initialized yet!
Null Pointer Exceptions?!
We’re not used to these any more
They’re an artifact of initialization order and usage

Thursday, December 12, 13

Initialization Order

A
B
C

A is referencing ‘s’
‘s’ hasn’t been initialized yet!
The only sane value for ‘s’ at
this point is null
Dealing with the Pain

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
trait A {
val s: String
val t: String = s.substring(0, 2)
}
class B(val s) extends A
val b = new B(“What?”)

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
trait A {
val s: String
val t: String = s.substring(0, 2)
}

OK

class B(val s) extends A
val b = new B(“What?”)

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
trait A {
val s: String
val t: String = s.substring(0, 2)
}

trait A {
val s: String
val t: String = s.substring(0, 2)
}

class B(val s) extends A

class B extends A {
lazy val s = “What?”
}

OK

val b = new B(“What?”)

val b = new B

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
trait A {
val s: String
val t: String = s.substring(0, 2)
}

trait A {
val s: String
val t: String = s.substring(0, 2)
}

class B(val s) extends A

class B extends A {
lazy val s = “What?”
}

OK

val b = new B(“What?”)

OK

val b = new B

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
trait A {
trait A {
val s: String
val s: String
val t: String = s.substring(0, 2)
val t: String = s.substring(0, 2)
trait A {
}
}
val s: String
val t: String = s.substring(0, 2)
class B extends A {
class B(val s) extends} A
lazy val s = “What?”
val b = new B(“What?”)class B extends A { }
def s = “What?”
val b = new B
}

OK

OK

val b = new B
Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
trait A {
trait A {
val s: String
val s: String
val t: String = s.substring(0, 2)
val t: String = s.substring(0, 2)
trait A {
}
}
val s: String
val t: String = s.substring(0, 2)
class B extends A {
class B(val s) extends} A
lazy val s = “What?”
val b = new B(“What?”)class B extends A { }
def s = “What?”
val b = new B
}

OK

OK

val b = new B
Thursday, December 12, 13

OK
Now go get Fat

Eat lots of cake

AND

audularize Yore Coad
M
Derek Wyatt
Twitter: @derekwyatt
Email: derek@derekwyatt.org
Thursday, December 12, 13

More Related Content

Similar to Baking Delicious Modularity in Scala

Cloud Austin 2013: Conferenced2013
Cloud Austin 2013: Conferenced2013Cloud Austin 2013: Conferenced2013
Cloud Austin 2013: Conferenced2013Karthik Gaekwad
 
OmniOS Motivation and Design ~ LISA 2012
OmniOS Motivation and Design ~ LISA 2012OmniOS Motivation and Design ~ LISA 2012
OmniOS Motivation and Design ~ LISA 2012Theo Schlossnagle
 
HTML5 e CSS3 - A nova novidade
HTML5 e CSS3 - A nova novidadeHTML5 e CSS3 - A nova novidade
HTML5 e CSS3 - A nova novidadeDiego Eis
 
UBC STAT545 2014 Cm001 intro to-course
UBC STAT545 2014 Cm001 intro to-courseUBC STAT545 2014 Cm001 intro to-course
UBC STAT545 2014 Cm001 intro to-courseJennifer Bryan
 
University of arizona mobile matters - technology, a means to an end
University of arizona   mobile matters - technology, a means to an endUniversity of arizona   mobile matters - technology, a means to an end
University of arizona mobile matters - technology, a means to an endThibault Imbert
 
Deconstructing Functional Programming
Deconstructing Functional ProgrammingDeconstructing Functional Programming
Deconstructing Functional ProgrammingC4Media
 
How AngryNerds Convinced Atlassian to Use Magnolia
How AngryNerds Convinced Atlassian to Use MagnoliaHow AngryNerds Convinced Atlassian to Use Magnolia
How AngryNerds Convinced Atlassian to Use Magnoliabkraft
 
.NET Development for SQL Server Developer - Sql Saturday #264 Ancona
.NET Development for SQL Server Developer - Sql Saturday #264 Ancona.NET Development for SQL Server Developer - Sql Saturday #264 Ancona
.NET Development for SQL Server Developer - Sql Saturday #264 AnconaMarco Parenzan
 
Refactoring annotations
Refactoring annotationsRefactoring annotations
Refactoring annotationsCarlos Noguera
 
Replacing Wordpress with Cascade Server (where possible) by Mike Roy
Replacing Wordpress with Cascade Server (where possible) by Mike RoyReplacing Wordpress with Cascade Server (where possible) by Mike Roy
Replacing Wordpress with Cascade Server (where possible) by Mike Royhannonhill
 
Cassandra - PHP
Cassandra - PHPCassandra - PHP
Cassandra - PHPmauritsl
 
Ga london-html5&mobile advertising-tomlimongello
Ga london-html5&mobile advertising-tomlimongelloGa london-html5&mobile advertising-tomlimongello
Ga london-html5&mobile advertising-tomlimongelloTom Limongello
 
იოსებ ძმანაშვილი Node.js
იოსებ ძმანაშვილი   Node.jsიოსებ ძმანაშვილი   Node.js
იოსებ ძმანაშვილი Node.jsunihack
 
JavaScript DOM Manipulations
JavaScript DOM ManipulationsJavaScript DOM Manipulations
JavaScript DOM ManipulationsYnon Perek
 
.NET Development for SQL Server Developer
.NET Development for SQL Server Developer.NET Development for SQL Server Developer
.NET Development for SQL Server DeveloperMarco Parenzan
 

Similar to Baking Delicious Modularity in Scala (20)

Cloud Austin 2013: Conferenced2013
Cloud Austin 2013: Conferenced2013Cloud Austin 2013: Conferenced2013
Cloud Austin 2013: Conferenced2013
 
OmniOS Motivation and Design ~ LISA 2012
OmniOS Motivation and Design ~ LISA 2012OmniOS Motivation and Design ~ LISA 2012
OmniOS Motivation and Design ~ LISA 2012
 
HTML5 e CSS3 - A nova novidade
HTML5 e CSS3 - A nova novidadeHTML5 e CSS3 - A nova novidade
HTML5 e CSS3 - A nova novidade
 
Technology largely unseen - but on the radar
Technology largely unseen - but on the radarTechnology largely unseen - but on the radar
Technology largely unseen - but on the radar
 
StORM preview
StORM previewStORM preview
StORM preview
 
UBC STAT545 2014 Cm001 intro to-course
UBC STAT545 2014 Cm001 intro to-courseUBC STAT545 2014 Cm001 intro to-course
UBC STAT545 2014 Cm001 intro to-course
 
Java 8 to the rescue!?
Java 8 to the rescue!?Java 8 to the rescue!?
Java 8 to the rescue!?
 
University of arizona mobile matters - technology, a means to an end
University of arizona   mobile matters - technology, a means to an endUniversity of arizona   mobile matters - technology, a means to an end
University of arizona mobile matters - technology, a means to an end
 
Deconstructing Functional Programming
Deconstructing Functional ProgrammingDeconstructing Functional Programming
Deconstructing Functional Programming
 
How AngryNerds Convinced Atlassian to Use Magnolia
How AngryNerds Convinced Atlassian to Use MagnoliaHow AngryNerds Convinced Atlassian to Use Magnolia
How AngryNerds Convinced Atlassian to Use Magnolia
 
Neo4j
Neo4jNeo4j
Neo4j
 
.NET Development for SQL Server Developer - Sql Saturday #264 Ancona
.NET Development for SQL Server Developer - Sql Saturday #264 Ancona.NET Development for SQL Server Developer - Sql Saturday #264 Ancona
.NET Development for SQL Server Developer - Sql Saturday #264 Ancona
 
Refactoring annotations
Refactoring annotationsRefactoring annotations
Refactoring annotations
 
20151020 Metis
20151020 Metis20151020 Metis
20151020 Metis
 
Replacing Wordpress with Cascade Server (where possible) by Mike Roy
Replacing Wordpress with Cascade Server (where possible) by Mike RoyReplacing Wordpress with Cascade Server (where possible) by Mike Roy
Replacing Wordpress with Cascade Server (where possible) by Mike Roy
 
Cassandra - PHP
Cassandra - PHPCassandra - PHP
Cassandra - PHP
 
Ga london-html5&mobile advertising-tomlimongello
Ga london-html5&mobile advertising-tomlimongelloGa london-html5&mobile advertising-tomlimongello
Ga london-html5&mobile advertising-tomlimongello
 
იოსებ ძმანაშვილი Node.js
იოსებ ძმანაშვილი   Node.jsიოსებ ძმანაშვილი   Node.js
იოსებ ძმანაშვილი Node.js
 
JavaScript DOM Manipulations
JavaScript DOM ManipulationsJavaScript DOM Manipulations
JavaScript DOM Manipulations
 
.NET Development for SQL Server Developer
.NET Development for SQL Server Developer.NET Development for SQL Server Developer
.NET Development for SQL Server Developer
 

Recently uploaded

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 

Recently uploaded (20)

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 

Baking Delicious Modularity in Scala

  • 1. Baking Delicious Modularization cala in S Derek Wyatt Twitter: @derekwyatt Email: derek@derekwyatt.org Thursday, December 12, 13
  • 2. odularity Oriented M Object OOD gives us... Thursday, December 12, 13
  • 3. odularity Oriented M Object OOD gives us... Thursday, December 12, 13 private Inheritance Clanc erfaces I sist s&ro ses ubl e p tlas p Cected Composition act str Ab
  • 4. odularity Oriented M Object OOD gives us... C++ gave us... Thursday, December 12, 13 private Inheritance Clanc erfaces I sist s&ro ses ubl e p tlas p Cected Composition act str Ab ht? R ig ... l Ev i Multiple Inheritance lain st P Ju
  • 5. d Problem he Diamon T is Thursday, December 12, 13 A B is A A C
  • 7. d Problem he Diamon T A A is is A ? B A is Thursday, December 12, 13 D C is A Who initializes A?
  • 8. d Problem he Diamon T A is A D C is A A Thursday, December 12, 13 ? B is They can’t both do it! is l d s it initiaoizeoes C B need S d A Who initializes A?
  • 9. d Problem he Diamon T A is A Thursday, December 12, 13 D C is A A Enter: Virtual Inheritance ? B is They can’t both do it! is l d s it initiaoizeoes C B need S d A Who initializes A?
  • 10. d Problem he Diamon T A is A ? A D C is A B is They can’t both do it! is l d s it initiaoizeoes C B need S d A Who initializes A? Enter: Virtual Inheritance Convincing the world for decades that Multiple Inheritance is BAD Thursday, December 12, 13
  • 11. Inheritance to Multiple ’s Solution Java Multiple Inheritance Thursday, December 12, 13
  • 12. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Thursday, December 12, 13
  • 13. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Thursday, December 12, 13
  • 14. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Implementing the multiple interfaces is work Thursday, December 12, 13
  • 15. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Implementing the multiple interfaces is work and ose e mp gat Sharing code amongst implementations is hard Co le de Thursday, December 12, 13
  • 16. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Implementing the multiple interfaces is work and ose e mp gat Sharing code amongst implementations is hard Co le de Inconsistencies show up very quickly and maintenance is a pain Thursday, December 12, 13
  • 17. Inheritance to Multiple ’s Solution Java L I A F # Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Implementing the multiple interfaces is work and ose e mp gat Sharing code amongst implementations is hard Co le de Inconsistencies show up very quickly and maintenance is a pain Thursday, December 12, 13
  • 18. nheritance to Multiple I a’s Solution Scal Thursday, December 12, 13
  • 19. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond Thursday, December 12, 13
  • 20. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond Scala integrates inheritance with mixin functionality Thursday, December 12, 13
  • 21. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond Scala integrates inheritance with mixin functionality Traits provide the construct for mixins trait trait trait class Thursday, December 12, 13 A B extends A C extends A D extends B with C
  • 22. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond trait trait trait class A B extends A C extends A D extends B with C AnyRef A Translates to B C D Thursday, December 12, 13 Initialize Scala integrates inheritance with mixin functionality Traits provide the construct for mixins Any
  • 23. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond trait trait trait class A B extends A C extends A D extends B with C A Translates to If a conflict exists between B and C with respect to A, then C wins. Thursday, December 12, 13 AnyRef B C D Initialize Scala integrates inheritance with mixin functionality Traits provide the construct for mixins Any
  • 24. Origins of the Cake Dependency Injection and Modularity Persistence REST Persistence PicRetriever Database Persistence Persistence Randomizer def randomPic: Future[Pic] HashMap Randomizer Random Randomizer Specifier Thursday, December 12, 13 Test Test
  • 25. Origins of the Cake Dependency Injection and Modularity Persistence REST Persistence PicRetriever Database Persistence Persistence Randomizer def randomPic: Future[Pic] HashMap Randomizer Random Randomizer Specifier Thursday, December 12, 13 Test Test
  • 26. Origins of the Cake Dependency Injection and Modularity Persistence REST Persistence PicRetriever ce on lian re re Decla modules hese t Database Persistence Persistence Randomizer def randomPic: Future[Pic] HashMap Randomizer Random Randomizer Specifier Thursday, December 12, 13 Test Test
  • 27. Origins of the Cake Dependency Injection and Modularity Persistence REST Persistence PicRetriever ce on lian re re Decla modules hese t Persistence Persistence Randomizer def randomPic: Future[Pic] new PicRetriever extends Database with Random Choos e concrete implementa tions Thursday, December 12, 13 Database HashMap Test Randomizer Random Randomizer Specifier Test
  • 28. Origins of the Cake REST Dependency Injection and Modularity PicRetriever ce on lian re re Decla modules hese t Persistence Persistence Database Randomizer Randomizer Random Persistence iever Retr Pic the Persistence es in Test mix HashMap face ter in the and tion enta plem im def randomPic: Future[Pic] new PicRetriever extends Database with Random Choos e concrete implementa tions Thursday, December 12, 13 Randomizer Specifier Test
  • 29. The Basic Cupcake trait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } Thursday, December 12, 13 trait Randomizer { def nextInt(upperBound: Int): Int = ??? }
  • 30. The Basic Cupcake trait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } trait Randomizer { def nextInt(upperBound: Int): Int = ??? } cRe Pi ever tri lare Dec ype elf t s class PicRetriever { this: Persistence with Randomizer => def randomPic: Future[Pic] = ??? } object PicRetriever { def production: PicRetriever = new PicRetriever with Persistence with Randomizer } Thursday, December 12, 13
  • 31. The Basic Cupcake trait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } trait Randomizer { def nextInt(upperBound: Int): Int = ??? } cRe Pi ever tri lare Dec ype elf t s class PicRetriever { this: Persistence with Randomizer => def randomPic: Future[Pic] = ??? } Define factory method that makes construction simpler object PicRetriever { def production: PicRetriever = new PicRetriever with Persistence with Randomizer } Thursday, December 12, 13
  • 32. The Basic Cupcake trait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } trait Randomizer { def nextInt(upperBound: Int): Int = ??? } cRe Pi ever tri lare Dec ype elf t s class PicRetriever { this: Persistence with Randomizer => def randomPic: Future[Pic] = ??? } Define factory method that makes construction simpler object PicRetriever { def production: PicRetriever = new PicRetriever with Persistence with Randomizer } You could derive new Persistence and Randomizer traits and instantiate accordingly. Not great, but it does get the job done. Thursday, December 12, 13
  • 33. ng a Layer Addi The lack of an “interface” requires overrides in the derivations Thursday, December 12, 13
  • 34. ng a Layer Addi The lack of an “interface” requires overrides in the derivations We can add that layer, making derivations easier to write Thursday, December 12, 13
  • 35. ng a Layer Addi The lack of an “interface” requires overrides in the derivations We can add that layer, making derivations easier to write trait def def } trait val def def } Persistence { pic(idx: Int): Future[Pic] totalPics: Future[Int] Database extends Persistence { dbUrl: String pic(idx: Int): Future[Pic] = ??? totalPics: Int = ??? Thursday, December 12, 13 trait def } trait def } Randomizer { nextInt(upperBound: Int): Int RealRandomizer extends Randomizer { nextInt(upperBound: Int): Int = ???
  • 36. ng a Layer Addi The lack of an “interface” requires overrides in the derivations We can add that layer, making derivations easier to write trait def def } trait val def def } Persistence { pic(idx: Int): Future[Pic] totalPics: Future[Int] Database extends Persistence { dbUrl: String pic(idx: Int): Future[Pic] = ??? totalPics: Int = ??? trait def } trait def } Randomizer { nextInt(upperBound: Int): Int RealRandomizer extends Randomizer { nextInt(upperBound: Int): Int = ??? object PicRetriever { def production: PicRetriever = new PicRetriever with Database with RealRandomizer } Thursday, December 12, 13
  • 38. Eliminating Naming Conflicts There’s nothing to stop you from tromping all over your names Thursday, December 12, 13
  • 39. Eliminating Naming Conflicts There’s nothing to stop you from tromping all over your names It’s a good idea to give namespaces to the mixed-in modules trait PersistenceComponent { val persistence: Persistence trait Persistence { def pic(idx: Int): Future[Pic] def totalPics: Future[Int] } } Thursday, December 12, 13 trait RandomizerComponent { val randomizer: Randomizer trait Randomizer { def nextInt(upperBound: Int): Int } }
  • 40. Eliminating Naming Conflicts There’s nothing to stop you from tromping all over your names It’s a good idea to give namespaces to the mixed-in modules trait PersistenceComponent { val persistence: Persistence trait Persistence { def pic(idx: Int): Future[Pic] def totalPics: Future[Int] } } trait RandomizerComponent { val randomizer: Randomizer trait Randomizer { def nextInt(upperBound: Int): Int } } g can be Everythin th another solved wi indirection layer of Thursday, December 12, 13
  • 41. Eliminating Naming Conflicts There’s nothing to stop you from tromping all over your names It’s a good idea to give namespaces to the mixed-in modules trait PersistenceComponent { trait RandomizerComponent { val persistence: Persistence val randomizer: Randomizer trait Persistence { trait Randomizer { def pic(idx: Int): Future[Pic] def nextInt(upperBound: Int): Int def totalPics: Future[Int] } } } } class PicRetriever { this: PersistenceComponent with RandomizerComponent => // ... } object PicRetriever { def production: PicRetriever = new PicRetriever with ProdPersistence with ProdRandomizer { val persistence = new Persistence { } val randomizer = new Randomizer { } } Thursday, December 12, 13
  • 42. he Test aming t T Thursday, December 12, 13
  • 43. he Test aming t T ze ndomi Ra r t ponen Com ds exten p { erCom zer izer miz om i do stRan r: Random tends Rand Te e rait t domiz omizer ex i an nt = val r estRand I Int): t T : trai Int Bound r : val i tInt(uppe ex def n } } Thursday, December 12, 13 {
  • 44. he Test aming t T ze ndomi Ra r t ponen Com { ds exten p { erCom zer izer miz om i do { stRan r: Random tends Rand Te ponent om trait andomize mizer ex tenceC i is nt = val r estRando s Pers I nd p exte mponent Int): t T : Com trai { Int Bound stence istenceCo i: per tence ersi is up tP val tInt( it Tes stence: Pers extends Pers ex tra )) def n cs(idx persi ence pi st val uture( ize) tPersi r[Pic] es = F } .s rait T s: Vecto [Pic] t ture e(pics u r c val pi idx: Int): F [Int] = Futu } ( ef pic Pics: Future d l f tota de } } Thursday, December 12, 13
  • 45. he Test aming t T ze ndomi Ra r t ponen Com { ds exten p { erCom zer izer miz om i do { stRan r: Random tends Rand Te ponent om trait andomize mizer ex tenceC i is nt = val r estRando s Pers I nd p exte mponent Int): t T : Com trai { Int Bound stence istenceCo i: per tence ersi is up tP val tInt( it Tes stence: Pers extends Pers ex tra )) def n cs(idx persi ence pi st val uture( ize) tPersi r[Pic] es = F } .s rait T s: Vecto [Pic] t ture e(pics u r c val pi idx: Int): F [Int] = Futu } ( ef pic Pics: Future d l f tota de } object TestPicRetriever } { def test(num: Int, images : Vector[Pic]): PicRetri ever = new PicRetriever with Te stPersistenceComp with TestRandomizerComp { val persistence = new Te stPersistence { val pics = images } val randomizer = new Test Randomizer { val i = num } } Thursday, December 12, 13
  • 46. he Test aming t T ze ndomi Ra r t ponen Com { ds exten p { erCom zer izer miz om i do { stRan r: Random tends Rand Te ponent om trait andomize mizer ex tenceC i is nt = val r estRando s Pers I nd p exte mponent Int): t T : Com trai { Int Bound stence istenceCo i: per tence ersi is up tP val tInt( it Tes stence: Pers extends Pers ex tra )) def n cs(idx val pic = loadPic(“pic1”) rsi pe ence pi st val uture( ize) tPersi r[Pic] es ] val retriever = TestPicRetriever.test(0, Vector(pic))= F pics.s } rait T s: Vecto t re[Pic ture( u Await.result(retriever.randomPic,:1.second)t should be (pic) l pic t): Fu nt] = Fu va In } I (idx pic uture[ F def lPics: ta def to } object TestPicRetriever } { def test(num: Int, images : Vector[Pic]): PicRetri ever = new PicRetriever with Te stPersistenceComp with TestRandomizerComp { val persistence = new Te stPersistence { val pics = images } val randomizer = new Test Randomizer { val i = num } } Thursday, December 12, 13
  • 48. nough Analogues... Modularity! E You don’t have to “self type” in order to establish the contract Thursday, December 12, 13
  • 49. nough Analogues... Modularity! E You don’t have to “self type” in order to establish the contract Abstract types and constraints can solve the problem with greater flexibility Thursday, December 12, 13
  • 50. nough Analogues... Modularity! E You don’t have to “self type” in order to establish the contract Abstract types and constraints can solve the problem with greater flexibility trait PersistenceLike { def pic(idx: Int): Future[Pic] def totalPics: Future[Int] } Thursday, December 12, 13 trait RandomizerLike { def nextInt(upperBound: Int): Int }
  • 51. nough Analogues... Modularity! E You don’t have to “self type” in order to establish the contract Abstract types and constraints can solve the problem with greater flexibility trait PersistenceLike { def pic(idx: Int): Future[Pic] def totalPics: Future[Int] } trait RandomizerLike { def nextInt(upperBound: Int): Int } trait PicRetriever { type Persistence <: PersistenceLike type Randomizer <: RandomizerLike val persistence: Persistence val randomizer: Randomizer } Thursday, December 12, 13 // ...
  • 52. nough Analogues... Modularity! E You don’t have to “self type” in order to establish the contract Abstract types and constraints can solve the problem with greater flexibility trait PersistenceLike { def pic(idx: Int): Future[Pic] def totalPics: Future[Int] } Abstract types define enough to work with for the PicRetriever, but allow for further specification later Thursday, December 12, 13 trait RandomizerLike { def nextInt(upperBound: Int): Int } trait PicRetriever { type Persistence <: PersistenceLike type Randomizer <: RandomizerLike val persistence: Persistence val randomizer: Randomizer } // ...
  • 54. Use Case... Configuration Let’s say you want to declare a method for configuring objects trait class val val } class val val } class val val } Thursday, December 12, 13 Config DBConfig extends Config { dbHost: String dbPort: Int RandomizerConfig extends Config { randomSeed: Int randomScale: Int RESTConfig extends Config { restHost: String restPort: Int
  • 55. Use Case... Configuration Let’s say you want to declare a method for configuring objects You want generality, so you can’t pass multiple configs abstract class Component(config: Config) Thursday, December 12, 13 trait class val val } class val val } class val val } Config DBConfig extends Config { dbHost: String dbPort: Int RandomizerConfig extends Config { randomSeed: Int randomScale: Int RESTConfig extends Config { restHost: String restPort: Int
  • 56. Use Case... Configuration Let’s say you want to declare a method for configuring objects You want generality, so you can’t pass multiple configs abstract class Component(config: Config) trait Config class DBConfig extends Config { val dbHost: String class Database(config: Config) extends Component(config) ort: Int val dbP { require(config.isInstanceOf[DBConfig]) } } class RandomizerConfig extends Config { val randomSeed: Int val randomScale: Int class Randomizer(config: Config) extends Component(config) { } require(config.isInstanceOf[RandomizerConfig]) ss RESTConfig extends Config { cla } val restHost: String val restPort: Int } class REST(config: Config) extends Component(config) { require(config.isInstanceOf[RESTConfig]) } Thursday, December 12, 13
  • 57. Use Case... Configuration Let’s say you want to declare a method for configuring objects You want generality, so you can’t pass multiple configs d an e, af s n ,U g ly in g U oy n n A abstract class Component(config: Config) trait Config class DBConfig extends Config { val dbHost: String class Database(config: Config) extends Component(config) ort: Int val dbP { require(config.isInstanceOf[DBConfig]) } } class RandomizerConfig extends Config { val randomSeed: Int val randomScale: Int class Randomizer(config: Config) extends Component(config) { } require(config.isInstanceOf[RandomizerConfig]) ss RESTConfig extends Config { cla } val restHost: String val restPort: Int } class REST(config: Config) extends Component(config) { require(config.isInstanceOf[RESTConfig]) } Thursday, December 12, 13
  • 58. ring through Inverse Generality Configu Database Config Thursday, December 12, 13 REST Config Randomization Config
  • 59. ring through Inverse Generality Configu Config sA I Database Config Thursday, December 12, 13 IsA REST Config IsA Randomization Config
  • 60. ring through Inverse Generality Configu Config sA I Database Config Thursday, December 12, 13 IsA REST Config Empty generalization IsA Randomization Config
  • 61. ring through Inverse Generality Configu Database Config Randomization Config REST Config Da REST iz m ti a n o CONFIG OBJECT ba do s ta e an R Highly Specific and Type safe Thursday, December 12, 13
  • 62. Thickly Typed Objects Thursday, December 12, 13 ❊ Kinda stolen from Daniel Spiewak
  • 63. Thickly Typed Objects trait ConfigComponent { type Config def config: Config } Thursday, December 12, 13 ❊ Kinda stolen from Daniel Spiewak Declare a way to configure things
  • 64. Thickly Typed Objects trait ConfigComponent { type Config def config: Config } ❊ Kinda stolen from Daniel Spiewak Declare a way to configure things trait DBComponent extends PersistenceComponent with ConfigComponent { type Config <: DBConfig val persistence = new DB class DB extends Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } } trait DBConfig { val dbHost: String val dbPort: Int } Thursday, December 12, 13
  • 65. Thickly Typed Objects trait ConfigComponent { type Config def config: Config } ❊ Kinda stolen from Daniel Spiewak Declare a way to configure things trait DBComponent extends PersistenceComponent with ConfigComponent { type Config <: DBConfig val persistence = new DB class DB extends Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } } trait DBConfig { val dbHost: String val dbPort: Int } Thursday, December 12, 13 Define how to configure this component
  • 66. Thickly Typed Objects trait ConfigComponent { type Config def config: Config } ❊ Kinda stolen from Daniel Spiewak Declare a way to configure things Repeat for REST and Randomizer trait DBComponent extends PersistenceComponent with ConfigComponent { type Config <: DBConfig val persistence = new DB class DB extends Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } } trait DBConfig { val dbHost: String val dbPort: Int } Thursday, December 12, 13 Define how to configure this component
  • 67. Typed Objects Continued Thickly class TheFinalThing extends DBComponent with RandomizerComponent with RESTComponent { type Config = DBConfig with RESTConfig with RandomzierConfig } object config extends DBConfig with RESTConfig with RandomzierConfig { val dbHost = “dbhost1” val dbPort = 56872 val restHost = “resthost1” val restPort = 8080 val randomSeed = System.currentTimeMillis.toInt val randomScale = 6 } // etc... Thursday, December 12, 13
  • 68. Typed Objects Continued Thickly class TheFinalThing extends DBComponent with RandomizerComponent with RESTComponent { type Config = DBConfig with RESTConfig with RandomzierConfig } object config extends DBConfig with RESTConfig with RandomzierConfig { val dbHost = “dbhost1” val dbPort = 56872 val restHost = “resthost1” val restPort = 8080 val randomSeed = System.currentTimeMillis.toInt val randomScale = 6 } // etc... Thursday, December 12, 13 The config object now conforms to the types requested by everything that’s been mixed in.
  • 69. Typed Objects Continued Thickly class TheFinalThing extends DBComponent with RandomizerComponent with RESTComponent { type Config = DBConfig with RESTConfig with RandomzierConfig } object config extends DBConfig with RESTConfig with RandomzierConfig { val dbHost = “dbhost1” val dbPort = 56872 val restHost = “resthost1” val restPort = 8080 val randomSeed = System.currentTimeMillis.toInt val randomScale = 6 } // etc... Thursday, December 12, 13 The config object now conforms to the types requested by everything that’s been mixed in. Each Component can access the fields of their slice of the config object without the need for casting. The compiler already knows it’s right.
  • 71. n and Frustration ai P Cakes generally involve abstract Thursday, December 12, 13 vals
  • 72. n and Frustration ai P Cakes generally involve abstract vals They also involve “Multiple Inheritance” Thursday, December 12, 13
  • 73. n and Frustration ai P Cakes generally involve abstract vals They also involve “Multiple Inheritance” This presents an interesting initialization problem Thursday, December 12, 13
  • 74. n and Frustration ai P Cakes generally involve abstract vals They also involve “Multiple Inheritance” This presents an interesting initialization problem trait A { val s: String val t: String = s.substring(0, 2) } trait B { val s: String = “What?” } Thursday, December 12, 13
  • 75. n and Frustration ai P Cakes generally involve abstract vals They also involve “Multiple Inheritance” This presents an interesting initialization problem trait A { val s: String val t: String = s.substring(0, 2) } trait B { val s: String = “What?” } Thursday, December 12, 13 class C extends A with B val c = new C
  • 76. n and Frustration ai P Cakes generally involve abstract vals They also involve “Multiple Inheritance” This presents an interesting initialization problem trait A { val s: String val t: String = s.substring(0, 2) } trait B { val s: String = “What?” } Thursday, December 12, 13 class C extends A with B val c = new C
  • 77. n and Frustration ai P Cakes generally involve abstract vals They also involve “Multiple Inheritance” This presents an interesting initialization problem trait A { val s: String val t: String = s.substring(0, 2) } trait B { val s: String = “What?” } Thursday, December 12, 13 PE N !! !!! ! class C extends A with B val c = new C
  • 79. Null Pointer Exceptions?! We’re not used to these any more Thursday, December 12, 13
  • 80. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13
  • 81. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage A B C Thursday, December 12, 13
  • 82. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13 Initialization Order A B C
  • 83. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13 Initialization Order A B C A is referencing ‘s’
  • 84. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13 Initialization Order A B C A is referencing ‘s’ ‘s’ hasn’t been initialized yet!
  • 85. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13 Initialization Order A B C A is referencing ‘s’ ‘s’ hasn’t been initialized yet! The only sane value for ‘s’ at this point is null
  • 86. Dealing with the Pain Thursday, December 12, 13
  • 87. Dealing with the Pain Methods aren’t susceptible to this problem Thursday, December 12, 13
  • 88. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Thursday, December 12, 13
  • 89. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters Thursday, December 12, 13
  • 90. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters trait A { val s: String val t: String = s.substring(0, 2) } class B(val s) extends A val b = new B(“What?”) Thursday, December 12, 13
  • 91. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters trait A { val s: String val t: String = s.substring(0, 2) } OK class B(val s) extends A val b = new B(“What?”) Thursday, December 12, 13
  • 92. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters trait A { val s: String val t: String = s.substring(0, 2) } trait A { val s: String val t: String = s.substring(0, 2) } class B(val s) extends A class B extends A { lazy val s = “What?” } OK val b = new B(“What?”) val b = new B Thursday, December 12, 13
  • 93. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters trait A { val s: String val t: String = s.substring(0, 2) } trait A { val s: String val t: String = s.substring(0, 2) } class B(val s) extends A class B extends A { lazy val s = “What?” } OK val b = new B(“What?”) OK val b = new B Thursday, December 12, 13
  • 94. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters trait A { trait A { val s: String val s: String val t: String = s.substring(0, 2) val t: String = s.substring(0, 2) trait A { } } val s: String val t: String = s.substring(0, 2) class B extends A { class B(val s) extends} A lazy val s = “What?” val b = new B(“What?”)class B extends A { } def s = “What?” val b = new B } OK OK val b = new B Thursday, December 12, 13
  • 95. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters trait A { trait A { val s: String val s: String val t: String = s.substring(0, 2) val t: String = s.substring(0, 2) trait A { } } val s: String val t: String = s.substring(0, 2) class B extends A { class B(val s) extends} A lazy val s = “What?” val b = new B(“What?”)class B extends A { } def s = “What?” val b = new B } OK OK val b = new B Thursday, December 12, 13 OK
  • 96. Now go get Fat Eat lots of cake AND audularize Yore Coad M Derek Wyatt Twitter: @derekwyatt Email: derek@derekwyatt.org Thursday, December 12, 13