This was a presentation I gave in October 2013 to the Waterloo Scala Meetup. It's probably the 437th presentation on Scala modularity to date. There's tons of them, but the group was curious about how it was done and wanted the personal touch, so I gave it to them...
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
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
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
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
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
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
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
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
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.
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
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
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