Download as pdf or txt
Download as pdf or txt
You are on page 1of 448

Download at WoweBook.

Com
Programming Scala

Download at WoweBook.Com
Download at WoweBook.Com
Programming Scala

'HDQ:DPSOHUDQG$OH[3D\QH

Beijing • Cambridge • Farnham • Köln • Sebastopol • Taipei • Tokyo

Download at WoweBook.Com
Programming Scala
E\'HDQ:DPSOHUDQG$OH[3D\QH

&RS\ULJKW‹'HDQ:DPSOHUDQG$OH[3D\QH$OOULJKWVUHVHUYHG
3ULQWHGLQWKH8QLWHG6WDWHVRI$PHULFD

3XEOLVKHGE\2¦5HLOO\0HGLD,QF*UDYHQVWHLQ+LJKZD\1RUWK6HEDVWRSRO&$

2¦5HLOO\ERRNVPD\EHSXUFKDVHGIRUHGXFDWLRQDOEXVLQHVVRUVDOHVSURPRWLRQDOXVH2QOLQHHGLWLRQV
DUHDOVRDYDLODEOHIRUPRVWWLWOHV KWWSP\VDIDULERRNVRQOLQHFRP )RUPRUHLQIRUPDWLRQFRQWDFWRXU
FRUSRUDWHLQVWLWXWLRQDOVDOHVGHSDUWPHQWRUFRUSRUDWH#RUHLOO\FRP

Editor: 0LNH/RXNLGHV Indexer: (OOHQ7URXWPDQ=DLJ


Production Editor: 6DUDK6FKQHLGHU Cover Designer: .DUHQ0RQWJRPHU\
Proofreader: 6DUDK6FKQHLGHU Interior Designer: 'DYLG)XWDWR
Illustrator: 5REHUW5RPDQR

Printing History:
6HSWHPEHU )LUVW(GLWLRQ

2¦5HLOO\DQGWKH2¦5HLOO\ORJRDUHUHJLVWHUHGWUDGHPDUNVRI2¦5HLOO\0HGLD,QF3URJUDPPLQJ6FDODWKH
LPDJHRID0DOD\DQWDSLUDQGUHODWHGWUDGHGUHVVDUHWUDGHPDUNVRI2¦5HLOO\0HGLD,QF
0DQ\RIWKHGHVLJQDWLRQVXVHGE\PDQXIDFWXUHUVDQGVHOOHUVWRGLVWLQJXLVKWKHLUSURGXFWVDUHFODLPHGDV
WUDGHPDUNV:KHUHWKRVHGHVLJQDWLRQVDSSHDULQWKLVERRNDQG2¦5HLOO\0HGLD,QFZDVDZDUHRID
WUDGHPDUNFODLPWKHGHVLJQDWLRQVKDYHEHHQSULQWHGLQFDSVRULQLWLDOFDSV

:KLOHHYHU\SUHFDXWLRQKDVEHHQWDNHQLQWKHSUHSDUDWLRQRIWKLVERRNWKHSXEOLVKHUDQGDXWKRUVDVVXPH
QRUHVSRQVLELOLW\IRUHUURUVRURPLVVLRQVRUIRUGDPDJHVUHVXOWLQJIURPWKHXVHRIWKHLQIRUPDWLRQFRQ
WDLQHGKHUHLQ7KLVZRUNKDVEHHQUHOHDVHGXQGHUWKH&UHDWLYH&RPPRQV$WWULEXWLRQ1RQFRPPHUFLDO
OLFHQVH

,6%1

>0@



Download at WoweBook.Com
7R'DGDQG0RPZKRDOZD\VEHOLHYHGLQPH
7R$QQZKRZDVDOZD\VWKHUHIRUPH
¢'HDQ

7RP\PRWKHUZKRJDYHPHDQDSSUHFLDWLRQIRU
JRRGZULWLQJDQGWKHDFFRPSDQ\LQJLQWHOOHFWXDO
WRROVZLWKZKLFKWRDWWHPSWWRSURGXFHLW
7R.ULVWHQIRUKHUXQHQGLQJSDWLHQFHORYHDQG
NLQGQHVV
¢$OH[

Download at WoweBook.Com
Download at WoweBook.Com
Table of Contents

Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii

1. Zero to Sixty: Introducing Scala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1


:K\6FDOD" 
,I<RX$UHD-DYD3URJUDPPHUš 
,I<RX$UHD5XE\3\WKRQHWF3URJUDPPHUš 
,QWURGXFLQJ6FDOD 
7KH6HGXFWLRQVRI6FDOD 
,QVWDOOLQJ6FDOD 
)RU0RUH,QIRUPDWLRQ 
$7DVWHRI6FDOD 
$7DVWHRI&RQFXUUHQF\ 
5HFDSDQG:KDW¦V1H[W 

2. Type Less, Do More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23


,Q7KLV&KDSWHU 
6HPLFRORQV 
9DULDEOH'HFODUDWLRQV 
0HWKRG'HFODUDWLRQV 
0HWKRG'HIDXOWDQG1DPHG$UJXPHQWV 6FDOD9HUVLRQ 
1HVWLQJ0HWKRG'HILQLWLRQV 
,QIHUULQJ7\SH,QIRUPDWLRQ 
/LWHUDOV 
,QWHJHU/LWHUDOV 
)ORDWLQJ3RLQW/LWHUDOV 
%RROHDQ/LWHUDOV 
&KDUDFWHU/LWHUDOV 
6WULQJ/LWHUDOV 
6\PERO/LWHUDOV 

vii

Download at WoweBook.Com
7XSOHV 
2SWLRQ6RPHDQG1RQH$YRLGLQJQXOOV 
2UJDQL]LQJ&RGHLQ)LOHVDQG1DPHVSDFHV 
,PSRUWLQJ7\SHVDQG7KHLU0HPEHUV 
,PSRUWVDUH5HODWLYH 
$EVWUDFW7\SHV$QG3DUDPHWHUL]HG7\SHV 
5HVHUYHG:RUGV 
5HFDSDQG:KDW¦V1H[W 

3. Rounding Out the Essentials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53


2SHUDWRU"2SHUDWRU" 
6\QWDFWLF6XJDU 
0HWKRGV:LWKRXW3DUHQWKHVHVDQG'RWV 
3UHFHGHQFH5XOHV 
'RPDLQ6SHFLILF/DQJXDJHV 
6FDODLI6WDWHPHQWV 
6FDODIRU&RPSUHKHQVLRQV 
$'RJ6LPSOH([DPSOH 
)LOWHULQJ 
<LHOGLQJ 
([SDQGHG6FRSH 
2WKHU/RRSLQJ&RQVWUXFWV 
6FDODZKLOH/RRSV 
6FDODGRZKLOH/RRSV 
*HQHUDWRU([SUHVVLRQV 
&RQGLWLRQDO2SHUDWRUV 
3DWWHUQ0DWFKLQJ 
$6LPSOH0DWFK 
9DULDEOHVLQ0DWFKHV 
0DWFKLQJRQ7\SH 
0DWFKLQJRQ6HTXHQFHV 
0DWFKLQJRQ7XSOHV DQG*XDUGV 
0DWFKLQJRQ&DVH&ODVVHV 
0DWFKLQJRQ5HJXODU([SUHVVLRQV 
%LQGLQJ1HVWHG9DULDEOHVLQ&DVH&ODXVHV 
8VLQJWU\FDWFKDQGILQDOO\&ODXVHV 
&RQFOXGLQJ5HPDUNVRQ3DWWHUQ0DWFKLQJ 
(QXPHUDWLRQV 
5HFDSDQG:KDW¦V1H[W 

4. Traits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
,QWURGXFLQJ7UDLWV 
7UDLWV$V0L[LQV 

viii | Table of Contents

Download at WoweBook.Com
6WDFNDEOH7UDLWV 
&RQVWUXFWLQJ7UDLWV 
&ODVVRU7UDLW" 
5HFDSDQG:KDW¦V1H[W 

5. Basic Object-Oriented Programming in Scala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89


&ODVVDQG2EMHFW%DVLFV 
3DUHQW&ODVVHV 
&RQVWUXFWRUVLQ6FDOD 
&DOOLQJ3DUHQW&ODVV&RQVWUXFWRUV 
1HVWHG&ODVVHV 
9LVLELOLW\5XOHV 
3XEOLF9LVLELOLW\ 
3URWHFWHG9LVLELOLW\ 
3ULYDWH9LVLELOLW\ 
6FRSHG3ULYDWHDQG3URWHFWHG9LVLELOLW\ 
)LQDO7KRXJKWVRQ9LVLELOLW\ 
5HFDSDQG:KDW¦V1H[W 

6. Advanced Object-Oriented Programming In Scala . . . . . . . . . . . . . . . . . . . . . . . . . . 111


2YHUULGLQJ0HPEHUVRI&ODVVHVDQG7UDLWV 
$WWHPSWLQJWR2YHUULGHILQDO'HFODUDWLRQV 
2YHUULGLQJ$EVWUDFWDQG&RQFUHWH0HWKRGV 
2YHUULGLQJ$EVWUDFWDQG&RQFUHWH)LHOGV 
2YHUULGLQJ$EVWUDFWDQG&RQFUHWH)LHOGVLQ7UDLWV 
2YHUULGLQJ$EVWUDFWDQG&RQFUHWH)LHOGVLQ&ODVVHV 
2YHUULGLQJ$EVWUDFW7\SHV 
:KHQ$FFHVVRU0HWKRGVDQG)LHOGV$UH,QGLVWLQJXLVKDEOH7KH8QL
IRUP$FFHVV3ULQFLSOH 
&RPSDQLRQ2EMHFWV 
$SSO\ 
8QDSSO\ 
$SSO\DQG8QDSSO\6HTIRU&ROOHFWLRQV 
&RPSDQLRQ2EMHFWVDQG-DYD6WDWLF0HWKRGV 
&DVH&ODVVHV 
6\QWDFWLF6XJDUIRU%LQDU\2SHUDWLRQV 
7KHFRS\0HWKRGLQ6FDOD9HUVLRQ 
&DVH&ODVV,QKHULWDQFH 
(TXDOLW\RI2EMHFWV 
7KHHTXDOV0HWKRG 
7KH DQG 0HWKRGV 
7KHQHDQGHT0HWKRGV 
$UUD\(TXDOLW\DQGWKHVDPH(OHPHQWV0HWKRG 

Table of Contents | ix

Download at WoweBook.Com
5HFDSDQG:KDW¦V1H[W 

7. The Scala Object System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145


7KH3UHGHI2EMHFW 
&ODVVHVDQG2EMHFWV:KHUH$UHWKH6WDWLFV" 
3DFNDJH2EMHFWV 
6HDOHG&ODVV+LHUDUFKLHV 
7KH6FDOD7\SH+LHUDUFK\ 
/LQHDUL]DWLRQRIDQ2EMHFW¦V+LHUDUFK\ 
5HFDSDQG:KDW¦V1H[W 

8. Functional Programming in Scala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165


:KDW,V)XQFWLRQDO3URJUDPPLQJ" 
)XQFWLRQVLQ0DWKHPDWLFV 
9DULDEOHVWKDW$UHQ¦W 
)XQFWLRQDO3URJUDPPLQJLQ6FDOD 
)XQFWLRQ/LWHUDOVDQG&ORVXUHV 
3XULW\,QVLGH9HUVXV2XWVLGH 
5HFXUVLRQ 
7DLO&DOOVDQG7DLO&DOO2SWLPL]DWLRQ 
7UDPSROLQHIRU7DLO&DOOV 
)XQFWLRQDO'DWD6WUXFWXUHV 
/LVWVLQ)XQFWLRQDO3URJUDPPLQJ 
0DSVLQ)XQFWLRQDO3URJUDPPLQJ 
6HWVLQ)XQFWLRQDO3URJUDPPLQJ 
2WKHU'DWD6WUXFWXUHVLQ)XQFWLRQDO3URJUDPPLQJ 
7UDYHUVLQJ0DSSLQJ)LOWHULQJ)ROGLQJDQG5HGXFLQJ 
7UDYHUVDO 
0DSSLQJ 
)LOWHULQJ 
)ROGLQJDQG5HGXFLQJ 
)XQFWLRQDO2SWLRQV 
3DWWHUQ0DWFKLQJ 
3DUWLDO)XQFWLRQV 
&XUU\LQJ 
,PSOLFLWV 
,PSOLFLW&RQYHUVLRQV 
,PSOLFLW)XQFWLRQ3DUDPHWHUV 
)LQDO7KRXJKWVRQ,PSOLFLWV 
&DOOE\1DPH&DOOE\9DOXH 
/D]\9DOV 
5HFDS)XQFWLRQDO&RPSRQHQW$EVWUDFWLRQV 

x | Table of Contents

Download at WoweBook.Com
9. Robust, Scalable Concurrency with Actors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
7KH3UREOHPVRI6KDUHG6\QFKURQL]HG6WDWH 
$FWRUV 
$FWRUVLQ$EVWUDFW 
$FWRUVLQ6FDOD 
6HQGLQJ0HVVDJHVWR$FWRUV 
7KH0DLOER[ 
$FWRUVLQ'HSWK 
(IIHFWLYH$FWRUV 
7UDGLWLRQDO&RQFXUUHQF\LQ6FDOD7KUHDGLQJDQG(YHQWV 
2QH2II7KUHDGV 
8VLQJMDYDXWLOFRQFXUUHQW 
(YHQWV 
5HFDSDQG:KDW¦V1H[W 

10. Herding XML in Scala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211


5HDGLQJ;0/ 
([SORULQJ;0/ 
/RRSLQJDQG0DWFKLQJ;0/ 
:ULWLQJ;0/ 
$5HDO:RUOG([DPSOH 
5HFDSDQG:KDW¦V1H[W 

11. Domain-Specific Languages in Scala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217


,QWHUQDO'6/V 
$3D\UROO,QWHUQDO'6/ 
,QIL[2SHUDWRU1RWDWLRQ 
,PSOLFLW&RQYHUVLRQVDQG8VHU'HILQHG7\SHV 
$SSO\0HWKRGV 
3D\UROO5XOHV'6/,PSOHPHQWDWLRQ 
,QWHUQDO'6/V)LQDO7KRXJKWV 
([WHUQDO'6/VZLWK3DUVHU&RPELQDWRUV 
$ERXW3DUVHU&RPELQDWRUV 
$3D\UROO([WHUQDO'6/ 
$6FDOD,PSOHPHQWDWLRQRIWKH([WHUQDO'6/*UDPPDU 
*HQHUDWLQJ3D\FKHFNVZLWKWKH([WHUQDO'6/ 
,QWHUQDO9HUVXV([WHUQDO'6/V)LQDO7KRXJKWV 
5HFDSDQG:KDW¦V1H[W 

12. The Scala Type System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247


5HIOHFWLQJRQ7\SHV 
8QGHUVWDQGLQJ3DUDPHWHUL]HG7\SHV 
0DQLIHVWV 

Table of Contents | xi

Download at WoweBook.Com
3DUDPHWHUL]HG0HWKRGV 
9DULDQFH8QGHU,QKHULWDQFH 
9DULDQFHRI0XWDEOH7\SHV 
9DULDQFH,Q6FDOD9HUVXV-DYD 
,PSOHPHQWDWLRQ1RWHV 
7\SH%RXQGV 
8SSHU7\SH%RXQGV 
/RZHU7\SH%RXQGV 
$&ORVHU/RRNDW/LVWV 
9LHZVDQG9LHZ%RXQGV 
1RWKLQJDQG1XOO 
8QGHUVWDQGLQJ$EVWUDFW7\SHV 
3DUDPHWHUL]HG7\SHV9HUVXV$EVWUDFW7\SHV 
3DWK'HSHQGHQW7\SHV 
&WKLV 
&VXSHU 
SDWK[ 
9DOXH7\SHV 
7\SH'HVLJQDWRUV 
7XSOHV 
3DUDPHWHUL]HG7\SHV 
$QQRWDWHG7\SHV 
&RPSRXQG7\SHV 
,QIL[7\SHV 
)XQFWLRQ7\SHV 
7\SH3URMHFWLRQV 
6LQJOHWRQ7\SHV 
6HOI7\SH$QQRWDWLRQV 
6WUXFWXUDO7\SHV 
([LVWHQWLDO7\SHV 
,QILQLWH'DWD6WUXFWXUHVDQG/D]LQHVV 
5HFDSDQG:KDW¦V1H[W 

13. Application Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289


$QQRWDWLRQV 
(QXPHUDWLRQV9HUVXV3DWWHUQ0DWFKLQJ 
7KRXJKWV2Q$QQRWDWLRQVDQG(QXPHUDWLRQV 
(QXPHUDWLRQV9HUVXV&DVH&ODVVHVDQG3DWWHUQ0DWFKLQJ 
8VLQJ1XOOV9HUVXV2SWLRQV 
2SWLRQVDQGIRU&RPSUHKHQVLRQV 
([FHSWLRQVDQGWKH$OWHUQDWLYHV 
6FDODEOH$EVWUDFWLRQV 
)LQH*UDLQHG9LVLELOLW\5XOHV 

xii | Table of Contents

Download at WoweBook.Com
0L[LQ&RPSRVLWLRQ 
6HOI7\SH$QQRWDWLRQVDQG$EVWUDFW7\SH0HPEHUV 
(IIHFWLYH'HVLJQRI7UDLWV 
'HVLJQ3DWWHUQV 
7KH9LVLWRU3DWWHUQ$%HWWHU$OWHUQDWLYH 
'HSHQGHQF\,QMHFWLRQLQ6FDOD7KH&DNH3DWWHUQ 
%HWWHU'HVLJQZLWK'HVLJQ%\&RQWUDFW 
5HFDSDQG:KDW¦V1H[W 

14. Scala Tools, Libraries, and IDE Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343


&RPPDQG/LQH7RROV 
VFDODF&RPPDQG/LQH7RRO 
7KHVFDOD&RPPDQG/LQH7RRO 
7KHVFDODSMDYDSDQGMDG&RPPDQG/LQH7RROV 
7KHVFDODGRF&RPPDQG/LQH7RRO 
7KHVED]&RPPDQG/LQH7RRO 
7KHIVF&RPPDQG/LQH7RRO 
%XLOG7RROV 
,QWHJUDWLRQZLWK,'(V 
(FOLSVH 
,QWHOOL- 
1HW%HDQV 
7H[W(GLWRUV 
7HVW'ULYHQ'HYHORSPHQWLQ6FDOD 
6FDOD7HVW 
6SHFV 
6FDOD&KHFN 
2WKHU1RWDEOH6FDOD/LEUDULHVDQG7RROV 
/LIW 
6FDOD] 
6FDOD[ 
0HWD6FDOD 
-DYD5HEHO 
0LVFHOODQHRXV6PDOOHU/LEUDULHV 
-DYD,QWHURSHUDELOLW\ 
-DYDDQG6FDOD*HQHULFV 
8VLQJ6FDOD)XQFWLRQVLQ-DYD 
-DYD%HDQ3URSHUWLHV 
$Q\9DO7\SHVDQG-DYD3ULPLWLYHV 
6FDOD1DPHVLQ-DYD&RGH 
-DYD/LEUDU\,QWHURSHUDELOLW\ 
$VSHFW- 
7KH6SULQJ)UDPHZRUN 

Table of Contents | xiii

Download at WoweBook.Com
7HUUDFRWWD 
+DGRRS 
5HFDSDQG:KDW¦V1H[W 

Appendix: References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387

Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407

xiv | Table of Contents

Download at WoweBook.Com
Foreword

,IWKHUHKDVEHHQDFRPPRQWKHPHWKURXJKRXWP\FDUHHUDVDSURJUDPPHULWKDVEHHQ
WKHTXHVWIRUEHWWHUDEVWUDFWLRQVDQGEHWWHUWRROVWRVXSSRUWWKHFUDIWRIZULWLQJVRIWZDUH
2YHUWKH\HDUV,KDYHFRPHWRYDOXHRQHWUDLWPRUHWKDQDQ\RWKHUFRPSRVDELOLW\,I
RQHFDQZULWHFRGHZLWKJRRGFRPSRVDELOLW\LWXVXDOO\PHDQVWKDWRWKHUWUDLWVZHVRIW
ZDUHGHYHORSHUVYDOXH¢VXFKDVRUWKRJRQDOLW\ORRVHFRXSOLQJDQGKLJKFRKHVLRQ¢
DUHDOUHDG\SUHVHQW,WLVDOOFRQQHFWHG
:KHQ,GLVFRYHUHG6FDODVRPH\HDUVDJRWKHWKLQJWKDWPDGHWKHELJJHVWLPSUHVVLRQ
RQPHZDVLWVFRPSRVDELOLW\7KURXJKVRPHYHU\HOHJDQWGHVLJQFKRLFHVDQGVLPSOH\HW
SRZHUIXO DEVWUDFWLRQV WKDW ZHUH WDNHQ IURP WKH REMHFWRULHQWHG DQG IXQFWLRQDO
SURJUDPPLQJ ZRUOGV 0DUWLQ 2GHUVN\ KDV PDQDJHG WR FUHDWH D ODQJXDJH ZLWK KLJK
FRKHVLRQDQGRUWKRJRQDOGHHSDEVWUDFWLRQVWKDWLQYLWHVFRPSRVDELOLW\LQDOOGLPHQVLRQV
RIVRIWZDUHGHVLJQ6FDODLVWUXO\D6&$ODEOH/$QJXDJHWKDWVFDOHVZLWKXVDJHIURP
VFULSWLQJDOOWKHZD\XSWRODUJHVFDOHHQWHUSULVHDSSOLFDWLRQVDQGPLGGOHZDUH6FDOD
ZDVERUQRXWRIDFDGHPLDEXWLWKDVJURZQLQWRDSUDJPDWLFDQGSUDFWLFDOODQJXDJH
WKDWLVYHU\PXFKUHDG\IRUUHDOZRUOGSURGXFWLRQXVH
:KDWH[FLWHVPHPRVWDERXWWKLVERRNLVWKDWLW¦VVRSUDFWLFDO'HDQDQG$OH[KDYHGRQH
DIDQWDVWLFMREQRWRQO\E\H[SODLQLQJWKHODQJXDJHWKURXJKLQWHUHVWLQJGLVFXVVLRQVDQG
VDPSOHV EXW DOVR E\ SXWWLQJ LW LQ WKH FRQWH[W RI WKH UHDO ZRUOG ,W;V ZULWWHQ IRU WKH
SURJUDPPHUZKRZDQWVWRJHWWKLQJVGRQH,KDGWKHSOHDVXUHRIJHWWLQJWRNQRZ'HDQ
VRPH \HDUV DJR ZKHQ ZH ZHUH ERWK SDUW RI WKH DVSHFWRULHQWHG SURJUDPPLQJ FRP
PXQLW\'HDQKROGVDUDUHPL[RIGHHSDQDO\WLFDODFDGHPLFWKLQNLQJDQGDSUDJPDWLF
JHWWKLQJVGRQHNLQGRIPHQWDOLW\$OH[ZKRP,¦YHKDGWKHSOHDVXUHWRPHHWRQFHLV
OHDGLQJWKH$3,WHDPDW7ZLWWHU,QF$OH[KDVSOD\HGDOHDGLQJUROHLQPRYLQJ7ZLWWHU¦V
FRGHDQGLQIUDVWUXFWXUHWR6FDODPDNLQJLWRQHRQWKHILUVWFRPSDQLHVWRVXFFHVVIXOO\
GHSOR\6FDODLQSURGXFWLRQ

xv

Download at WoweBook.Com
<RXDUHDERXWWROHDUQKRZWRZULWHUHXVDEOHFRPSRQHQWVXVLQJPL[LQDQGIXQFWLRQ
FRPSRVLWLRQKRZWRZULWHFRQFXUUHQWDSSOLFDWLRQVXVLQJ6FDOD¦V$FWRUVKRZWRPDNH
HIIHFWLYHXVHRI6FDOD¦V;0/;3DWKVXSSRUWKRZWRXWLOL]H6FDOD;VULFKIOH[LEOHDQG
H[SUHVVLYH V\QWD[ WR EXLOG 'RPDLQ6SHFLILF /DQJXDJHV KRZ WR HIIHFWLYHO\ WHVW \RXU
6FDODFRGHKRZWRXVH6FDODZLWKSRSXODUIUDPHZRUNVVXFKDV6SULQJ+DGRRSDQG
7HUUDFRWWDDQGPXFKPXFKPRUH(QMR\WKHULGH,VXUHGLG
¢-RQDV%RQpU
,QGHSHQGHQW&RQVXOWDQW6FDODEOH6ROXWLRQV$%
$XJXVW

xvi | Foreword

Download at WoweBook.Com
Preface

3URJUDPPLQJ6FDODLQWURGXFHVDQH[FLWLQJQHZODQJXDJHWKDWRIIHUVDOOWKHEHQHILWVRI
DPRGHUQREMHFWPRGHOIXQFWLRQDOSURJUDPPLQJDQGDQDGYDQFHGW\SHV\VWHP3DFNHG
ZLWKFRGHH[DPSOHVWKLVFRPSUHKHQVLYHERRNWHDFKHV\RXKRZWREHSURGXFWLYHZLWK
6FDODTXLFNO\DQGH[SODLQVZKDWPDNHVWKLVODQJXDJHLGHDOIRUWRGD\¦VVFDODEOHGLV
WULEXWHG FRPSRQHQWEDVHG DSSOLFDWLRQV WKDW VXSSRUW FRQFXUUHQF\ DQG GLVWULEXWLRQ
<RX¦OODOVROHDUQKRZ6FDODWDNHVDGYDQWDJHRIWKHDGYDQFHG-DYD9LUWXDO0DFKLQHDVD
SODWIRUPIRUSURJUDPPLQJODQJXDJHV
/HDUQPRUHDWKWWSSURJUDPPLQJVFDODFRPRUDWWKHERRN¦VFDWDORJSDJH

Welcome to Programming Scala


3URJUDPPLQJODQJXDJHVEHFRPHSRSXODUIRUPDQ\UHDVRQV6RPHWLPHVSURJUDPPHUV
RQDJLYHQSODWIRUPSUHIHUDSDUWLFXODUODQJXDJHRURQHLVLQVWLWXWLRQDOL]HGE\DYHQGRU
0RVW0DF26SURJUDPPHUVXVH2EMHFWLYH&0RVW:LQGRZVSURJUDPPHUVXVH&
DQG1(7ODQJXDJHV0RVWHPEHGGHGV\VWHPVGHYHORSHUVXVH&DQG&
6RPHWLPHVSRSXODULW\GHULYHGIURPWHFKQLFDOPHULWJLYHVZD\WRIDVKLRQDQGIDQDWL
FLVP & -DYD DQG 5XE\ KDYH EHHQ WKH REMHFWV RI IDQDWLFDO GHYRWLRQ DPRQJ
SURJUDPPHUV
6RPHWLPHVDODQJXDJHEHFRPHVSRSXODUEHFDXVHLWILWVWKHQHHGVRILWVHUD-DYDZDV
LQLWLDOO\ VHHQ DV D SHUIHFW ILW IRU EURZVHUEDVHG ULFK FOLHQW DSSOLFDWLRQV 6PDOOWDON
FDSWXUHG WKH HVVHQFH RI REMHFWRULHQWHG SURJUDPPLQJ 223  DV WKDW PRGHO RI SUR
JUDPPLQJHQWHUHGWKHPDLQVWUHDP
7RGD\FRQFXUUHQF\KHWHURJHQHLW\DOZD\VRQVHUYLFHVDQGHYHUVKULQNLQJGHYHORS
PHQWVFKHGXOHVDUHGULYLQJLQWHUHVWLQIXQFWLRQDOSURJUDPPLQJ )3 ,WDSSHDUVWKDWWKH
GRPLQDQFHRIREMHFWRULHQWHGSURJUDPPLQJPD\EHRYHU0L[LQJSDUDGLJPVLVEHFRP
LQJSRSXODUHYHQQHFHVVDU\
:HJUDYLWDWHGWR6FDODIURPRWKHUODQJXDJHVEHFDXVH6FDODHPERGLHVPDQ\RIWKHRS
WLPDOTXDOLWLHVZHZDQWLQDJHQHUDOSXUSRVHSURJUDPPLQJODQJXDJHIRUWKHNLQGVRI
DSSOLFDWLRQVZHEXLOGWRGD\UHOLDEOHKLJKSHUIRUPDQFHKLJKO\FRQFXUUHQW,QWHUQHWDQG
HQWHUSULVHDSSOLFDWLRQV

xvii

Download at WoweBook.Com
6FDODLVDPXOWLSDUDGLJPODQJXDJHVXSSRUWLQJERWKREMHFWRULHQWHGDQGIXQFWLRQDO
SURJUDPPLQJDSSURDFKHV6FDODLVVFDODEOHVXLWDEOHIRUHYHU\WKLQJIURPVKRUWVFULSWV
XSWRODUJHVFDOHFRPSRQHQWEDVHGDSSOLFDWLRQV6FDODLVVRSKLVWLFDWHGLQFRUSRUDWLQJ
VWDWHRIWKHDUWLGHDVIURPWKHKDOOVRIFRPSXWHUVFLHQFHGHSDUWPHQWVZRUOGZLGH<HW
6FDODLVSUDFWLFDO,WVFUHDWRU0DUWLQ2GHUVN\SDUWLFLSDWHGLQWKHGHYHORSPHQWRI-DYD
IRU\HDUVDQGXQGHUVWDQGVWKHQHHGVRISURIHVVLRQDOGHYHORSHUV
%RWKRIXVZHUHVHGXFHGE\6FDODE\LWVFRQFLVHHOHJDQWDQGH[SUHVVLYHV\QWD[DQGE\
WKHEUHDGWKRIWRROVLWSXWDWRXUGLVSRVDO,QWKLVERRNZHVWULYHWRGHPRQVWUDWHZK\
DOOWKHVHTXDOLWLHVPDNH6FDODDFRPSHOOLQJDQGLQGLVSHQVDEOHSURJUDPPLQJODQJXDJH
,I\RXDUHDQH[SHULHQFHGGHYHORSHUZKRZDQWVDIDVWWKRURXJKLQWURGXFWLRQWR6FDOD
WKLVERRNLVIRU\RX<RXPD\EHHYDOXDWLQJ6FDODDVDUHSODFHPHQWIRURUFRPSOHPHQW
WR\RXUFXUUHQWODQJXDJHV0D\EH\RXKDYHDOUHDG\GHFLGHGWRXVH6FDODDQG\RXQHHG
WR OHDUQ LWV IHDWXUHV DQG KRZ WR XVH LW ZHOO (LWKHU ZD\ ZH KRSH WR LOOXPLQDWH WKLV
SRZHUIXOODQJXDJHIRU\RXLQDQDFFHVVLEOHZD\
:HDVVXPHWKDW\RXDUHZHOOYHUVHGLQREMHFWRULHQWHGSURJUDPPLQJEXWZHGRQ¦W
DVVXPHWKDW\RXKDYHSULRUH[SRVXUHWRIXQFWLRQDOSURJUDPPLQJ:HDVVXPHWKDW\RX
DUHH[SHULHQFHGLQRQHRUPRUHRWKHUSURJUDPPLQJODQJXDJHV:HGUDZSDUDOOHOVWR
IHDWXUHVLQ-DYD&5XE\DQGRWKHUODQJXDJHV,I\RXNQRZDQ\RIWKHVHODQJXDJHV
ZH¦OOSRLQWRXWVLPLODUIHDWXUHVLQ6FDODDVZHOODVPDQ\IHDWXUHVWKDWDUHQHZ
:KHWKHU\RXFRPHIURPDQREMHFWRULHQWHGRUIXQFWLRQDOSURJUDPPLQJEDFNJURXQG
\RXZLOOVHHKRZ6FDODHOHJDQWO\FRPELQHVERWKSDUDGLJPVGHPRQVWUDWLQJWKHLUFRP
SOHPHQWDU\QDWXUH%DVHGRQPDQ\H[DPSOHV\RXZLOOXQGHUVWDQGKRZDQGZKHQWR
DSSO\223DQG)3WHFKQLTXHVWRPDQ\GLIIHUHQWGHVLJQSUREOHPV
,QWKHHQGZHKRSHWKDW\RXWRRZLOOEHVHGXFHGE\6FDOD(YHQLI6FDODGRHVQRWHQG
XSEHFRPLQJ\RXUGD\WRGD\ODQJXDJHZHKRSH\RXZLOOJDLQLQVLJKWVWKDW\RXFDQ
DSSO\UHJDUGOHVVRIZKLFKODQJXDJH\RXDUHXVLQJ

Conventions Used in This Book


7KHIROORZLQJW\SRJUDSKLFDOFRQYHQWLRQVDUHXVHGLQWKLVERRN
,WDOLF
,QGLFDWHVQHZWHUPV85/VHPDLODGGUHVVHVILOHQDPHVDQGILOHH[WHQVLRQV0DQ\
LWDOLFL]HGWHUPVDUHGHILQHGLQWKH*ORVVDU\RQSDJH
Constant width
8VHGIRUSURJUDPOLVWLQJVDVZHOODVZLWKLQSDUDJUDSKVWRUHIHUWRSURJUDPHOHPHQWV
VXFKDVYDULDEOHRUIXQFWLRQQDPHVGDWDEDVHVGDWDW\SHVHQYLURQPHQWYDULDEOHV
VWDWHPHQWVDQGNH\ZRUGV
Constant width bold
6KRZVFRPPDQGVRURWKHUWH[WWKDWVKRXOGEHW\SHGOLWHUDOO\E\WKHXVHU

xviii | Preface

Download at WoweBook.Com
Constant width italic
6KRZVWH[WWKDWVKRXOGEHUHSODFHGZLWKXVHUVXSSOLHGYDOXHVRUE\YDOXHVGHWHU
PLQHGE\FRQWH[W

7KLVLFRQVLJQLILHVDWLSVXJJHVWLRQRUJHQHUDOQRWH

7KLVLFRQLQGLFDWHVDZDUQLQJRUFDXWLRQ

Using Code Examples


7KLVERRNLVKHUHWRKHOS\RXJHW\RXUMREGRQH,QJHQHUDO\RXPD\XVHWKHFRGHLQ
WKLVERRNLQ\RXUSURJUDPVDQGGRFXPHQWDWLRQ<RXGRQRWQHHGWRFRQWDFWXVIRU
SHUPLVVLRQXQOHVV\RX¦UHUHSURGXFLQJDVLJQLILFDQWSRUWLRQRIWKHFRGH)RUH[DPSOH
ZULWLQJDSURJUDPWKDWXVHVVHYHUDOFKXQNVRIFRGHIURPWKLVERRNGRHVQRWUHTXLUH
SHUPLVVLRQ6HOOLQJRUGLVWULEXWLQJD&'520RIH[DPSOHVIURP2¦5HLOO\ERRNVGRHV
UHTXLUH SHUPLVVLRQ $QVZHULQJ D TXHVWLRQ E\ FLWLQJ WKLV ERRN DQG TXRWLQJ H[DPSOH
FRGHGRHVQRWUHTXLUHSHUPLVVLRQ,QFRUSRUDWLQJDVLJQLILFDQWDPRXQWRIH[DPSOHFRGH
IURPWKLVERRNLQWR\RXUSURGXFW¦VGRFXPHQWDWLRQGRHVUHTXLUHSHUPLVVLRQ
:HDSSUHFLDWHEXWGRQRWUHTXLUHDWWULEXWLRQ$QDWWULEXWLRQXVXDOO\LQFOXGHVWKHWLWOH
DXWKRUSXEOLVKHUDQG,6%1)RUH[DPSOH£3URJUDPPLQJ6FDODE\'HDQ:DPSOHUDQG
$OH[3D\QH&RS\ULJKW'HDQ:DPSOHUDQG$OH[3D\QH¤
,I\RXIHHO\RXUXVHRIFRGHH[DPSOHVIDOOVRXWVLGHIDLUXVHRUWKHSHUPLVVLRQJLYHQDERYH
IHHOIUHHWRFRQWDFWXVDWSHUPLVVLRQV#RUHLOO\FRP

Getting the Code Examples


<RX FDQ GRZQORDG WKH FRGH H[DPSOHV IURP KWWSH[DPSOHVRUHLOO\FRP
8Q]LSWKHILOHVWRDFRQYHQLHQWORFDWLRQ6HHWKH5($'0(W[WILOHLQ
WKHGLVWULEXWLRQIRULQVWUXFWLRQVRQEXLOGLQJDQGXVLQJWKHH[DPSOHV
6RPHRIWKHH[DPSOHILOHVFDQEHUXQDVVFULSWVXVLQJWKHscalaFRPPDQG2WKHUVPXVW
EHFRPSLOHGLQWRFODVVILOHV6RPHILOHVFRQWDLQGHOLEHUDWHHUURUVDQGZRQ¦WFRPSLOH:H
KDYHDGRSWHGDILOHQDPLQJFRQYHQWLRQWRLQGLFDWHHDFKRIWKHVHFDVHVDOWKRXJKDV\RX
OHDUQ6FDODLWVKRXOGEHFRPHREYLRXVIURPWKHFRQWHQWVRIWKHILOHVLQPRVWFDVHV
VFULSWVFDOD
)LOHVWKDWHQGLQVFULSWVFDODFDQEHUXQRQDFRPPDQGOLQHXVLQJscalaHJscala
foo-script.scala <RX FDQ DOVR VWDUW scala LQ WKH LQWHUSUHWHU PRGH ZKHQ \RX

Preface | xix

Download at WoweBook.Com
GRQ¦WVSHFLI\DVFULSWILOH DQGORDGDQ\VFULSWILOHLQWKHLQWHUSUHWHUXVLQJWKH:load
filenameFRPPDQG
ZRQWFRPSLOHVFDOD
)LOHVWKDWHQGLQZRQWFRPSLOHVFDODFRQWDLQGHOLEHUDWHHUURUVWKDWZLOOFDXVHWKHP
WRIDLOWRFRPSLOH:HXVHWKLVQDPLQJFRQYHQWLRQDORQJZLWKRQHRUPRUHHP
EHGGHGFRPPHQWVDERXWWKHHUURUVVRLWZLOOEHFOHDUWKDWWKH\DUHLQYDOLG$OVR
WKHVHILOHVDUHVNLSSHGE\WKHEXLOGSURFHVVIRUWKHH[DPSOHV
VDNHVFDOD
)LOHVQDPHGVDNHVFDODDUHXVHGE\RXUEXLOGWRROFDOOHG sake7KH5($'0(W[W
ILOHGHVFULEHVWKLVWRRO
VFDOD
$OORWKHU6FDODILOHVPXVWEHFRPSLOHGXVLQJ scalac,QWKHGLVWULEXWLRQWKH\DUH
XVHGHLWKHUE\RWKHUFRPSLOHGRUVFULSWILOHVVXFKDVWHVWVQRWDOORIZKLFKDUHOLVWHG
LQWKLVERRN

Safari® Books Online


6DIDUL%RRNV2QOLQHLVDQRQGHPDQGGLJLWDOOLEUDU\WKDWOHWV\RXHDVLO\
VHDUFKRYHUWHFKQRORJ\DQGFUHDWLYHUHIHUHQFHERRNVDQGYLGHRVWR
ILQGWKHDQVZHUV\RXQHHGTXLFNO\
:LWKDVXEVFULSWLRQ\RXFDQUHDGDQ\SDJHDQGZDWFKDQ\YLGHRIURPRXUOLEUDU\RQOLQH
5HDGERRNVRQ\RXUFHOOSKRQHDQGPRELOHGHYLFHV$FFHVVQHZWLWOHVEHIRUHWKH\DUH
DYDLODEOHIRUSULQWDQGJHWH[FOXVLYHDFFHVVWRPDQXVFULSWVLQGHYHORSPHQWDQGSRVW
IHHGEDFNIRUWKHDXWKRUV&RS\DQGSDVWHFRGHVDPSOHVRUJDQL]H\RXUIDYRULWHVGRZQ
ORDGFKDSWHUVERRNPDUNNH\VHFWLRQVFUHDWHQRWHVSULQWRXWSDJHVDQGEHQHILWIURP
WRQVRIRWKHUWLPHVDYLQJIHDWXUHV
2¦5HLOO\0HGLDKDVXSORDGHGWKLVERRNWRWKH6DIDUL%RRNV2QOLQHVHUYLFH7RKDYHIXOO
GLJLWDODFFHVVWRWKLVERRNDQGRWKHUVRQVLPLODUWRSLFVIURP2¦5HLOO\DQGRWKHUSXE
OLVKHUVVLJQXSIRUIUHHDWKWWSP\VDIDULERRNVRQOLQHFRP

How to Contact Us
3OHDVHDGGUHVVFRPPHQWVDQGTXHVWLRQVFRQFHUQLQJWKLVERRNWRWKHSXEOLVKHU
2¦5HLOO\0HGLD,QF
*UDYHQVWHLQ+LJKZD\1RUWK
6HEDVWRSRO&$
 LQWKH8QLWHG6WDWHVRU&DQDGD

xx | Preface

Download at WoweBook.Com
 LQWHUQDWLRQDORUORFDO
 ID[
:HKDYHDZHESDJHIRUWKLVERRNZKHUHZHOLVWHUUDWDH[DPSOHVDQGDQ\DGGLWLRQDO
LQIRUPDWLRQ<RXFDQDFFHVVWKLVSDJHDW
KWWSRUHLOO\FRPFDWDORJ
7RFRPPHQWRUDVNWHFKQLFDOTXHVWLRQVDERXWWKLVERRNVHQGHPDLOWR
ERRNTXHVWLRQV#RUHLOO\FRP
)RU PRUH LQIRUPDWLRQ DERXW RXU ERRNV FRQIHUHQFHV 5HVRXUFH &HQWHUV DQG WKH
2¦5HLOO\1HWZRUNVHHRXUZHEVLWHDW
KWWSRUHLOO\FRP

Acknowledgments
$VZHGHYHORSHGWKLVERRNPDQ\SHRSOHUHDGHDUO\GUDIWVDQGVXJJHVWHGQXPHURXV
LPSURYHPHQWVWRWKHWH[WIRUZKLFKZHDUHHWHUQDOO\JUDWHIXO:HDUHHVSHFLDOO\JUDWHIXO
WR6WHYH-HQVHQ5DPQLYDV/DGGDG0DUFHO0ROLQD%LOO9HQQHUVDQG-RQDV%RQpUIRU
WKHLUH[WHQVLYHIHHGEDFN
0XFKRIWKHIHHGEDFNZHUHFHLYHGFDPHWKURXJKWKH6DIDUL5RXJK&XWVUHOHDVHVDQG
WKH RQOLQH HGLWLRQ DYDLODEOH DW KWWSSURJUDPPLQJVFDODFRP :H DUH JUDWHIXO IRU WKH
IHHGEDFNSURYLGHGE\ LQQRSDUWLFXODURUGHU ,XOLDQ'UDJRV1LNRODM/LQGEHUJ0DWW
+HOOLJH'DYLG9\GUD5LFN\&ODUNVRQ$OH[&UXLVH-RVK&URQHPH\HU7\OHU-HQQLQJV
$ODQ6XS\QXN7RQ\+LOOHUVRQ5RJHU9DXJKQ$UEL6RRND]LDQ%UXFH/HLGO'DQLHO
6REUDO(GHU$QGUHV$YLOD0DUHN.XELFD+HQULN+XWWXQHQ%KDVNDU0DGGDOD*HG
%\UQH'HUHN0DKDU*HRIIUH\:LVHPDQ3HWHU5DZVWKRUQH*HRIIUH\:LVHPDQ-RH
%RZEHHU $OH[DQGHU %DWWLVWL 5RE 'LFNHQV 7LP 0DF(DFKHUQ -DVRQ +DUULV 6WHYHQ
*UDG\%RE)ROOHN$ULHO2UWL]3DUWK0DOZDQNDU5HLG+RFKVWHGOHU-DVRQ=DXJJ-RQ
+DQVRQ 0DULR *OHLFKPDQQ 'DYLG *DWHV =HI +HPHO 0LFKDHO <HH 0DULXV .UHLV
0DUWLQ6VVNUDXW-DYLHU9HJDV7RELDV+DXWK)UDQFHVFR%RFKLFFKLR6WHSKHQ'XQFDQ
-U 3DWULN 'XGLWV -DQ 1LHKXVPDQQ %LOO %XUGLFN 'DYLG +ROEURRN 6KDORP 'HLWFK
-HVSHU 1RUGHQEHUJ (VD /DLQH *OHE )UDQN 6LPRQ $QGHUVVRQ 3DWULN 'XGLWV &KULV
/HZLV-XOLDQ+RZDUWK'LUN.X]HPF]DN+HQUL*HUULWV-RKQ+HLQW]6WXDUW5RHEXFN
DQG-XQJKR.LP0DQ\RWKHUUHDGHUVIRUZKRPZHRQO\KDYHXVHUQDPHVDOVRSURYLGHG
IHHGEDFN:HZLVKWRWKDQN=DFN-RVK*HZLOOLJHUVDEFRDWHVEUDGWHWRSMFMPNOHLQW
GDQGR\RQ$UHNUXHDFDQJLDQRYNHOPDQEU\DQO-HIIPED[WHUSMEN[HQKLSHU
WUDFNHUFWUDQ5DP5FRG\1RODQ-RVKXD$MD\-RHDQGDQRQ\PRXVFRQWULEXWRUV
:HDSRORJL]HLIZHKDYHRYHUORRNHGDQ\RQH
2XUHGLWRU0LNH/RXNLGHVNQRZVKRZWRSXVKDQGSURGJHQWOH+H¦VEHHQDJUHDWKHOS
WKURXJKRXW WKLV FUD]\ SURFHVV 0DQ\ RWKHU SHRSOH DW 2¦5HLOO\ ZHUH DOZD\V WKHUH WR
DQVZHURXUTXHVWLRQVDQGKHOSXVPRYHIRUZDUG

Preface | xxi

Download at WoweBook.Com
:HWKDQN-RQDV%RQpUIRUZULWLQJWKH)RUHZRUGIRUWKHERRN-RQDVLVDORQJWLPHIULHQG
DQGFROODERUDWRUIURPWKHDVSHFWRULHQWHGSURJUDPPLQJ $23 FRPPXQLW\)RU\HDUV
KHKDVGRQHSLRQHHULQJZRUNLQWKH-DYDFRPPXQLW\1RZKHLVDSSO\LQJKLVHQHUJLHV
WRSURPRWLQJ6FDODDQGJURZLQJWKDWFRPPXQLW\
%LOO9HQQHUVJUDFLRXVO\SURYLGHGWKHTXRWHRQWKHEDFNFRYHU7KHILUVWSXEOLVKHGERRN
RQ6FDOD3URJUDPPLQJLQ6FDOD $UWLPD WKDWKHFRZURWHZLWK0DUWLQ2GHUVN\DQG
/H[6SRRQLVLQGLVSHQVDEOHIRUWKH6FDODGHYHORSHU%LOOKDVDOVRFUHDWHGWKHZRQGHUIXO
6FDOD7HVWOLEUDU\
:HKDYHOHDUQHGDORWIURPIHOORZGHYHORSHUVDURXQGWKHZRUOG%HVLGHV-RQDVDQG%LOO
'HEDVLVK *KRVK -DPHV ,U\ 'DQLHO 6SLHZDN 'DYLG 3ROODFN 3DXO 6QLYHO\ 2OD %LQL
'DQLHO6REUDO-RVK6XHUHWK5REH\3RLQWHU1DWKDQ+DPEOHQ-RUJH2UWL]DQGRWKHUV
KDYHLOOXPLQDWHGGDUNFRUQHUVZLWKWKHLUEORJHQWULHVIRUXPGLVFXVVLRQVDQGSHUVRQDO
FRQYHUVDWLRQV
'HDQWKDQNVKLVFROOHDJXHVDW2EMHFW0HQWRUDQGVHYHUDOGHYHORSHUVDWFOLHQWVLWHVIRU
PDQ\VWLPXODWLQJGLVFXVVLRQVRQODQJXDJHVVRIWZDUHGHVLJQDQGWKHSUDJPDWLFLVVXHV
IDFLQJ GHYHORSHUV LQ LQGXVWU\ 7KH PHPEHUV RI WKH &KLFDJR $UHD 6FDOD (QWKXVLDVWV
&$6( JURXSKDYHDOVREHHQDVRXUFHRIYDOXDEOHIHHGEDFNDQGLQVSLUDWLRQ
$OH[ WKDQNV KLV FROOHDJXHV DW 7ZLWWHU IRU WKHLU HQFRXUDJHPHQW DQG VXSHUE ZRUN LQ
GHPRQVWUDWLQJ6FDOD¦VHIIHFWLYHQHVVDVDODQJXDJH+HDOVRWKDQNVWKH%D\$UHD6FDOD
(QWKXVLDVWV %$6( IRUWKHLUPRWLYDWLRQDQGFRPPXQLW\
0RVWRIDOOZHWKDQN0DUWLQ2GHUVN\DQGKLVWHDPIRUFUHDWLQJ6FDOD

xxii | Preface

Download at WoweBook.Com
CHAPTER 1
Zero to Sixty: Introducing Scala

Why Scala?
7RGD\¦VHQWHUSULVHDQG,QWHUQHWDSSOLFDWLRQVPXVWEDODQFHDQXPEHURIFRQFHUQV7KH\
PXVWEHLPSOHPHQWHGTXLFNO\DQGUHOLDEO\1HZIHDWXUHVPXVWEHDGGHGLQVKRUWLQ
FUHPHQWDOF\FOHV%H\RQGVLPSO\SURYLGLQJEXVLQHVVORJLFDSSOLFDWLRQVPXVWVXSSRUW
VHFXUHDFFHVVSHUVLVWHQFHRIGDWDWUDQVDFWLRQDOEHKDYLRUDQGRWKHUDGYDQFHGIHDWXUHV
$SSOLFDWLRQV PXVW EH KLJKO\ DYDLODEOH DQG VFDODEOH UHTXLULQJ GHVLJQV WKDW VXSSRUW
FRQFXUUHQF\DQGGLVWULEXWLRQ$SSOLFDWLRQVDUHQHWZRUNHGDQGSURYLGHLQWHUIDFHVIRU
ERWKSHRSOHDQGRWKHUDSSOLFDWLRQVWRXVH
7RPHHWWKHVHFKDOOHQJHVPDQ\GHYHORSHUVDUHORRNLQJIRUQHZODQJXDJHVDQGWRROV
9HQHUDEOHVWDQGE\VOLNH-DYD&DQG&DUHQRORQJHURSWLPDOIRUGHYHORSLQJWKH
QH[WJHQHUDWLRQRIDSSOLFDWLRQV

If You Are a Java Programmer…


-DYDZDVRIILFLDOO\LQWURGXFHGE\6XQ0LFURV\VWHPVLQ0D\RIDWWKHDGYHQWRI
ZLGHVSUHDGLQWHUHVWLQWKH,QWHUQHW-DYDZDVLPPHGLDWHO\KDLOHGDVDQLGHDOODQJXDJH
IRU ZULWLQJ EURZVHUEDVHG DSSOHWV ZKHUH D VHFXUH SRUWDEOH DQG GHYHORSHUIULHQGO\
DSSOLFDWLRQ ODQJXDJH ZDV QHHGHG 7KH UHLJQLQJ ODQJXDJH RI WKH GD\ & ZDV QRW
VXLWDEOHIRUWKLVGRPDLQ
7RGD\-DYDLVPRUHRIWHQXVHGIRUVHUYHUVLGHDSSOLFDWLRQV,WLVRQHRIWKHPRVWSRSXODU
ODQJXDJHVLQXVHIRUWKHGHYHORSPHQWRIZHEDQGHQWHUSULVHDSSOLFDWLRQV
+RZHYHU-DYDZDVDFKLOGRILWVWLPH1RZLWVKRZVLWVDJH,Q-DYDSURYLGHGD
V\QWD[VLPLODUHQRXJKWR&WRHQWLFH&GHYHORSHUVZKLOHDYRLGLQJPDQ\RIWKDW
ODQJXDJH¦VGHILFLHQFLHVDQG£VKDUSHGJHV¤-DYDDGRSWHGWKHPRVWXVHIXOLGHDVIRUWKH
GHYHORSPHQWSUREOHPVRILWVHUDVXFKDVREMHFWRULHQWHGSURJUDPPLQJ 223 ZKLOH
GLVFDUGLQJPRUHWURXEOHVRPHWHFKQLTXHVVXFKDVPDQXDOPHPRU\PDQDJHPHQW7KHVH
GHVLJQFKRLFHVVWUXFNDQH[FHOOHQWEDODQFHWKDWPLQLPL]HGFRPSOH[LW\DQGPD[LPL]HG
GHYHORSHUSURGXFWLYLW\ZKLOHWUDGLQJRIISHUIRUPDQFHFRPSDUHGWRQDWLYHO\FRPSLOHG

Download at WoweBook.Com
FRGH :KLOH -DYD KDV HYROYHG VLQFH LWV ELUWK PDQ\ SHRSOH EHOLHYH LW KDV JURZQ WRR
FRPSOH[ZLWKRXWDGHTXDWHO\DGGUHVVLQJVRPHQHZHUGHYHORSPHQWFKDOOHQJHV
'HYHORSHUVZDQWODQJXDJHVWKDWDUHPRUHVXFFLQFWDQGIOH[LEOHWRLPSURYHWKHLUSUR
GXFWLYLW\7KLVLVRQHUHDVRQZK\VRFDOOHGVFULSWLQJODQJXDJHVOLNH5XE\DQG3\WKRQ
KDYHEHFRPHPRUHSRSXODUUHFHQWO\
7KHQHYHUHQGLQJQHHGWRVFDOHLVGULYLQJDUFKLWHFWXUHVWRZDUGSHUYDVLYHFRQFXUUHQF\
+RZHYHU-DYD¦VFRQFXUUHQF\PRGHOZKLFKLVEDVHGRQV\QFKURQL]HGDFFHVVWRVKDUHG
PXWDEOHVWDWHUHVXOWVLQFRPSOH[DQGHUURUSURQHSURJUDPV
:KLOHWKH-DYDODQJXDJHLVVKRZLQJLWVDJHWKH-DYD9LUWXDO0DFKLQH -90 RQZKLFK
LWUXQVFRQWLQXHVWRVKLQH7KHRSWLPL]DWLRQVSHUIRUPHGE\WRGD\¦V-90DUHH[WUDRU
GLQDU\DOORZLQJE\WHFRGHWRRXWSHUIRUPQDWLYHO\FRPSLOHGFRGHLQPDQ\FDVHV7RGD\
PDQ\GHYHORSHUVEHOLHYHWKDWXVLQJWKH-90ZLWKQHZODQJXDJHVLVWKHSDWKIRUZDUG
6XQLVHPEUDFLQJWKLVWUHQGE\HPSOR\LQJPDQ\RIWKHOHDGGHYHORSHUVRI-5XE\DQG
-\WKRQZKLFKDUH-90SRUWVRI5XE\DQG3\WKRQUHVSHFWLYHO\
7KHDSSHDORI6FDODIRUWKH-DYDGHYHORSHULVWKDWLWJLYHV\RXDQHZHUPRUHPRGHUQ
ODQJXDJH ZKLOH OHYHUDJLQJ WKH -90¦V DPD]LQJ SHUIRUPDQFH DQG WKH ZHDOWK RI -DYD
OLEUDULHVWKDWKDYHEHHQGHYHORSHGIRURYHUDGHFDGH

If You Are a Ruby, Python, etc. Programmer…


'\QDPLFDOO\ W\SHG ODQJXDJHV OLNH 5XE\ 3\WKRQ *URRY\ -DYD6FULSW DQG 6PDOOWDON
RIIHUYHU\KLJKSURGXFWLYLW\GXHWRWKHLUIOH[LELOLW\SRZHUIXOPHWDSURJUDPPLQJDQG
HOHJDQFH

Statically Typed Versus Dynamically Typed Languages


2QHRIWKHIXQGDPHQWDOODQJXDJHGHVLJQFKRLFHVLVVWDWLFYHUVXVG\QDPLFW\SLQJ
7KHZRUG£W\SLQJ¤LVXVHGLQPDQ\FRQWH[WVLQVRIWZDUH7KHIROORZLQJLVD£SODXVLEOH¤
GHILQLWLRQWKDWLVXVHIXOIRURXUSXUSRVHV
$W\SHV\VWHPLVDWUDFWDEOHV\QWDFWLFPHWKRGIRUSUHVHUYLQJWKHDEVHQFHRIFHUWDLQ
SURJUDPEHKDYLRUVE\FODVVLI\LQJSKUDVHVDFFRUGLQJWRWKHNLQGVRIYDOXHVWKH\
FRPSXWH
¢%HQMDPLQ&3LHUFH7\SHVDQG3URJUDPPLQJ/DQJXDJHV 0,73UHVV
1RWHWKHHPSKDVLVRQKRZDW\SHV\VWHPDOORZVUHDVRQLQJDERXWZKDWDV\VWHPH[
FOXGHVIURPKDSSHQLQJ7KDW¦VJHQHUDOO\HDVLHUWKDQWU\LQJWRGHWHUPLQHWKHVHWRIDOO
DOORZHGSRVVLELOLWLHV$W\SHV\VWHPLVXVHGWRFDWFKYDULRXVHUURUVOLNHXQVXSSRUWHG
RSHUDWLRQVRQSDUWLFXODUGDWDVWUXFWXUHVDWWHPSWLQJWRFRPELQHGDWDLQDQXQGHILQHG
ZD\ HJWU\LQJWRDGGDQLQWHJHUWRDVWULQJ EUHDNLQJDEVWUDFWLRQVHWF
,QIRUPDOO\LQVWDWLFW\SLQJDYDULDEOHLVERXQGWRDSDUWLFXODUW\SHIRULWVOLIHWLPH,WV
W\SHFDQ¦WEHFKDQJHGDQGLWFDQRQO\UHIHUHQFHW\SHFRPSDWLEOHLQVWDQFHV7KDWLVLID
YDULDEOHUHIHUVWRDYDOXHRIW\SH A\RXFDQ¦WDVVLJQDYDOXHRIDGLIIHUHQWW\SH BWRLW
XQOHVVBLVDVXEW\SHRIAIRUVRPHUHDVRQDEOHGHILQLWLRQRI£VXEW\SH¤

2 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
,QG\QDPLFW\SLQJWKHW\SHLVERXQGWRWKHYDOXHQRWWKHYDULDEOH6RDYDULDEOHPLJKW
UHIHUWRDYDOXHRIW\SHAWKHQEHUHDVVLJQHGODWHUWRDYDOXHRIDQXQUHODWHGW\SHX
7KHWHUPG\QDPLFDOO\W\SHGLVXVHGEHFDXVHWKHW\SHRIDYDULDEOHLVHYDOXDWHGZKHQLW
LVXVHGGXULQJUXQWLPHZKLOHLQDVWDWLFDOO\W\SHGODQJXDJHWKHW\SHLVHYDOXDWHGDWSDUVH
WLPH
7KLVPD\VHHPOLNHDVPDOOGLVWLQFWLRQEXWLWKDVDSHUYDVLYHLPSDFWRQWKHSKLORVRSK\
GHVLJQDQGLPSOHPHQWDWLRQRIDODQJXDJH:H¦OOH[SORUHVRPHRIWKHVHLPSOLFDWLRQVDV
ZHJRWKURXJKWKHERRN
6FDODDQG-DYDDUHVWDWLFDOO\W\SHGODQJXDJHVZKHUHDV5XE\3\WKRQ*URRY\-DYD
6FULSWDQG6PDOOWDONDUHG\QDPLFDOO\W\SHGODQJXDJHV
)RUVLPSOLFLW\ZHZLOORIWHQXVHWKHWHUPV VWDWLFODQJXDJHDQGG\QDPLFODQJXDJHDV
VKRUWKDQGVIRUVWDWLFDOO\W\SHGODQJXDJHDQGG\QDPLFDOO\W\SHGODQJXDJHUHVSHFWLYHO\
$QRUWKRJRQDOGHVLJQFRQVLGHUDWLRQLVVWURQJYHUVXVZHDNW\SLQJ,QVWURQJW\SLQJHYHU\
YDULDEOH IRUVWDWLFW\SLQJ RUYDOXH IRUG\QDPLFW\SLQJ PXVWKDYHDQXQDPELJXRXV
W\SH,QZHDNW\SLQJDVSHFLILFW\SHLVQRWUHTXLUHG:KLOHPRVWODQJXDJHVDOORZVRPH
PL[WXUHRIVWURQJYHUVXVZHDNW\SLQJ6FDOD-DYDDQG5XE\DUHSUHGRPLQDQWO\VWURQJO\
W\SHGODQJXDJHV6RPHODQJXDJHVOLNH&DQG3HUODUHPRUHZHDNO\W\SHG

'HVSLWHWKHLUSURGXFWLYLW\DGYDQWDJHVG\QDPLFODQJXDJHVPD\QRWEHWKHEHVWFKRLFHV
IRUDOODSSOLFDWLRQVSDUWLFXODUO\IRUYHU\ODUJHFRGHEDVHVDQGKLJKSHUIRUPDQFHDSSOL
FDWLRQV7KHUHLVDORQJVWDQGLQJVSLULWHGGHEDWHLQWKHSURJUDPPLQJFRPPXQLW\DERXW
WKHUHODWLYHPHULWVRIG\QDPLFYHUVXVVWDWLFW\SLQJ0DQ\RIWKHSRLQWVRIFRPSDULVRQ
DUHVRPHZKDWVXEMHFWLYH:HZRQ¦WJRWKURXJKDOOWKHDUJXPHQWVKHUHEXWZHZLOORIIHU
DIHZWKRXJKWVIRUFRQVLGHUDWLRQ
2SWLPL]LQJWKHSHUIRUPDQFHRIDG\QDPLFODQJXDJHLVPRUHFKDOOHQJLQJWKDQIRUDVWDWLF
ODQJXDJH,QDVWDWLFODQJXDJHRSWLPL]HUVFDQH[SORLWWKHW\SHLQIRUPDWLRQWRPDNH
GHFLVLRQV ,Q D G\QDPLF ODQJXDJH IHZHU VXFK FOXHV DUH DYDLODEOH IRU WKH RSWLPL]HU
PDNLQJRSWLPL]DWLRQFKRLFHVKDUGHU:KLOHUHFHQWDGYDQFHPHQWVLQRSWLPL]DWLRQVIRU
G\QDPLFODQJXDJHVDUHSURPLVLQJWKH\ODJEHKLQGWKHVWDWHRIWKHDUWIRUVWDWLFODQ
JXDJHV6RLI\RXUHTXLUHYHU\KLJKSHUIRUPDQFHVWDWLFODQJXDJHVDUHSUREDEO\DVDIHU
FKRLFH
6WDWLF ODQJXDJHV FDQ DOVR EHQHILW WKH GHYHORSPHQW SURFHVV ,QWHJUDWHG GHYHORSPHQW
HQYLURQPHQW ,'(  IHDWXUHV OLNH DXWRFRPSOHWLRQ VRPHWLPHV FDOOHG FRGH VHQVH  DUH
HDVLHUWRLPSOHPHQWIRUVWDWLFODQJXDJHVDJDLQEHFDXVHRIWKHH[WUDW\SHLQIRUPDWLRQ
DYDLODEOH 7KH PRUH H[SOLFLW W\SH LQIRUPDWLRQ LQ VWDWLF FRGH SURPRWHV EHWWHU £VHOI
GRFXPHQWDWLRQ¤ZKLFKFDQEHLPSRUWDQWIRUFRPPXQLFDWLQJLQWHQWDPRQJGHYHORSHUV
HVSHFLDOO\DVDSURMHFWJURZV
:KHQXVLQJDVWDWLFODQJXDJH\RXKDYHWRWKLQNDERXWDSSURSULDWHW\SHFKRLFHVPRUH
RIWHQZKLFKIRUFHV\RXWRZHLJKGHVLJQFKRLFHVPRUHFDUHIXOO\:KLOHWKLVPD\VORZ
GRZQGDLO\GHVLJQGHFLVLRQVWKLQNLQJWKURXJKWKHW\SHVLQWKHDSSOLFDWLRQFDQUHVXOW
LQDPRUHFRKHUHQWGHVLJQRYHUWLPH

Why Scala? | 3

Download at WoweBook.Com
$QRWKHUVPDOOEHQHILWRIVWDWLFODQJXDJHVLVWKHH[WUDFKHFNLQJWKHFRPSLOHUSHUIRUPV
:HWKLQNWKLVDGYDQWDJHLVRIWHQRYHUVROGDVW\SHPLVPDWFKHUURUVDUHDVPDOOIUDFWLRQ
RIWKHUXQWLPHHUURUV\RXW\SLFDOO\VHH7KHFRPSLOHUFDQ¦WILQGORJLFHUURUVZKLFKDUH
IDUPRUHVLJQLILFDQW2QO\DFRPSUHKHQVLYHDXWRPDWHGWHVWVXLWHFDQILQGORJLFHUURUV
)RUG\QDPLFDOO\W\SHGODQJXDJHVWKHWHVWVPXVWFRYHUSRVVLEOHW\SHHUURUVWRR,I\RX
DUHFRPLQJIURPDG\QDPLFDOO\W\SHGODQJXDJH\RXPD\ILQGWKDW\RXUWHVWVXLWHVDUH
DOLWWOHVPDOOHUDVDUHVXOWEXWQRWWKDWPXFKVPDOOHU
0DQ\GHYHORSHUVZKRILQGVWDWLFODQJXDJHVWRRYHUERVHRIWHQEODPHVWDWLFW\SLQJIRU
WKHYHUERVLW\ZKHQWKHUHDOSUREOHPLVDODFNRIW\SHLQIHUHQFH,QW\SHLQIHUHQFHWKH
FRPSLOHULQIHUVWKHW\SHVRIYDOXHVEDVHGRQWKHFRQWH[W)RUH[DPSOHWKHFRPSLOHUZLOO
UHFRJQL]H WKDW x = 1 + 3 PHDQV WKDW x PXVW EH DQ LQWHJHU 7\SH LQIHUHQFH UHGXFHV
YHUERVLW\ VLJQLILFDQWO\ PDNLQJ WKH FRGH IHHO PRUH OLNH FRGH ZULWWHQ LQ D G\QDPLF
ODQJXDJH
:HKDYHZRUNHGZLWKERWKVWDWLFDQGG\QDPLFODQJXDJHVDWYDULRXVWLPHV:HILQG
ERWKNLQGVRIODQJXDJHVFRPSHOOLQJIRUGLIIHUHQWUHDVRQV:HEHOLHYHWKHPRGHUQVRIW
ZDUHGHYHORSHUPXVWPDVWHUDUDQJHRIODQJXDJHVDQGWRROV6RPHWLPHVDG\QDPLF
ODQJXDJHZLOOEHWKHULJKWWRROIRUWKHMRE$WRWKHUWLPHVDVWDWLFODQJXDJHOLNH6FDODLV
MXVWZKDW\RXQHHG

Introducing Scala
6FDOD LV D ODQJXDJH WKDW DGGUHVVHV WKH PDMRU QHHGV RI WKH PRGHUQ GHYHORSHU ,W LV D
VWDWLFDOO\W\SHGPL[HGSDUDGLJP-90ODQJXDJHZLWKDVXFFLQFWHOHJDQWDQGIOH[LEOH
V\QWD[DVRSKLVWLFDWHGW\SHV\VWHPDQGLGLRPVWKDWSURPRWHVFDODELOLW\IURPVPDOO
LQWHUSUHWHGVFULSWVWRODUJHVRSKLVWLFDWHGDSSOLFDWLRQV7KDW¦VDPRXWKIXOVROHW¦VORRN
DWHDFKRIWKRVHLGHDVLQPRUHGHWDLO
6WDWLFDOO\W\SHG
$VZHGHVFULEHGLQWKHSUHYLRXVVHFWLRQDVWDWLFDOO\W\SHGODQJXDJHELQGVWKHW\SH
WRDYDULDEOHIRUWKHOLIHWLPHRIWKDWYDULDEOH,QFRQWUDVWG\QDPLFDOO\W\SHGODQ
JXDJHVELQGWKHW\SHWRWKHDFWXDOYDOXHUHIHUHQFHGE\DYDULDEOHPHDQLQJWKDWWKH
W\SHRIDYDULDEOHFDQFKDQJHDORQJZLWKWKHYDOXHLWUHIHUHQFHV
2IWKHVHWRIQHZHU-90ODQJXDJHV6FDODLVRQHRIWKHIHZWKDWLVVWDWLFDOO\W\SHG
DQGLWLVWKHEHVWNQRZQDPRQJWKHP
0L[HGSDUDGLJP¢REMHFWRULHQWHGSURJUDPPLQJ
6FDOD IXOO\ VXSSRUWV REMHFWRULHQWHG SURJUDPPLQJ 223  6FDOD LPSURYHV XSRQ
-DYD¦VVXSSRUWIRU223ZLWKWKHDGGLWLRQRIWUDLWVDFOHDQZD\RILPSOHPHQWLQJ
FODVVHVXVLQJPL[LQFRPSRVLWLRQ6FDOD¦VWUDLWVZRUNPXFKOLNH5XE\¦VPRGXOHV,I
\RX¦UH D -DYD SURJUDPPHU WKLQN RI WUDLWV DV XQLI\LQJ LQWHUIDFHV ZLWK WKHLU
LPSOHPHQWDWLRQV
,Q6FDODHYHU\WKLQJLVUHDOO\DQREMHFW6FDODGRHVQRWKDYHSULPLWLYHW\SHVOLNH
-DYD ,QVWHDG DOO QXPHULF W\SHV DUH WUXH REMHFWV +RZHYHU IRU RSWLPDO

4 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
SHUIRUPDQFH6FDODXVHVWKHXQGHUO\LQJSULPLWLYHVW\SHVRIWKHUXQWLPHZKHQHYHU
SRVVLEOH$OVR6FDODGRHVQRWVXSSRUW£VWDWLF¤RUFODVVOHYHOPHPEHUVRIW\SHVVLQFH
WKH\DUHQRWDVVRFLDWHGZLWKDQDFWXDOLQVWDQFH,QVWHDG6FDODVXSSRUWVDVLQJOHWRQ
REMHFW FRQVWUXFW WR VXSSRUW WKRVH FDVHV ZKHUH H[DFWO\ RQH LQVWDQFH RI D W\SH LV
QHHGHG
0L[HGSDUDGLJP¢IXQFWLRQDOSURJUDPPLQJ
6FDODIXOO\VXSSRUWVIXQFWLRQDOSURJUDPPLQJ )3 )3LVDSURJUDPPLQJSDUDGLJP
WKDWLVROGHUWKDQ223EXWLWKDVEHHQVKHOWHUHGLQWKHLYRU\WRZHUVRIDFDGHPLD
XQWLOUHFHQWO\,QWHUHVWLQ)3LVLQFUHDVLQJEHFDXVHRIWKHZD\VLWVLPSOLILHVFHUWDLQ
GHVLJQSUREOHPVHVSHFLDOO\FRQFXUUHQF\£3XUH¤IXQFWLRQDOODQJXDJHVGRQ¦WDOORZ
IRUDQ\PXWDEOHVWDWHWKHUHE\DYRLGLQJWKHQHHGIRUV\QFKURQL]DWLRQRQVKDUHG
DFFHVVWRPXWDEOHVWDWH,QVWHDGSURJUDPVZULWWHQLQSXUHIXQFWLRQDOODQJXDJHV
FRPPXQLFDWHE\SDVVLQJPHVVDJHVEHWZHHQFRQFXUUHQWDXWRQRPRXVSURFHVVHV
6FDODVXSSRUWVWKLVPRGHOZLWKLWV$FWRUVOLEUDU\EXWLWDOORZVIRUERWKPXWDEOH
DQGLPPXWDEOHYDULDEOHV
)XQFWLRQVDUH£ILUVWFODVV¤FLWL]HQVLQ)3PHDQLQJWKH\FDQEHDVVLJQHGWRYDULDEOHV
SDVVHGWRRWKHUIXQFWLRQVHWFMXVWOLNHRWKHUYDOXHV7KLVIHDWXUHSURPRWHVFRP
SRVLWLRQRIDGYDQFHGEHKDYLRUXVLQJSULPLWLYHRSHUDWLRQV%HFDXVH6FDODDGKHUHV
WRWKHGLFWXPWKDWHYHU\WKLQJLVDQREMHFWIXQFWLRQVDUHWKHPVHOYHVREMHFWVLQ6FDOD
6FDODDOVRRIIHUVFORVXUHVDIHDWXUHWKDWG\QDPLFODQJXDJHVOLNH3\WKRQDQG5XE\
KDYHDGRSWHGIURPWKHIXQFWLRQDOSURJUDPPLQJZRUOGDQGRQHVDGO\DEVHQWIURP
UHFHQWYHUVLRQVRI-DYD&ORVXUHVDUHIXQFWLRQVWKDWUHIHUHQFHYDULDEOHVIURPWKH
VFRSHHQFORVLQJWKHIXQFWLRQGHILQLWLRQ7KDWLVWKHYDULDEOHVDUHQ¦WSDVVHGLQDV
DUJXPHQWV RU GHILQHG DV ORFDO YDULDEOHV ZLWKLQ WKH IXQFWLRQ $ FORVXUH £FORVHV
DURXQG¤WKHVHUHIHUHQFHVVRWKHIXQFWLRQLQYRFDWLRQFDQVDIHO\UHIHUWRWKHYDULDEOHV
HYHQ ZKHQ WKH YDULDEOHV KDYH JRQH RXW RI VFRSH &ORVXUHV DUH VXFK D SRZHUIXO
DEVWUDFWLRQ WKDW REMHFW V\VWHPV DQG IXQGDPHQWDO FRQWURO VWUXFWXUHV DUH RIWHQ
LPSOHPHQWHGXVLQJWKHP
$-90DQG1(7ODQJXDJH
:KLOH6FDODLVSULPDULO\NQRZQDVD-90ODQJXDJHPHDQLQJWKDW6FDODJHQHUDWHV
-90E\WHFRGHD1(7YHUVLRQRI6FDODWKDWJHQHUDWHV&RPPRQ/DQJXDJH5XQWLPH
&/5  E\WH FRGH LV DOVR XQGHU GHYHORSPHQW :KHQ ZH UHIHU WR WKH XQGHUO\LQJ
£UXQWLPH¤ZHZLOOXVXDOO\GLVFXVVWKH-90EXWPRVWRIZKDWZHZLOOVD\DSSOLHV
HTXDOO\WRERWKUXQWLPHV:KHQZHGLVFXVV-90VSHFLILFGHWDLOVWKH\JHQHUDOL]H
WRWKH1(7YHUVLRQH[FHSWZKHUHQRWHG
7KH6FDODFRPSLOHUXVHVFOHYHUWHFKQLTXHVWRPDS6FDODH[WHQVLRQVWRYDOLGE\WH
FRGHLGLRPV)URP6FDOD\RXFDQHDVLO\LQYRNHE\WHFRGHWKDWRULJLQDWHGDV-DYD
VRXUFH IRUWKH-90 RU&VRXUFH IRU1(7 &RQYHUVHO\\RXFDQLQYRNH6FDOD
FRGHIURP-DYD&HWF5XQQLQJRQWKH-90DQG&/5DOORZVWKH6FDODGHYHORSHU
WROHYHUDJHDYDLODEOHOLEUDULHVDQGWRLQWHURSHUDWHZLWKRWKHUODQJXDJHVKRVWHGRQ
WKRVHUXQWLPHV

Why Scala? | 5

Download at WoweBook.Com
$VXFFLQFWHOHJDQWDQGIOH[LEOHV\QWD[
-DYDV\QWD[FDQEHYHUERVH6FDODXVHVDQXPEHURIWHFKQLTXHVWRPLQLPL]HXQ
QHFHVVDU\V\QWD[PDNLQJ6FDODFRGHDVVXFFLQFWDVFRGHLQPRVWG\QDPLFDOO\W\SHG
ODQJXDJHV7\SHLQIHUHQFHPLQLPL]HVWKHQHHGIRUH[SOLFLWW\SHLQIRUPDWLRQLQPDQ\
FRQWH[WV'HFODUDWLRQVRIW\SHVDQGIXQFWLRQVDUHYHU\FRQFLVH
6FDODDOORZVIXQFWLRQQDPHVWRLQFOXGHQRQDOSKDQXPHULFFKDUDFWHUV&RPELQHG
ZLWKVRPHV\QWDFWLFVXJDUWKLVIHDWXUHSHUPLWVWKHXVHUWRGHILQHPHWKRGVWKDWORRN
DQGEHKDYHOLNHRSHUDWRUV$VDUHVXOWOLEUDULHVRXWVLGHWKHFRUHRIWKHODQJXDJH
FDQIHHO£QDWLYH¤WRXVHUV
$VRSKLVWLFDWHGW\SHV\VWHP
6FDODH[WHQGVWKHW\SHV\VWHPRI-DYDZLWKPRUHIOH[LEOHJHQHULFVDQGDQXPEHURI
PRUHDGYDQFHGW\SLQJFRQVWUXFWV7KHW\SHV\VWHPFDQEHLQWLPLGDWLQJDWILUVWEXW
PRVWRIWKHWLPH\RXZRQ¦WQHHGWRZRUU\DERXWWKHDGYDQFHGFRQVWUXFWV7\SH
LQIHUHQFHKHOSVE\DXWRPDWLFDOO\LQIHUULQJW\SHVLJQDWXUHVVRWKDWWKHXVHUGRHVQ¦W
KDYHWRSURYLGHWULYLDOW\SHLQIRUPDWLRQPDQXDOO\:KHQ\RXQHHGWKHPWKRXJK
WKHDGYDQFHGW\SHIHDWXUHVSURYLGH\RXZLWKJUHDWHUIOH[LELOLW\IRUVROYLQJGHVLJQ
SUREOHPVLQDW\SHVDIHZD\
6FDODEOH¢DUFKLWHFWXUHV
6FDODLVGHVLJQHGWRVFDOHIURPVPDOOLQWHUSUHWHGVFULSWVWRODUJHGLVWULEXWHGDS
SOLFDWLRQV6FDODSURYLGHVIRXUODQJXDJHPHFKDQLVPVWKDWSURPRWHVFDODEOHFRP
SRVLWLRQRIV\VWHPV H[SOLFLWVHOIW\SHV DEVWUDFWW\SHPHPEHUVDQGJHQHULFV
 QHVWHGFODVVHVDQG PL[LQFRPSRVLWLRQXVLQJWUDLWV
1RRWKHUODQJXDJHSURYLGHVDOOWKHVHPHFKDQLVPV7RJHWKHUWKH\DOORZDSSOLFD
WLRQVWREHFRQVWUXFWHGIURPUHXVDEOH£FRPSRQHQWV¤LQDW\SHVDIHDQGVXFFLQFW
PDQQHU$VZHZLOOVHHPDQ\FRPPRQGHVLJQSDWWHUQVDQGDUFKLWHFWXUDOWHFKQL
TXHVOLNHGHSHQGHQF\LQMHFWLRQDUHHDV\WRLPSOHPHQWLQ6FDODZLWKRXWWKHERLOHU
SODWHFRGHRUOHQJWK\;0/FRQILJXUDWLRQILOHVWKDWFDQPDNH-DYDGHYHORSPHQW
WHGLRXV
6FDODEOH¢SHUIRUPDQFH
%HFDXVH6FDODFRGHUXQVRQWKH-90DQGWKH&/5LWEHQHILWVIURPDOOWKHSHUIRUP
DQFHRSWLPL]DWLRQVSURYLGHGE\WKRVHUXQWLPHVDQGDOOWKHWKLUGSDUW\WRROVWKDW
VXSSRUWSHUIRUPDQFHDQGVFDODELOLW\VXFKDVSURILOHUVGLVWULEXWHGFDFKHOLEUDULHV
FOXVWHULQJPHFKDQLVPVHWF,I\RXWUXVW-DYD¦VDQG&¦VSHUIRUPDQFH\RXFDQWUXVW
6FDOD¦VSHUIRUPDQFH2IFRXUVHVRPHSDUWLFXODUFRQVWUXFWVLQWKHODQJXDJHDQG
VRPHSDUWVRIWKHOLEUDU\PD\SHUIRUPVLJQLILFDQWO\EHWWHURUZRUVHWKDQDOWHUQDWLYH
RSWLRQVLQRWKHUODQJXDJHV$VDOZD\V\RXVKRXOGSURILOH\RXUFRGHDQGRSWLPL]H
LWZKHQQHFHVVDU\
,WPLJKWDSSHDUWKDW223DQG)3DUHLQFRPSDWLEOH,QIDFWDGHVLJQSKLORVRSK\RI6FDOD
LVWKDW223DQG)3DUHPRUHV\QHUJLVWLFWKDQRSSRVHG7KHIHDWXUHVRIRQHDSSURDFK
FDQHQKDQFHWKHRWKHU

6 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
,Q)3IXQFWLRQVKDYHQRVLGHHIIHFWVDQGYDULDEOHVDUHLPPXWDEOHZKLOHLQ223PX
WDEOHVWDWHDQGVLGHHIIHFWVDUHFRPPRQHYHQHQFRXUDJHG6FDODOHWV\RXFKRRVHWKH
DSSURDFKWKDWEHVWILWV\RXUGHVLJQSUREOHPV)XQFWLRQDOSURJUDPPLQJLVHVSHFLDOO\
XVHIXOIRUFRQFXUUHQF\VLQFHLWHOLPLQDWHVWKHQHHGWRV\QFKURQL]HDFFHVVWRPXWDEOH
VWDWH+RZHYHU£SXUH¤)3FDQEHUHVWULFWLYH6RPHGHVLJQSUREOHPVDUHHDVLHUWRVROYH
ZLWKPXWDEOHREMHFWV
7KHQDPH6FDODLVDFRQWUDFWLRQRIWKHZRUGVVFDODEOHODQJXDJH:KLOHWKLVVXJJHVWV
WKDWWKHSURQXQFLDWLRQVKRXOGEHVFDOHDKWKHFUHDWRUVRI6FDODDFWXDOO\SURQRXQFHLW
VFDKODKOLNHWKH,WDOLDQZRUGIRU£VWDLUV¤7KHWZR£D¤VDUHSURQRXQFHGWKHVDPH
6FDODZDVVWDUWHGE\0DUWLQ2GHUVN\LQ0DUWLQLVDSURIHVVRULQWKH6FKRRORI
&RPSXWHUDQG&RPPXQLFDWLRQ6FLHQFHVDWWKH(FROH3RO\WHFKQLTXH)pGpUDOHGH/DX
VDQQH (3)/ +HVSHQWKLVJUDGXDWH\HDUVZRUNLQJLQWKHJURXSKHDGHGE\1LNODXV
:LUWKRI3DVFDOIDPH0DUWLQZRUNHGRQ3L]]DDQHDUO\IXQFWLRQDOODQJXDJHRQWKH
-90+HODWHUZRUNHGRQ*-DSURWRW\SHRIZKDWODWHUEHFDPH*HQHULFVLQ-DYDZLWK
3KLOLS:DGOHURI+DVNHOOIDPH0DUWLQZDVKLUHGE\6XQ0LFURV\VWHPVWRSURGXFHWKH
UHIHUHQFHLPSOHPHQWDWLRQRIjavacWKH-DYDFRPSLOHUWKDWVKLSVZLWKWKH-DYD'HYHORSHU
.LW -'. WRGD\
0DUWLQ2GHUVN\¦VEDFNJURXQGDQGH[SHULHQFHDUHHYLGHQWLQWKHODQJXDJH$V\RXOHDUQ
6FDOD \RX FRPH WR XQGHUVWDQG WKDW LW LV WKH SURGXFW RI FDUHIXOO\ FRQVLGHUHG GHVLJQ
GHFLVLRQVH[SORLWLQJWKHVWDWHRIWKHDUWLQW\SHWKHRU\223DQG)30DUWLQ¦VH[SH
ULHQFHZLWKWKH-90LVHYLGHQWLQ6FDOD¦VHOHJDQWLQWHJUDWLRQZLWKWKDWSODWIRUP7KH
V\QWKHVLVLWFUHDWHVEHWZHHQ223DQG)3LVDQH[FHOOHQW£EHVWRIERWKZRUOGV¤VROXWLRQ

The Seductions of Scala


7RGD\RXULQGXVWU\LVIRUWXQDWHWRKDYHDZLGHYDULHW\RIODQJXDJHRSWLRQV7KHSRZHU
IOH[LELOLW\DQGHOHJDQFHRIG\QDPLFDOO\W\SHGODQJXDJHVKDYHPDGHWKHPYHU\SRSXODU
DJDLQ<HWWKHZHDOWKRI-DYDDQG1(7OLEUDULHVDQGWKHSHUIRUPDQFHRIWKH-90DQG
&/5PHHWPDQ\SUDFWLFDOQHHGVIRUHQWHUSULVHDQG,QWHUQHWSURMHFWV
6FDODLVFRPSHOOLQJEHFDXVHLWIHHOVOLNHDG\QDPLFDOO\W\SHGVFULSWLQJODQJXDJHGXHWR
LWVVXFFLQFWV\QWD[DQGW\SHLQIHUHQFH<HW6FDODJLYHV\RXDOOWKHEHQHILWVRIVWDWLFW\SLQJ
DPRGHUQREMHFWPRGHOIXQFWLRQDOSURJUDPPLQJDQGDQDGYDQFHGW\SHV\VWHP7KHVH
WRROVOHW\RXEXLOGVFDODEOHPRGXODUDSSOLFDWLRQVWKDWFDQUHXVHOHJDF\-DYDDQG1(7
$3,VDQGOHYHUDJHWKHSHUIRUPDQFHRIWKH-90DQG&/5
6FDODLVDODQJXDJHIRUSURIHVVLRQDOGHYHORSHUV&RPSDUHGWRODQJXDJHVOLNH-DYDDQG
5XE\6FDODLVDPRUHGLIILFXOWODQJXDJHWRPDVWHUEHFDXVHLWUHTXLUHVFRPSHWHQF\ZLWK
223)3DQGVWDWLFW\SLQJWRXVHLWPRVWHIIHFWLYHO\,WLVWHPSWLQJWRSUHIHUWKHUHODWLYH
VLPSOLFLW\RIG\QDPLFDOO\W\SHGODQJXDJHV<HWWKLVVLPSOLFLW\FDQEHGHFHSWLYH,QD
G\QDPLFDOO\W\SHGODQJXDJHLWLVRIWHQQHFHVVDU\WRXVHPHWDSURJUDPPLQJIHDWXUHVWR
LPSOHPHQWDGYDQFHGGHVLJQV:KLOHPHWDSURJUDPPLQJLVSRZHUIXOXVLQJLWZHOOWDNHV
H[SHULHQFHDQGWKHUHVXOWLQJFRGHWHQGVWREHKDUGWRXQGHUVWDQGPDLQWDLQDQGGHEXJ

Why Scala? | 7

Download at WoweBook.Com
,Q 6FDOD PDQ\ RI WKH VDPH GHVLJQ JRDOV FDQ EH DFKLHYHG LQ D W\SHVDIH PDQQHU E\
H[SORLWLQJLWVW\SHV\VWHPDQGPL[LQFRPSRVLWLRQWKURXJKWUDLWV
:HIHHOWKDWWKHH[WUDHIIRUWUHTXLUHGGD\WRGD\WRXVH6FDODZLOOSURPRWHPRUHFDUHIXO
UHIOHFWLRQDERXW\RXUGHVLJQV2YHUWLPHWKLVGLVFLSOLQHZLOO\LHOGPRUHFRKHUHQWPRG
XODUDQGPDLQWDLQDEOHDSSOLFDWLRQV)RUWXQDWHO\\RXGRQ¦WQHHGDOORIWKHVRSKLVWLFD
WLRQRI6FDODDOORIWKHWLPH0XFKRI\RXUFRGHZLOOKDYHWKHVLPSOLFLW\DQGFODULW\RI
FRGHZULWWHQLQ\RXUIDYRULWHG\QDPLFDOO\W\SHGODQJXDJH
$QDOWHUQDWLYHVWUDWHJ\LVWRFRPELQHVHYHUDOVLPSOHUODQJXDJHVHJ-DYDIRUREMHFW
RULHQWHGFRGHDQG(UODQJIRUIXQFWLRQDOFRQFXUUHQWFRGH6XFKDGHFRPSRVLWLRQFDQ
ZRUNEXWRQO\LI\RXUV\VWHPGHFRPSRVHVFOHDQO\LQWRVXFKGLVFUHWHSDUWVDQG\RXU
WHDP FDQ PDQDJH D KHWHURJHQHRXV HQYLURQPHQW 6FDOD LV DWWUDFWLYH IRU VLWXDWLRQV LQ
ZKLFKDVLQJOHDOOLQRQHODQJXDJHLVSUHIHUUHG7KDWVDLG6FDODFRGHFDQKDSSLO\FR
H[LVWZLWKRWKHUODQJXDJHVHVSHFLDOO\RQWKH-90RU1(7

Installing Scala
7RJHWXSDQGUXQQLQJDVTXLFNO\DVSRVVLEOHWKLVVHFWLRQGHVFULEHVKRZWRLQVWDOOWKH
FRPPDQGOLQHWRROVIRU6FDODZKLFKDUHDOO\RXQHHGWRZRUNZLWKWKHH[DPSOHVLQWKH
ERRN )RU GHWDLOV RQ XVLQJ 6FDOD LQ YDULRXV HGLWRUV DQG ,'(V VHH £,QWHJUDWLRQ ZLWK
,'(V¤RQSDJH7KHH[DPSOHVXVHGLQWKLVERRNZHUHZULWWHQDQGFRPSLOHGXVLQJ
6FDOD YHUVLRQ ILQDO WKH ODWHVW UHOHDVH DW WKH WLPH RI WKLV ZULWLQJ DQG £QLJKWO\
EXLOGV¤RI6FDODYHUVLRQZKLFKPD\EHILQDOL]HGE\WKHWLPH\RXUHDGWKLV

9HUVLRQ  LQWURGXFHV PDQ\ QHZ IHDWXUHV ZKLFK ZH ZLOO KLJKOLJKW
WKURXJKRXWWKHERRN

:HZLOOZRUNZLWKWKH-90YHUVLRQRI6FDODLQWKLVERRN)LUVW\RXPXVWKDYH-DYD
RUJUHDWHULQVWDOOHG RUJUHDWHULVUHFRPPHQGHG ,I\RXQHHGWRLQVWDOO-DYDJRWR
KWWSZZZMDYDFRPHQGRZQORDGPDQXDOMVSDQGIROORZWKHLQVWUXFWLRQVWRLQVWDOO-DYD
RQ\RXUPDFKLQH
7KH RIILFLDO 6FDOD ZHEVLWH LV KWWSZZZVFDODODQJRUJ 7R LQVWDOO 6FDOD JR WR WKH
GRZQORDGVSDJH'RZQORDGWKHLQVWDOOHUIRU\RXUHQYLURQPHQWDQGIROORZWKHLQVWUXF
WLRQVRQWKHGRZQORDGVSDJH
7KHHDVLHVWFURVVSODWIRUPLQVWDOOHULVWKH,]3DFNLQVWDOOHU'RZQORDGWKH6FDOD-$5ILOH
HLWKHUVFDODILQDOLQVWDOOHUMDURUVFDOD1LQVWDOOHUMDUZKHUH NLVWKHODWHVW
UHOHDVHRIWKHYHUVLRQ*RWRWKHGRZQORDGGLUHFWRU\LQDWHUPLQDOZLQGRZDQG
LQVWDOO 6FDOD ZLWK WKH java FRPPDQG $VVXPLQJ \RX GRZQORDGHG VFDODILQDO
LQVWDOOHUMDUUXQWKHIROORZLQJFRPPDQGZKLFKZLOOJXLGH\RXWKURXJKWKHSURFHVV
java -jar scala-2.8.0.final-installer.jar

8 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
2Q0DF26;WKHHDVLHVWURXWHWRDZRUNLQJ6FDODLQVWDOODWLRQLVYLD
0DF3RUWV)ROORZWKHLQVWDOODWLRQLQVWUXFWLRQVDWKWWSZZZPDFSRUWV
RUJWKHQsudo port install scala<RX¦OOEHXSDQGUXQQLQJLQDIHZ
PLQXWHV

7KURXJKRXWWKLVERRNZHZLOOXVHWKHV\PEROscala-homeWRUHIHUWRWKH£URRW¤GLUHFWRU\
RI\RXU6FDODLQVWDOODWLRQ

2Q 8QL[ /LQX[ DQG 0DF 26 ; V\VWHPV \RX ZLOO QHHG WR UXQ WKLV
FRPPDQGDVWKH rootXVHURUXVLQJWKH sudoFRPPDQGLI\RXZDQWWR
LQVWDOO 6FDOD XQGHU D V\VWHP GLUHFWRU\ HJ scala-home  XVUORFDO
VFDODILQDO

$V DQ DOWHUQDWLYH \RX FDQ GRZQORDG DQG H[SDQG WKH FRPSUHVVHG 7$5 ILOH HJ
VFDODILQDOWJ] RU=,3ILOH VFDODILQDO]LS 2Q8QL[OLNHV\VWHPVH[SDQG
WKHFRPSUHVVHGILOHLQWRDORFDWLRQRI\RXUFKRRVLQJ$IWHUZDUGDGGWKH scala-home
ELQ VXEGLUHFWRU\ LQ WKH QHZ GLUHFWRU\ WR \RXU PATH )RU H[DPSOH LI \RX LQVWDOOHG
LQWRXVUORFDOVFDODILQDOWKHQDGGXVUORFDOVFDODILQDOELQWR\RXUPATH
7RWHVW\RXULQVWDOODWLRQUXQWKHIROORZLQJFRPPDQGRQWKHFRPPDQGOLQH
scala -version

:H¦OOOHDUQPRUHDERXWWKHscalaFRPPDQGOLQHWRROODWHU<RXVKRXOGJHWVRPHWKLQJ
OLNHWKHIROORZLQJRXWSXW
Scala code runner version 2.8.0.final -- Copyright 2002-2009, LAMP/EPFL

2IFRXUVHWKHYHUVLRQQXPEHU\RXVHHZLOOEHGLIIHUHQWLI\RXLQVWDOOHGDGLIIHUHQWUH
OHDVH)URPQRZRQZKHQZHVKRZFRPPDQGRXWSXWWKDWFRQWDLQVWKHYHUVLRQQXPEHU
ZH¦OOVKRZLWDVversion 2.8.0.final
&RQJUDWXODWLRQV\RXKDYHLQVWDOOHG6FDOD,I\RXJHWDQHUURUPHVVDJHDORQJWKHOLQHV
RI scala: command not foundPDNHVXUH\RXUHQYLURQPHQW¦V PATHLVVHWSURSHUO\WR
LQFOXGHWKHFRUUHFWELQGLUHFWRU\

6FDODYHUVLRQV;DQGHDUOLHUDUHFRPSDWLEOHZLWK-'.DQGODWHU
6FDODYHUVLRQGURSVFRPSDWLELOLW\1RWHWKDW6FDODXVHVPDQ\
-'.FODVVHVDVLWVRZQIRUH[DPSOHWKH StringFODVV2Q1(76FDOD
XVHVWKHFRUUHVSRQGLQJ1(7FODVVHV

<RXFDQDOVRILQGGRZQORDGVIRUWKH$3,GRFXPHQWDWLRQDQGWKHVRXUFHVIRU6FDODLWVHOI
RQWKHVDPHGRZQORDGVSDJH

Installing Scala | 9

Download at WoweBook.Com
For More Information
$V\RXH[SORUH6FDOD\RXZLOOILQGRWKHUXVHIXOUHVRXUFHVWKDWDUHDYDLODEOHRQKWWS
VFDODODQJRUJ<RXZLOOILQGOLQNVIRUGHYHORSPHQWVXSSRUWWRROVDQGOLEUDULHVWXWRULDOV
WKHODQJXDJHVSHFLILFDWLRQ>6FDOD6SHF@DQGDFDGHPLFSDSHUVWKDWGHVFULEHIHDWXUHV
RIWKHODQJXDJH
7KHGRFXPHQWDWLRQIRUWKH6FDODWRROVDQG$3,VDUHHVSHFLDOO\XVHIXO<RXFDQEURZVH
WKH$3,DWKWWSZZZVFDODODQJRUJGRFXILOHVDSLLQGH[KWPO7KLVGRFXPHQWDWLRQZDV
JHQHUDWHGXVLQJWKHscaladocWRRODQDORJRXVWR-DYD¦VjavadocWRRO6HH£7KHVFDODGRF
&RPPDQG/LQH7RRO¤RQSDJHIRUPRUHLQIRUPDWLRQ
<RXFDQDOVRGRZQORDGDFRPSUHVVHGILOHRIWKH$3,GRFXPHQWDWLRQIRUORFDOEURZVLQJ
XVLQJWKHDSSURSULDWHOLQNRQWKHGRZQORDGVSDJHRU\RXFDQLQVWDOOLWZLWKWKH sbaz
SDFNDJHWRRODVIROORZV
sbaz install scala-devel-docs

sbazLVLQVWDOOHGLQWKHVDPHELQGLUHFWRU\DVWKHscalaDQGscalacFRPPDQGOLQHWRROV
7KHLQVWDOOHGGRFXPHQWDWLRQDOVRLQFOXGHVGHWDLOVRQWKHVFDODWRROFKDLQ LQFOXGLQJ
sbaz DQGFRGHH[DPSOHV)RUPRUHLQIRUPDWLRQRQWKH6FDODFRPPDQGOLQHWRROVDQG
RWKHUUHVRXUFHVVHH&KDSWHU

A Taste of Scala
,W¦VWLPHWRZKHW\RXUDSSHWLWHZLWKVRPHUHDO6FDODFRGH,QWKHIROORZLQJH[DPSOHV
ZH¦OOGHVFULEHMXVWHQRXJKRIWKHGHWDLOVVR\RXXQGHUVWDQGZKDW¦VJRLQJRQ7KHJRDO
LVWRJLYH\RXDVHQVHRIZKDWSURJUDPPLQJLQ6FDODLVOLNH:H¦OOH[SORUHWKHGHWDLOVRI
WKHIHDWXUHVLQVXEVHTXHQWFKDSWHUV
)RURXUILUVWH[DPSOH\RXFRXOGUXQLWRQHRIWZRZD\VLQWHUDFWLYHO\RUDVD£VFULSW¤
/HW¦VVWDUWZLWKWKHLQWHUDFWLYHPRGH6WDUWWKHVFDODLQWHUSUHWHUE\W\SLQJscalaDQGWKH
UHWXUQNH\RQ\RXUFRPPDQGOLQH<RX¦OOVHHWKHIROORZLQJRXWSXW 6RPHRIWKHYHUVLRQ
QXPEHUVPD\YDU\
Welcome to Scala version 2.8.0.final (Java ...).
Type in expressions to have them evaluated.
Type :help for more information.

scala>

7KHODVWOLQHLVWKHSURPSWWKDWLVZDLWLQJIRU\RXULQSXW7KHLQWHUDFWLYHPRGHRIWKH
scalaFRPPDQGLVYHU\FRQYHQLHQWIRUH[SHULPHQWDWLRQ VHH£7KHVFDOD&RPPDQG/LQH
7RRO¤RQSDJHIRUPRUHGHWDLOV $QLQWHUDFWLYHLQWHUSUHWHUOLNHWKLVLVFDOOHGD5(3/
5HDG(YDOXDWH3ULQW/RRS

10 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
7\SHLQWKHIROORZLQJWZROLQHVRIFRGH
val book = "Programming Scala"
println(book)

7KHDFWXDOLQSXWDQGRXWSXWVKRXOGORRNOLNHWKHIROORZLQJ
scala> val book = "Programming Scala"
book: java.lang.String = Programming Scala

scala> println(book)
Programming Scala

scala>

7KHILUVWOLQHXVHVWKH valNH\ZRUGWRGHFODUHDUHDGRQO\YDULDEOHQDPHG book1RWH


WKDWWKHRXWSXWUHWXUQHGIURPWKHLQWHUSUHWHUVKRZV\RXWKHW\SHDQGYDOXHRI book
7KLVFDQEHYHU\KDQG\IRUXQGHUVWDQGLQJFRPSOH[GHFODUDWLRQV7KHVHFRQGOLQHSULQWV
WKHYDOXHRIbookZKLFKLV£3URJUDPPLQJ6FDOD¤

([SHULPHQWLQJZLWKWKHscalaFRPPDQGLQWKHLQWHUDFWLYHPRGH 5(3/
LVDJUHDWZD\WROHDUQWKHGHWDLOVRI6FDOD

0DQ\RIWKHH[DPSOHVLQWKLVERRNFDQEHH[HFXWHGLQWKHLQWHUSUHWHUOLNHWKLV+RZHYHU
LW¦VRIWHQPRUHFRQYHQLHQWWRXVHWKHVHFRQGRSWLRQZHPHQWLRQHGZULWLQJ6FDODVFULSWV
LQDWH[WHGLWRURU,'(DQGH[HFXWLQJWKHPZLWKWKHVDPH scalaFRPPDQG:H¦OOGR
WKDWIRUPRVWRIWKHUHPDLQLQJH[DPSOHVLQWKLVFKDSWHU
,Q\RXUWH[WHGLWRURIFKRLFHVDYHWKH6FDODFRGHLQWKHIROORZLQJH[DPSOHWRDILOH
QDPHGXSSHUVFULSWVFDODLQDGLUHFWRU\RI\RXUFKRRVLQJ
// code-examples/IntroducingScala/upper1-script.scala

class Upper {
def upper(strings: String*): Seq[String] = {
strings.map((s:String) => s.toUpperCase())
}
}

val up = new Upper


Console.println(up.upper("A", "First", "Scala", "Program"))

7KLV6FDODVFULSWFRQYHUWVVWULQJVWRXSSHUFDVH
%\WKHZD\WKDW¦VDFRPPHQWRQWKHILUVWOLQH ZLWKWKHQDPHRIWKHVRXUFHILOHIRUWKH
FRGHH[DPSOH 6FDODIROORZVWKHVDPHFRPPHQWFRQYHQWLRQVDV-DYD&&HWF
$// commentJRHVWRWKHHQGRIDOLQHZKLOHD/* comment */FDQFURVVOLQHERXQGDULHV

A Taste of Scala | 11

Download at WoweBook.Com
7RUXQWKLVVFULSWJRWRDFRPPDQGZLQGRZFKDQJHWRWKHVDPHGLUHFWRU\DQGUXQ
WKHIROORZLQJFRPPDQG
scala upper1-script.scala

7KHILOHLVLQWHUSUHWHGPHDQLQJLWLVFRPSLOHGDQGH[HFXWHGLQRQHVWHS<RXVKRXOG
JHWWKHIROORZLQJRXWSXW
Array(A, FIRST, SCALA, PROGRAM)

Interpreting Versus Compiling and Running Scala Code


7RVXPPDUL]HLI\RXW\SH scalaRQWKHFRPPDQGOLQHZLWKRXWDILOHDUJXPHQWWKH
LQWHUSUHWHUUXQVLQLQWHUDFWLYHPRGH<RXW\SHLQGHILQLWLRQVDQGVWDWHPHQWVWKDWDUH
HYDOXDWHGRQWKHIO\,I\RXJLYHWKHFRPPDQGDVFDODVRXUFHILOHDUJXPHQWLWFRPSLOHV
DQGUXQVWKHILOHDVDVFULSWDVLQRXUscala upper1-script.scalaH[DPSOH)LQDOO\\RX
FDQFRPSLOH6FDODILOHVVHSDUDWHO\DQGH[HFXWHWKH classILOHDVORQJDVLWKDVD main
PHWKRGMXVWDV\RXZRXOGQRUPDOO\GRZLWKWKH javaFRPPDQG :H¦OOVKRZDQH[
DPSOHVKRUWO\
7KHUHDUHVRPHVXEWOHWLHV\RX¦OOQHHGWRXQGHUVWDQGDERXWWKHOLPLWDWLRQVRIXVLQJWKH
LQWHUSUHWHUPRGHVYHUVXVVHSDUDWHFRPSLODWLRQDQGH[HFXWLRQVWHSV:HGLVFXVVWKHVH
VXEWOHWLHVLQ£&RPPDQG/LQH7RROV¤RQSDJH
:KHQHYHUZHUHIHUWRH[HFXWLQJDVFULSWZHPHDQUXQQLQJD6FDODVRXUFHILOHZLWKWKH
scalaFRPPDQG

,QWKHFXUUHQWH[DPSOHWKHupperPHWKRGLQWKHUpperFODVV QRSXQLQWHQGHG FRQYHUWV


WKHLQSXWVWULQJVWRXSSHUFDVHDQGUHWXUQVWKHPLQDQDUUD\7KHODVWOLQHLQWKHH[DPSOH
FRQYHUWVIRXUVWULQJVDQGSULQWVWKHUHVXOWLQJArray
/HW¦VH[DPLQHWKHFRGHLQGHWDLOVRZHFDQEHJLQWROHDUQ6FDODV\QWD[7KHUHDUHDORW
RIGHWDLOVLQMXVWVL[OLQHVRIFRGH:H¦OOH[SODLQWKHJHQHUDOLGHDVKHUH$OOWKHLGHDV
XVHGLQWKLVH[DPSOHZLOOEHH[SODLQHGPRUHWKRURXJKO\LQODWHUVHFWLRQVRIWKHERRN
,QWKHH[DPSOHWKHUpperFODVVEHJLQVZLWKWKHclassNH\ZRUG7KHFODVVERG\LVLQVLGH
WKHRXWHUPRVWFXUO\EUDFHV {...} 
7KHupperPHWKRGGHILQLWLRQEHJLQVRQWKHVHFRQGOLQHZLWKWKHdefNH\ZRUGIROORZHG
E\WKHPHWKRGQDPHDQGDQDUJXPHQWOLVWWKHUHWXUQW\SHRIWKHPHWKRGDQHTXDOV
VLJQ = DQGWKHQWKHPHWKRGERG\
7KHDUJXPHQWOLVWLQSDUHQWKHVHVLVDFWXDOO\DYDULDEOHOHQJWKDUJXPHQWOLVWRIStringV
LQGLFDWHGE\WKH String*W\SHIROORZLQJWKHFRORQ7KDWLV\RXFDQSDVVLQDVPDQ\
FRPPDVHSDUDWHGVWULQJVDV\RXZDQW LQFOXGLQJDQHPSW\OLVW 7KHVHVWULQJVDUHVWRUHG
LQDSDUDPHWHUQDPHGstrings,QVLGHWKHPHWKRGstringsLVDFWXDOO\DQArray

12 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
:KHQH[SOLFLWW\SHLQIRUPDWLRQIRUYDULDEOHVLVZULWWHQLQWKHFRGHWKHVH
W\SHDQQRWDWLRQVIROORZWKHFRORQDIWHUWKHLWHPQDPH LH3DVFDOOLNH
V\QWD[ :K\GRHVQ¦W6FDODIROORZ-DYDFRQYHQWLRQV"5HFDOOWKDWW\SH
LQIRUPDWLRQLVRIWHQLQIHUUHGLQ6FDOD XQOLNH-DYD PHDQLQJZHGRQ¦W
DOZD\V VKRZ W\SH DQQRWDWLRQV H[SOLFLWO\ &RPSDUHG WR -DYD¦V
type itemFRQYHQWLRQWKHitem: typeFRQYHQWLRQLVHDVLHUIRUWKHFRP
SLOHUWRDQDO\]HXQDPELJXRXVO\ZKHQ\RXRPLWWKHFRORQDQGWKHW\SH
DQQRWDWLRQDQGMXVWZULWHitem

7KHPHWKRGUHWXUQW\SHDSSHDUVDIWHUWKHDUJXPHQWOLVW,QWKLVFDVHWKHUHWXUQW\SHLV
Seq[String]ZKHUHSeq £VHTXHQFH¤ LVDSDUWLFXODUNLQGRIFROOHFWLRQ,WLVDSDUDPH
WHUL]HGW\SH OLNHDJHQHULFW\SHLQ-DYD SDUDPHWHUL]HGKHUHZLWKString1RWHWKDW6FDOD
XVHVVTXDUHEUDFNHWV [...] IRUSDUDPHWHUL]HGW\SHVZKHUHDV-DYDXVHVDQJOHEUDFNHWV
<...> 

6FDODDOORZVDQJOHEUDFNHWVWREHXVHGLQPHWKRGQDPHVHJQDPLQJD
£OHVVWKDQ¤PHWKRG <LVFRPPRQ6RWRDYRLGDPELJXLWLHV6FDODXVHV
VTXDUHEUDFNHWVLQVWHDGIRUSDUDPHWHUL]HGW\SHV7KH\FDQ¦WEHXVHGLQ
PHWKRGQDPHV$OORZLQJ<DQG>LQPHWKRGQDPHVLVZK\6FDODGRHVQ¦W
IROORZ-DYD¦VFRQYHQWLRQIRUDQJOHEUDFNHWV

7KHERG\RIWKH upperPHWKRGFRPHVDIWHUWKHHTXDOVVLJQ = :K\DQHTXDOVVLJQ"


:K\QRWMXVWFXUO\EUDFHV {...} OLNHLQ-DYD"%HFDXVHVHPLFRORQVIXQFWLRQUHWXUQ
W\SHVPHWKRGDUJXPHQWVOLVWVDQGHYHQWKHFXUO\EUDFHVDUHVRPHWLPHVRPLWWHGXVLQJ
DQHTXDOVVLJQSUHYHQWVVHYHUDOSRVVLEOHSDUVLQJDPELJXLWLHV8VLQJDQHTXDOVVLJQDOVR
UHPLQGV XV WKDW HYHQ IXQFWLRQV DUH YDOXHV LQ 6FDOD ZKLFK LV FRQVLVWHQW ZLWK 6FDOD¦V
VXSSRUWRIIXQFWLRQDOSURJUDPPLQJGHVFULEHGLQPRUHGHWDLOLQ&KDSWHU
7KHPHWKRGERG\FDOOVWKH mapPHWKRGRQWKH stringsDUUD\ZKLFKWDNHVDIXQFWLRQ
OLWHUDODVDQDUJXPHQW)XQFWLRQOLWHUDOVDUH£DQRQ\PRXV¤IXQFWLRQV7KH\DUHVLPLODU
WRODPEGDVFORVXUHVEORFNVRUSURFVLQRWKHUODQJXDJHV,Q-DYD\RXZRXOGKDYHWRXVH
DQDQRQ\PRXVLQQHUFODVVKHUHWKDWLPSOHPHQWVDPHWKRGGHILQHGE\DQLQWHUIDFHHWF
,QWKLVFDVHZHSDVVHGLQWKHIROORZLQJIXQFWLRQOLWHUDO
(s:String) => s.toUpperCase()

,W WDNHV DQ DUJXPHQW OLVW ZLWK D VLQJOH String DUJXPHQW QDPHG s 7KH ERG\ RI WKH
IXQFWLRQOLWHUDOLVDIWHUWKH£DUURZ¤ =>,WFDOOV toUpperCase()RQ s7KHUHVXOWRIWKLV
FDOOLVUHWXUQHGE\WKHIXQFWLRQOLWHUDO,Q6FDODWKHODVWH[SUHVVLRQLQDIXQFWLRQLVWKH
UHWXUQYDOXHDOWKRXJK\RXFDQKDYHreturnVWDWHPHQWVHOVHZKHUHWRR7KHreturnNH\
ZRUGLVRSWLRQDOKHUHDQGLVUDUHO\XVHGH[FHSWZKHQUHWXUQLQJRXWRIWKHPLGGOHRID
EORFN HJLQDQifVWDWHPHQW 

A Taste of Scala | 13

Download at WoweBook.Com
7KHYDOXHRIWKHODVWH[SUHVVLRQLVWKHGHIDXOWUHWXUQYDOXHRIDIXQFWLRQ
1RreturnLVUHTXLUHG

6R mapSDVVHVHDFK StringLQ stringsWRWKHIXQFWLRQOLWHUDODQGEXLOGVXSDQHZFRO


OHFWLRQZLWKWKHUHVXOWVUHWXUQHGE\WKHIXQFWLRQOLWHUDO
7RH[HUFLVHWKHFRGHZHFUHDWHDQHZUpperLQVWDQFHDQGDVVLJQLWWRDYDULDEOHQDPHG
up$VLQ-DYD&DQGVLPLODUODQJXDJHVWKHV\QWD[new UpperFUHDWHVDQHZLQVWDQFH
7KHupYDULDEOHLVGHFODUHGDVDUHDGRQO\£YDOXH¤XVLQJWKHvalNH\ZRUG
)LQDOO\ ZH FDOO WKH upper PHWKRG RQ D OLVW RI VWULQJV DQG SULQW RXW WKH UHVXOW ZLWK
Console.println(...)ZKLFKLVHTXLYDOHQWWR-DYD¦VSystem.out.println(...)
:HFDQDFWXDOO\VLPSOLI\RXUVFULSWHYHQIXUWKHU&RQVLGHUWKLVVLPSOLILHGYHUVLRQRIWKH
VFULSW
// code-examples/IntroducingScala/upper2-script.scala

object Upper {
def upper(strings: String*) = strings.map(_.toUpperCase())
}

println(Upper.upper("A", "First", "Scala", "Program"))

7KLVFRGHGRHVH[DFWO\WKHVDPHWKLQJEXWZLWKDWKLUGIHZHUFKDUDFWHUV
2QWKHILUVWOLQHUpperLVQRZGHFODUHGDVDQobjectZKLFKLVDVLQJOHWRQ:HDUHGH
FODULQJDFODVVEXWWKH6FDODUXQWLPHZLOORQO\HYHUFUHDWHRQHLQVWDQFHRIUpper <RX
FDQ¦WZULWHnew UpperIRUH[DPSOH 6FDODXVHVobjectsIRUVLWXDWLRQVZKHUHRWKHUODQ
JXDJHVZRXOGXVH£FODVVOHYHO¤PHPEHUVOLNH staticVLQ-DYD:HGRQ¦WUHDOO\QHHG
PRUHWKDQRQHLQVWDQFHKHUHVRDVLQJOHWRQLVILQH

:K\ GRHVQ¦W 6FDOD VXSSRUW staticV" 6LQFH HYHU\WKLQJ LV DQ REMHFW LQ
6FDODWKH objectFRQVWUXFWNHHSVWKLVSROLF\FRQVLVWHQW-DYD¦V static
PHWKRGVDQGILHOGVDUHQRWWLHGWRDQDFWXDOLQVWDQFH

1RWHWKDWWKLVFRGHLVIXOO\WKUHDGVDIH:HGRQ¦WGHFODUHDQ\YDULDEOHVWKDWPLJKWFDXVH
WKUHDGVDIHW\LVVXHV7KH$3,PHWKRGVZHXVHDUHDOVRWKUHDGVDIH7KHUHIRUHZHGRQ¦W
QHHGPXOWLSOHLQVWDQFHV$VLQJOHWRQobjectZRUNVILQH
7KHLPSOHPHQWDWLRQRIupperRQWKHVHFRQGOLQHLVDOVRVLPSOHU6FDODFDQXVXDOO\LQIHU
WKHUHWXUQW\SHRIWKHPHWKRG EXWQRWWKHW\SHVRIWKHPHWKRGDUJXPHQWV VRZHGURS
WKHH[SOLFLWGHFODUDWLRQ$OVREHFDXVHWKHUHLVRQO\RQHH[SUHVVLRQLQWKHPHWKRGERG\
ZHGURSWKHEUDFHVDQGSXWWKHHQWLUHPHWKRGGHILQLWLRQRQRQHOLQH7KHHTXDOVVLJQ
EHIRUHWKHPHWKRGERG\WHOOVWKHFRPSLOHUDVZHOODVWKHKXPDQUHDGHUZKHUHWKH
PHWKRGERG\EHJLQV

14 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
:HKDYHDOVRH[SORLWHGDVKRUWKDQGIRUWKHIXQFWLRQOLWHUDO3UHYLRXVO\ZHZURWHLWDV
IROORZV
(s:String) => s.toUpperCase()

:HFDQVKRUWHQLWWRWKHIROORZLQJH[SUHVVLRQ
_.toUpperCase()

%HFDXVHmapWDNHVRQHDUJXPHQWDIXQFWLRQZHFDQXVHWKH£SODFHKROGHU¤LQGLFDWRU_
LQVWHDGRIDQDPHGSDUDPHWHU7KDWLVWKH_DFWVOLNHDQDQRQ\PRXVYDULDEOHWRZKLFK
HDFKVWULQJZLOOEHDVVLJQHGEHIRUH toUpperCaseLVFDOOHG1RWHWKDWWKH StringW\SHLV
LQIHUUHGIRUXVWRR$VZHZLOOVHH6FDODXVHV_DVD£ZLOGFDUG¤LQVHYHUDOFRQWH[WV
<RXFDQDOVRXVHWKLVVKRUWKDQGV\QWD[LQVRPHPRUHFRPSOH[IXQFWLRQOLWHUDOVDVZH
ZLOOVHHLQ&KDSWHU
2QWKHODVWOLQHXVLQJDQ objectUDWKHUWKDQD classVLPSOLILHVWKHFRGH,QVWHDGRI
FUHDWLQJDQLQVWDQFHZLWK new UpperZHFDQMXVWFDOOWKH upperPHWKRGRQWKH Upper
REMHFWGLUHFWO\ QRWHKRZWKLVORRNVOLNHWKHV\QWD[\RXZRXOGXVHZKHQFDOOLQJVWDWLF
PHWKRGVLQD-DYDFODVV 
)LQDOO\6FDODDXWRPDWLFDOO\LPSRUWVPDQ\PHWKRGVIRU,2OLNHprintlnVRZHGRQ¦W
QHHGWRFDOO Console.println():HFDQMXVWXVH printlnE\LWVHOI 6HH £7KH3UHGHI
2EMHFW¤RQSDJHIRUGHWDLOVRQWKHW\SHVDQGPHWKRGVWKDWDUHDXWRPDWLFDOO\LP
SRUWHGRUGHILQHG
/HW¦VGRRQHODVWUHIDFWRULQJ&RQYHUWWKHVFULSWLQWRDFRPSLOHGFRPPDQGOLQHWRRO
// code-examples/IntroducingScala/upper3.scala

object Upper {
def main(args: Array[String]) = {
args.map(_.toUpperCase()).foreach(printf("%s ",_))
println("")
}
}

1RZWKH upperPHWKRGKDVEHHQUHQDPHG main%HFDXVH UpperLVDQ objectWKLV main


PHWKRGZRUNVH[DFWO\OLNHDstatic mainPHWKRGLQD-DYDFODVV,WLVWKHHQWU\SRLQWWR
WKHUpperDSSOLFDWLRQ

,Q6FDODmainPXVWEHDPHWKRGLQDQobject ,Q-DYDmainPXVWEHD
staticPHWKRGLQDclass 7KHFRPPDQGOLQHDUJXPHQWVIRUWKHDSSOL
FDWLRQDUHSDVVHGWRmainLQDQDUUD\RIVWULQJVHJargs: Array[String]

7KHILUVWOLQHLQVLGHWKHmainPHWKRGXVHVWKHVDPHVKRUWKDQGQRWDWLRQIRUmapWKDWZH
MXVWH[DPLQHG
args.map(_.toUpperCase())...

A Taste of Scala | 15

Download at WoweBook.Com
7KHFDOOWRmapUHWXUQVDQHZFROOHFWLRQ:HLWHUDWHWKURXJKLWZLWKforeach:HXVHD
_SODFHKROGHUVKRUWFXWDJDLQLQDQRWKHUIXQFWLRQOLWHUDOWKDWZHSDVVWRforeach,QWKLV
FDVHHDFKVWULQJLQWKHFROOHFWLRQLVSDVVHGDVDQDUJXPHQWWRprintf
...foreach(printf("%s ",_))

7REHFOHDUWKHVHWZRXVHVRI _DUHFRPSOHWHO\LQGHSHQGHQWRIHDFKRWKHU0HWKRG
FKDLQLQJDQGIXQFWLRQOLWHUDOVKRUWKDQGVDVLQWKLVH[DPSOHFDQWDNHVRPHJHWWLQJXVHG
WREXWRQFH\RXDUHFRPIRUWDEOHZLWKWKHPWKH\\LHOGYHU\UHDGDEOHFRGHZLWKPLQLPDO
XVHRIWHPSRUDU\YDULDEOHV
7KHODVWOLQHLQmainDGGVDILQDOOLQHIHHGWRWKHRXWSXW
7KLVWLPH\RXPXVWILUVWFRPSLOHWKHFRGHWRD-90FODVVILOHXVLQJscalac
scalac upper3.scala

<RXVKRXOGQRZKDYHDILOHQDPHG8SSHUFODVVMXVWDVLI\RXKDGMXVWFRPSLOHGD-DYD
FODVV

<RXPD\KDYHQRWLFHGWKDWWKHFRPSLOHUGLGQRWFRPSODLQZKHQWKH
ILOHZDVQDPHGXSSHUVFDODDQGWKH objectZDVQDPHG Upper8QOLNH
-DYDWKHILOHQDPHGRHVQ¦WKDYHWRPDWFKWKHQDPHRIWKHW\SHZLWK
public VFRSH :H¦OO H[SORUH WKH YLVLELOLW\ UXOHV LQ £9LVLELOLW\
5XOHV¤RQSDJH ,QIDFWXQOLNH-DYD\RXFDQKDYHDVPDQ\SXEOLF
W\SHVLQDVLQJOHILOHDV\RXZDQW)XUWKHUPRUHWKHGLUHFWRU\ORFDWLRQRI
DILOHGRHVQ¦WKDYHWRPDWFKWKHSDFNDJHGHFODUDWLRQ+RZHYHU\RXFDQ
FHUWDLQO\IROORZWKH-DYDFRQYHQWLRQVLI\RXZDQWWR

1RZ\RXFDQH[HFXWHWKLVFRPPDQGIRUDQ\OLVWRIVWULQJV+HUHLVDQH[DPSOH
scala -cp . Upper Hello World!

7KH-cp .RSWLRQDGGVWKHFXUUHQWGLUHFWRU\WRWKHVHDUFK£FODVVSDWK¤<RXVKRXOGJHW
WKHIROORZLQJRXWSXW
HELLO WORLD!

7KHUHIRUHZHKDYHPHWWKHUHTXLUHPHQWWKDWDSURJUDPPLQJODQJXDJHERRNPXVWVWDUW
ZLWKD£KHOORZRUOG¤SURJUDP

A Taste of Concurrency
7KHUHDUHPDQ\UHDVRQVWREHVHGXFHGE\6FDOD2QHUHDVRQLVWKH$FWRUV$3,LQFOXGHG
LQWKH6FDODOLEUDU\ZKLFKLVEDVHGRQWKHUREXVW$FWRUVFRQFXUUHQF\PRGHOEXLOWLQWR
(UODQJ VHH>+DOOHU@ +HUHLVDQH[DPSOHWRZKHW\RXUDSSHWLWH
,QWKH$FWRUPRGHORIFRQFXUUHQF\ >$JKD@ LQGHSHQGHQWVRIWZDUHHQWLWLHVFDOOHG
$FWRUV VKDUH QR VWDWH LQIRUPDWLRQ ZLWK HDFK RWKHU ,QVWHDG WKH\ FRPPXQLFDWH E\

16 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
H[FKDQJLQJPHVVDJHV%\HOLPLQDWLQJWKHQHHGWRV\QFKURQL]HDFFHVVWRVKDUHGPXWDEOH
VWDWHLWLVIDUHDVLHUWRZULWHUREXVWFRQFXUUHQWDSSOLFDWLRQV
,QWKLVH[DPSOHLQVWDQFHVLQDJHRPHWULFShapeKLHUDUFK\DUHVHQWWRDQ$FWRUIRUGUDZ
LQJRQDGLVSOD\,PDJLQHDVFHQDULRZKHUHDUHQGHULQJ£IDUP¤JHQHUDWHVVFHQHVLQDQ
DQLPDWLRQ$VWKHUHQGHULQJRIDVFHQHLVFRPSOHWHGWKHVKDSH£SULPLWLYHV¤WKDWDUH
SDUWRIWKHVFHQHDUHVHQWWRDQ$FWRUIRUDGLVSOD\VXEV\VWHP
7REHJLQZHGHILQHDShapeFODVVKLHUDUFK\
// code-examples/IntroducingScala/shapes.scala

package shapes {
class Point(val x: Double, val y: Double) {
override def toString() = "Point(" + x + "," + y + ")"
}

abstract class Shape() {


def draw(): Unit
}

class Circle(val center: Point, val radius: Double) extends Shape {


def draw() = println("Circle.draw: " + this)
override def toString() = "Circle(" + center + "," + radius + ")"
}

class Rectangle(val lowerLeft: Point, val height: Double, val width: Double)
extends Shape {
def draw() = println("Rectangle.draw: " + this)
override def toString() =
"Rectangle(" + lowerLeft + "," + height + "," + width + ")"
}

class Triangle(val point1: Point, val point2: Point, val point3: Point)
extends Shape {
def draw() = println("Triangle.draw: " + this)
override def toString() =
"Triangle(" + point1 + "," + point2 + "," + point3 + ")"
}
}

7KHShapeFODVVKLHUDUFK\LVGHILQHGLQDshapesSDFNDJH<RXFDQGHFODUHWKHSDFNDJH
XVLQJ-DYDV\QWD[EXW6FDODDOVRVXSSRUWVDV\QWD[VLPLODUWR&¦V£QDPHVSDFH¤V\QWD[
ZKHUHWKHHQWLUHGHFODUDWLRQLVVFRSHGXVLQJFXUO\EUDFHVDVXVHGKHUH7KH-DYDVW\OH
SDFNDJHGHFODUDWLRQV\QWD[LVIDUPRUHFRPPRQO\XVHGKRZHYHUEHLQJERWKFRPSDFW
DQGUHDGDEOH
7KHPointFODVVUHSUHVHQWVDWZRGLPHQVLRQDOSRLQWRQDSODQH1RWHWKHDUJXPHQWOLVW
DIWHUWKHFODVVQDPH7KRVHDUHFRQVWUXFWRUSDUDPHWHUV,Q6FDODWKHZKROHFODVVERG\
LVWKHFRQVWUXFWRUVR\RXOLVWWKHDUJXPHQWVIRUWKHSULPDU\FRQVWUXFWRUDIWHUWKHFODVV
QDPH DQG EHIRUH WKH FODVV ERG\ :H¦OO VHH KRZ WR GHILQH DX[LOLDU\ FRQVWUXFWRUV LQ
£&RQVWUXFWRUV LQ 6FDOD¤ RQ SDJH   %HFDXVH ZH SXW WKH val NH\ZRUG EHIRUH HDFK
SDUDPHWHUGHFODUDWLRQWKH\DUHDXWRPDWLFDOO\FRQYHUWHGWRUHDGRQO\ILHOGVZLWKWKH

A Taste of Concurrency | 17

Download at WoweBook.Com
VDPHQDPHVZLWKSXEOLFUHDGHUPHWKRGVRIWKHVDPHQDPH7KDWLVZKHQ\RXLQVWDQ
WLDWHDPointLQVWDQFHHJpoint\RXFDQUHDGWKHILHOGVXVLQJpoint.xDQGpoint.y,I
\RXZDQWPXWDEOHILHOGVWKHQXVHWKHNH\ZRUGvar:H¦OOH[SORUHYDULDEOHGHFODUDWLRQV
DQGWKHvalDQGvarNH\ZRUGVLQ£9DULDEOH'HFODUDWLRQV¤RQSDJH
7KHERG\RIPointGHILQHVRQHPHWKRGDQRYHUULGHRIWKHIDPLOLDUtoStringPHWKRGLQ
-DYD OLNH ToStringLQ& 1RWHWKDW6FDODOLNH&UHTXLUHVWKH overrideNH\ZRUG
ZKHQHYHU \RX RYHUULGH D FRQFUHWH PHWKRG 8QOLNH & \RX GRQ¦W KDYH WR XVH D
virtualNH\ZRUGRQWKHRULJLQDOFRQFUHWHPHWKRG,QIDFWWKHUHLVQRvirtualNH\ZRUG
LQ6FDOD$VEHIRUHZHRPLWWKHFXUO\EUDFHV {...} DURXQGWKHERG\RItoStringVLQFH
LWKDVRQO\RQHH[SUHVVLRQ
ShapeLVDQDEVWUDFWFODVV$EVWUDFWFODVVHVLQ6FDODDUHVLPLODUWRWKRVHLQ-DYDDQG&
:HFDQ¦WLQVWDQWLDWHLQVWDQFHVRIDEVWUDFWFODVVHVHYHQZKHQDOOWKHLUILHOGDQGPHWKRG
PHPEHUVDUHFRQFUHWH
,QWKLVFDVH6KDSHGHFODUHVDQDEVWUDFWdrawPHWKRG:HNQRZLWLVDEVWUDFWEHFDXVHLW
KDVQRERG\1R abstractNH\ZRUGLVUHTXLUHGRQWKHPHWKRG$EVWUDFWPHWKRGVLQ
6FDOD DUH MXVW OLNH DEVWUDFW PHWKRGV LQ -DYD DQG & 6HH £2YHUULGLQJ 0HPEHUV RI
&ODVVHVDQG7UDLWV¤RQSDJHIRUPRUHGHWDLOV
7KHdrawPHWKRGUHWXUQVUnitZKLFKLVDW\SHWKDWLVURXJKO\HTXLYDOHQWWRvoidLQ&
GHULYHGODQJXDJHVOLNH-DYDHWF 6HH£7KH6FDOD7\SH+LHUDUFK\¤RQSDJHIRUPRUH
GHWDLOV
CircleLVGHFODUHGDVDFRQFUHWHVXEFODVVRIShape,WGHILQHVWKHdrawPHWKRGWRVLPSO\
SULQWDPHVVDJHWRWKHFRQVROHCircleDOVRRYHUULGHVtoString
Rectangle LV DOVR D FRQFUHWH VXEFODVV RI Shape WKDW GHILQHV draw DQG RYHUULGHV
toString)RUVLPSOLFLW\ZHDVVXPHLWLVQRWURWDWHGUHODWLYHWRWKH[DQG\D[HV+HQFH
DOOZHQHHGLVRQHSRLQWWKHORZHUOHIWKDQGSRLQWZLOOGRDQGWKHKHLJKWDQGZLGWKRI
WKHUHFWDQJOH
TriangleIROORZVWKHVDPHSDWWHUQ,WWDNHVWKUHHPointsDVLWVFRQVWUXFWRUDUJXPHQWV
%RWK drawPHWKRGVLQ Circle RectangleDQG TriangleXVH this$VLQ-DYDDQG&
thisLVKRZDQLQVWDQFHUHIHUVWRLWVHOI,QWKLVFRQWH[WZKHUHthisLVWKHULJKWKDQGVLGH
RID6WULQJFRQFDWHQDWLRQH[SUHVVLRQ XVLQJWKHSOXVVLJQ  this.toStringLVLQYRNHG
LPSOLFLWO\

2IFRXUVHLQDUHDODSSOLFDWLRQ\RXZRXOGQRWLPSOHPHQWGUDZLQJLQ
£GRPDLQPRGHO¤FODVVHVOLNHWKLVVLQFHWKHLPSOHPHQWDWLRQVZRXOGGH
SHQGRQGHWDLOVOLNHWKHRSHUDWLQJV\VWHPSODWIRUPJUDSKLFV$3,HWF
:HZLOOVHHDEHWWHUGHVLJQDSSURDFKZKHQZHGLVFXVVWUDLWVLQ&KDSWHU

1RZWKDWZHKDYHGHILQHGRXUVKDSHVW\SHVOHW¦VUHWXUQWR$FWRUV:HGHILQHDQ$FWRU
WKDWUHFHLYHV£PHVVDJHV¤WKDWDUHVKDSHVWRGUDZ

18 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
// code-examples/IntroducingScala/shapes-actor.scala

package shapes {
import scala.actors._
import scala.actors.Actor._

object ShapeDrawingActor extends Actor {


def act() {
loop {
receive {
case s: Shape => s.draw()
case "exit" => println("exiting..."); exit
case x: Any => println("Error: Unknown message! " + x)
}
}
}
}
}

7KH $FWRU LV GHFODUHG WR EH SDUW RI WKH shapes SDFNDJH 1H[W ZH KDYH WZR LPSRUW
VWDWHPHQWV
7KHILUVWLPSRUWVWDWHPHQWLPSRUWVDOOWKHW\SHVLQWKHscala.actorsSDFNDJH,Q6FDOD
WKHXQGHUVFRUH_LVXVHGWKHZD\WKHVWDU*LVXVHGLQ-DYD

%HFDXVH*LVDYDOLGFKDUDFWHUIRUDIXQFWLRQQDPHLWFDQ¦WEHXVHGDVWKH
importZLOGFDUG,QVWHDG_LVUHVHUYHGIRUWKLVSXUSRVH

$OOWKHPHWKRGVDQGSXEOLFILHOGVIURPActorDUHLPSRUWHGE\WKHVHFRQGimport7KHVH
DUHQRWstaticLPSRUWVIURPWKHActorW\SHDVWKH\ZRXOGEHLQ-DYD5DWKHUWKH\DUH
LPSRUWHGIURPDQobjectWKDWLVDOVRQDPHGActor7KHclassDQGobjectFDQKDYHWKH
VDPHQDPHDVZHZLOOVHHLQ£&RPSDQLRQ2EMHFWV¤RQSDJH
2XU$FWRUFODVVGHILQLWLRQShapeDrawingActorLVDQobjectWKDWH[WHQGVActor WKHW\SH
QRWWKH object 7KH actPHWKRGLVRYHUULGGHQWRGRWKHXQLTXHZRUNRIWKH$FWRU
%HFDXVH act LV DQ DEVWUDFW PHWKRG ZH GRQ¦W QHHG WR H[SOLFLWO\ RYHUULGH LW ZLWK WKH
overrideNH\ZRUG2XU$FWRUORRSVLQGHILQLWHO\ZDLWLQJIRULQFRPLQJPHVVDJHV
'XULQJHDFKSDVVLQWKHORRSWKHreceivePHWKRGLVFDOOHG,WEORFNVXQWLODQHZPHVVDJH
DUULYHV:K\LVWKHFRGHDIWHUreceiveHQFORVHGLQFXUO\EUDFHV{...}DQGQRWSDUHQWKHVHV
(...)":HZLOOOHDUQODWHUWKDWWKHUHDUHFDVHVZKHUHWKLVVXEVWLWXWLRQLVDOORZHGDQGLV
TXLWHXVHIXO VHH&KDSWHU )RUQRZZKDW\RXQHHGWRNQRZLVWKDWWKHH[SUHVVLRQV
LQVLGHWKHEUDFHVFRQVWLWXWHDVLQJOHIXQFWLRQOLWHUDOWKDWLVSDVVHGWRreceive7KLVIXQF
WLRQOLWHUDOGRHVDSDWWHUQPDWFKRQWKHPHVVDJHLQVWDQFHWRGHFLGHKRZWRKDQGOHWKH
PHVVDJH%HFDXVHRIWKH caseFODXVHVLWORRNVOLNHDW\SLFDOVZLWFKVWDWHPHQWLQ-DYD
IRUH[DPSOHDQGWKHEHKDYLRULVYHU\VLPLODU

A Taste of Concurrency | 19

Download at WoweBook.Com
7KHILUVWcaseGRHVDW\SHFRPSDULVRQZLWKWKHPHVVDJH 7KHUHLVQRH[SOLFLWYDULDEOH
IRUWKHPHVVDJHLQVWDQFHLQWKHFRGHLWLVLQIHUUHG ,IWKHPHVVDJHLVRIW\SHShapeWKH
ILUVWcasePDWFKHV7KHPHVVDJHLQVWDQFHLVFDVWWRDShapeDQGDVVLJQHGWRWKHYDULDEOH
sDQGWKHQWKHdrawPHWKRGLVFDOOHGRQLW
,I WKH PHVVDJH LV QRW D Shape WKH VHFRQG case LV WULHG ,I WKH PHVVDJH LV WKH VWULQJ
"exit"WKH$FWRUSULQWVDPHVVDJHDQGWHUPLQDWHVH[HFXWLRQ$FWRUVVKRXOGXVXDOO\
KDYHDZD\WRH[LWJUDFHIXOO\
7KHODVW caseFODXVHKDQGOHVDQ\RWKHUPHVVDJHLQVWDQFHWKHUHE\IXQFWLRQLQJDVWKH
GHIDXOWFDVH7KH$FWRUUHSRUWVDQHUURUDQGWKHQGURSVWKHPHVVDJHAnyLVWKHSDUHQW
RIDOOW\SHVLQWKH6FDODW\SHKLHUDUFK\OLNH ObjectLVWKHURRWW\SHLQ-DYDDQGRWKHU
ODQJXDJHV+HQFHWKLVFDVHFODXVHZLOOPDWFKDQ\PHVVDJHRIDQ\W\SH3DWWHUQPDWFKLQJ
LVHDJHUZHKDYHWRSXWWKLVFDVHFODXVHDWWKHHQGVRLWGRHVQ¦WFRQVXPHWKHPHVVDJHV
ZHDUHH[SHFWLQJ
5HFDOO WKDW ZH GHFODUHG draw DV DQ DEVWUDFW PHWKRG LQ Shape DQG ZH LPSOHPHQWHG
drawLQWKHFRQFUHWHVXEFODVVHV+HQFHWKHFRGHLQWKHILUVW caseVWDWHPHQWLQYRNHVD
SRO\PRUSKLFRSHUDWLRQ

Pattern Matching Versus Polymorphism


3DWWHUQPDWFKLQJSOD\VDFHQWUDOUROHLQIXQFWLRQDOSURJUDPPLQJMXVWDVSRO\PRUSKLVP
SOD\VDFHQWUDOUROHLQREMHFWRULHQWHGSURJUDPPLQJ)XQFWLRQDOSDWWHUQPDWFKLQJLV
PXFK PRUH LPSRUWDQW DQG VRSKLVWLFDWHG WKDQ WKH FRUUHVSRQGLQJ switch/case VWDWH
PHQWVIRXQGLQPRVWLPSHUDWLYHODQJXDJHVOLNH-DYD:HZLOOH[DPLQH6FDOD¦VVXSSRUW
IRUSDWWHUQPDWFKLQJLQPRUHGHWDLOLQ&KDSWHU,QRXUH[DPSOHKHUHZHFDQEHJLQWR
VHHWKDWMRLQLQJIXQFWLRQDOVW\OHSDWWHUQPDWFKLQJZLWKREMHFWRULHQWHGSRO\PRUSKLF
GLVSDWFKLQJLVDSRZHUIXOFRPELQDWLRQWKDWLVDEHQHILWRIPL[HGSDUDGLJPODQJXDJHV
OLNH6FDOD

)LQDOO\KHUHLVDVFULSWWKDWXVHVWKHShapeDrawingActor$FWRU
// code-examples/IntroducingScala/shapes-actor-script.scala

import shapes._

ShapeDrawingActor.start()

ShapeDrawingActor ! new Circle(new Point(0.0,0.0), 1.0)


ShapeDrawingActor ! new Rectangle(new Point(0.0,0.0), 2, 5)
ShapeDrawingActor ! new Triangle(new Point(0.0,0.0),
new Point(1.0,0.0),
new Point(0.0,1.0))
ShapeDrawingActor ! 3.14159

ShapeDrawingActor ! "exit"

20 | Chapter 1:—Zero to Sixty: Introducing Scala

Download at WoweBook.Com
7KHVKDSHVLQWKHshapesSDFNDJHDUHLPSRUWHG
7KHShapeDrawingActor$FWRULVVWDUWHG%\GHIDXOWLWUXQVLQLWVRZQWKUHDG WKHUHDUH
DOWHUQDWLYHVZHZLOOGLVFXVVLQ&KDSWHU ZDLWLQJIRUPHVVDJHV
)LYHPHVVDJHVDUHVHQWWRWKH$FWRUXVLQJWKHV\QWD[actor ! message7KHILUVWPHVVDJH
VHQGVD CircleLQVWDQFH7KH$FWRU£GUDZV¤WKHFLUFOH7KHVHFRQGPHVVDJHVHQGVD
RectanglePHVVDJH7KH$FWRU£GUDZV¤WKHUHFWDQJOH7KHWKLUGPHVVDJHGRHVWKHVDPH
WKLQJIRUDTriangle7KHIRXUWKPHVVDJHVHQGVDDoubleWKDWLVDSSUR[LPDWHO\HTXDOWR
3L7KLVLVDQXQNQRZQPHVVDJHIRUWKH$FWRUVRLWMXVWSULQWVDQHUURUPHVVDJH7KH
ILQDOPHVVDJHVHQGVDQ£H[LW¤VWULQJZKLFKFDXVHVWKH$FWRUWRWHUPLQDWH
7R WU\ RXW WKH $FWRU H[DPSOH VWDUW E\ FRPSLOLQJ WKH ILUVW WZR ILOHV <RX FDQ JHW
WKH VRXUFHV IURP WKH 2¦5HLOO\ GRZQORDG VLWH VHH £*HWWLQJ WKH &RGH ([DP
SOHV¤RQSDJH[L[IRUGHWDLOV RU\RXFDQFUHDWHWKHP\RXUVHOI
8VHWKHIROORZLQJFRPPDQGWRFRPSLOHWKHILOHV
scalac shapes.scala shapes-actor.scala

:KLOHWKHVRXUFHILOHQDPHVDQGORFDWLRQVGRQ¦WKDYHWRPDWFKWKHILOHFRQWHQWV\RX
ZLOOQRWLFHWKDWWKHJHQHUDWHGFODVVILOHVDUHZULWWHQWRDVKDSHVGLUHFWRU\DQGWKHUHLV
RQHFODVVILOHIRUHDFKFODVVZHGHILQHG7KHFODVVILOHQDPHVDQGORFDWLRQVPXVWFRQIRUP
WRWKH-90UHTXLUHPHQWV
1RZ\RXFDQUXQWKHVFULSWWRVHHWKH$FWRULQDFWLRQ
scala -cp . shapes-actor-script.scala

<RXVKRXOGVHHWKHIROORZLQJRXWSXW
Circle.draw: Circle(Point(0.0,0.0),1.0)
Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,5.0)
Triangle.draw: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0))
Error: Unknown message! 3.14159
exiting...

)RUPRUHRQ$FWRUVVHH&KDSWHU

Recap and What’s Next


:HPDGHWKHFDVHIRU6FDODDQGJRW\RXVWDUWHGZLWKWZRVDPSOH6FDODSURJUDPVRQH
RIZKLFKJDYH\RXDWDVWHRI6FDOD¦V$FWRUVOLEUDU\IRUFRQFXUUHQF\1H[WZH¦OOGLYHLQWR
PRUH6FDODV\QWD[HPSKDVL]LQJYDULRXVNH\VWURNHHFRQRPLFDOZD\VRIJHWWLQJORWVRI
ZRUNGRQH

Recap and What’s Next | 21

Download at WoweBook.Com
Download at WoweBook.Com
CHAPTER 2
Type Less, Do More

In This Chapter
:HHQGHGWKHSUHYLRXVFKDSWHUZLWKDIHZ£WHDVHU¤H[DPSOHVRI6FDODFRGH7KLVFKDSWHU
GLVFXVVHVXVHVRI6FDODWKDWSURPRWHVXFFLQFWIOH[LEOHFRGH:H¦OOGLVFXVVRUJDQL]DWLRQ
RIILOHVDQGSDFNDJHVLPSRUWLQJRWKHUW\SHVYDULDEOHGHFODUDWLRQVPLVFHOODQHRXVV\Q
WD[FRQYHQWLRQVDQGDIHZRWKHUFRQFHSWV:H¦OOHPSKDVL]HKRZWKHFRQFLVHV\QWD[RI
6FDODKHOSV\RXZRUNEHWWHUDQGIDVWHU
6FDOD¦VV\QWD[LVHVSHFLDOO\XVHIXOZKHQZULWLQJVFULSWV6HSDUDWHFRPSLOHDQGUXQVWHSV
DUHQ¦WUHTXLUHGIRUVLPSOHSURJUDPVWKDWKDYHIHZGHSHQGHQFLHVRQOLEUDULHVRXWVLGHRI
ZKDW6FDODSURYLGHV<RXFRPSLOHDQGUXQVXFKSURJUDPVLQRQHVKRWZLWKWKH scala
FRPPDQG,I\RX¦YHGRZQORDGHGWKHH[DPSOHFRGHIRUWKLVERRNPDQ\RIWKHVPDOOHU
H[DPSOHVFDQEHUXQXVLQJWKH scalaFRPPDQGHJ scala filename.scala6HHWKH
5($'0(W[WILOHVLQHDFKFKDSWHU¦VFRGHH[DPSOHVIRUPRUHGHWDLOV6HHDOVR£&RP
PDQG/LQH7RROV¤RQSDJHIRUPRUHLQIRUPDWLRQDERXWXVLQJWKHscalaFRPPDQG

Semicolons
<RXPD\KDYHDOUHDG\QRWLFHGWKDWWKHUHZHUHYHU\IHZVHPLFRORQVLQWKHFRGHH[DPSOHV
LQWKHSUHYLRXVFKDSWHU<RXFDQXVHVHPLFRORQVWRVHSDUDWHVWDWHPHQWVDQGH[SUHV
VLRQVDVLQ-DYD&3+3DQGVLPLODUODQJXDJHV,QPRVWFDVHVWKRXJK6FDODEHKDYHV
OLNHPDQ\VFULSWLQJODQJXDJHVLQWUHDWLQJWKHHQGRIWKHOLQHDVWKHHQGRIDVWDWHPHQW
RUDQH[SUHVVLRQ:KHQDVWDWHPHQWRUH[SUHVVLRQLVWRRORQJIRURQHOLQH6FDODFDQ
XVXDOO\LQIHUZKHQ\RXDUHFRQWLQXLQJRQWRWKHQH[WOLQHDVVKRZQLQWKLVH[DPSOH
// code-examples/TypeLessDoMore/semicolon-example-script.scala

// Trailing equals sign indicates more code on next line


def equalsign = {
val reallySuperLongValueNameThatGoesOnForeverSoYouNeedANewLine =
"wow that was a long value name"

println(reallySuperLongValueNameThatGoesOnForeverSoYouNeedANewLine)

23

Download at WoweBook.Com
}

// Trailing opening curly brace indicates more code on next line


def equalsign2(s: String) = {
println("equalsign2: " + s)
}

// Trailing comma, operator, etc. indicates more code on next line


def commas(s1: String,
s2: String) = {
println("comma: " + s1 +
", " + s2)
}

:KHQ\RXZDQWWRSXWPXOWLSOHVWDWHPHQWVRUH[SUHVVLRQVRQWKHVDPHOLQH\RXFDQ
XVH VHPLFRORQV WR VHSDUDWH WKHP :H XVHG WKLV WHFKQLTXH LQ WKH ShapeDrawingActor
H[DPSOHLQ£$7DVWHRI&RQFXUUHQF\¤RQSDJH
case "exit" => println("exiting..."); exit

7KLVFRGHFRXOGDOVREHZULWWHQDVIROORZV
...
case "exit" =>
println("exiting...")
exit
...

<RXPLJKWZRQGHUZK\\RXGRQ¦WQHHGFXUO\EUDFHV {...} DURXQGWKHWZRVWDWHPHQWV


DIWHUWKH case ... =>OLQH<RXFDQSXWWKHPLQLI\RXZDQWEXWWKHFRPSLOHUNQRZV
ZKHQ\RX¦YHUHDFKHGWKHHQGRIWKH£EORFN¤ZKHQLWILQGVWKHQH[WcaseFODXVHRUWKH
FXUO\EUDFH } WKDWHQGVWKHHQFORVLQJEORFNIRUDOOWKHcaseFODXVHV
2PLWWLQJRSWLRQDOVHPLFRORQVPHDQVIHZHUFKDUDFWHUVWRW\SHDQGIHZHUFKDUDFWHUVWR
FOXWWHU\RXUFRGH%UHDNLQJVHSDUDWHVWDWHPHQWVRQWRWKHLURZQOLQHVLQFUHDVHV\RXU
FRGH¦VUHDGDELOLW\

Variable Declarations
6FDODDOORZV\RXWRGHFLGHZKHWKHUDYDULDEOHLVLPPXWDEOH UHDGRQO\ RUQRW UHDG
ZULWH  ZKHQ \RX GHFODUH LW $Q LPPXWDEOH £YDULDEOH¤ LV GHFODUHG ZLWK WKH NH\ZRUG
val WKLQNYDOXHREMHFW 
val array: Array[String] = new Array(5)

7R EH PRUH SUHFLVH WKH array UHIHUHQFH FDQQRW EH FKDQJHG WR SRLQW WR D GLIIHUHQW
ArrayEXWWKHDUUD\LWVHOIFDQEHPRGLILHGDVVKRZQLQWKHIROORZLQJscalaVHVVLRQ
scala> val array: Array[String] = new Array(5)
array: Array[String] = Array(null, null, null, null, null)

scala> array = new Array(2)


<console>:5: error: reassignment to val
array = new Array(2)

24 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
^

scala> array(0) = "Hello"

scala> array
res3: Array[String] = Array(Hello, null, null, null, null)

scala>

$QLPPXWDEOHvalPXVWEHLQLWLDOL]HG¢WKDWLVGHILQHG¢ZKHQLWLVGHFODUHG
$PXWDEOHYDULDEOHLVGHFODUHGZLWKWKHNH\ZRUGvar
scala> var stockPrice: Double = 100.
stockPrice: Double = 100.0

scala> stockPrice = 10.


stockPrice: Double = 10.0

scala>

6FDODDOVRUHTXLUHV\RXWRLQLWLDOL]HDvarZKHQLWLVGHFODUHG<RXFDQDVVLJQDQHZYDOXH
WRD varDVRIWHQDV\RXZDQW$JDLQWREHSUHFLVHWKH stockPriceUHIHUHQFHFDQEH
FKDQJHGWRSRLQWWRDGLIIHUHQW DoubleREMHFW HJ 10. ,QWKLVFDVHWKHREMHFWWKDW
stockPriceUHIHUVWRFDQ¦WEHFKDQJHGEHFDXVHDoublesLQ6FDODDUHLPPXWDEOH
7KHUHDUHDIHZH[FHSWLRQVWRWKHUXOHWKDW\RXPXVWLQLWLDOL]HvalVDQGvarVZKHQWKH\
DUHGHFODUHG%RWKNH\ZRUGVFDQEHXVHGZLWKFRQVWUXFWRUSDUDPHWHUV:KHQXVHGDV
FRQVWUXFWRUSDUDPHWHUVWKHPXWDEOHRULPPXWDEOHYDULDEOHVVSHFLILHGZLOOEHLQLWLDOL]HG
ZKHQDQREMHFWLVLQVWDQWLDWHG%RWKNH\ZRUGVFDQEHXVHGWRGHFODUH£DEVWUDFW¤ XQ
LQLWLDOL]HG YDULDEOHVLQDEVWUDFWW\SHV$OVRGHULYHGW\SHVFDQRYHUULGH valVGHFODUHG
LQVLGHSDUHQWW\SHV:H¦OOGLVFXVVWKHVHH[FHSWLRQVLQ&KDSWHU
6FDODHQFRXUDJHV\RXWRXVHLPPXWDEOHYDOXHVZKHQHYHUSRVVLEOH$VZHZLOOVHHWKLV
SURPRWHVEHWWHUREMHFWRULHQWHGGHVLJQDQGLVFRQVLVWHQWZLWKWKHSULQFLSOHVRI£SXUH¤
IXQFWLRQDOSURJUDPPLQJ,WPD\WDNHVRPHJHWWLQJXVHGWREXW\RX¦OOILQGDQHZIRXQG
FRQILGHQFHLQ\RXUFRGHZKHQLWLVZULWWHQLQDQLPPXWDEOHVW\OH

7KH varDQG valNH\ZRUGVRQO\VSHFLI\ZKHWKHUWKHUHIHUHQFHFDQEH


FKDQJHGWRUHIHUWRDGLIIHUHQWREMHFW var RUQRW val 7KH\GRQ¦WVSHF
LI\ZKHWKHURUQRWWKHREMHFWWKH\UHIHUHQFHLVPXWDEOH

Method Declarations
,Q&KDSWHUZHVDZVHYHUDOH[DPSOHVRIKRZWRGHILQHPHWKRGVZKLFKDUHIXQFWLRQV
WKDWDUHPHPEHUVRIDFODVV0HWKRGGHILQLWLRQVVWDUWZLWKWKH defNH\ZRUGIROORZHG
E\RSWLRQDODUJXPHQWOLVWVDFRORQFKDUDFWHU : DQGWKHUHWXUQW\SHRIWKHPHWKRGDQ
HTXDOVVLJQ = DQGILQDOO\WKHPHWKRGERG\0HWKRGVDUHLPSOLFLWO\GHFODUHG£DEVWUDFW¤

Method Declarations | 25

Download at WoweBook.Com
LI \RX OHDYH RII WKH HTXDOV VLJQ DQG PHWKRG ERG\ 7KH HQFORVLQJ W\SH LV WKHQ LWVHOI
DEVWUDFW:H¦OOGLVFXVVDEVWUDFWW\SHVLQPRUHGHWDLOLQ&KDSWHU
:HVDLG£RSWLRQDODUJXPHQWOLVWV¤PHDQLQJPRUHWKDQRQH6FDODOHWV\RXGHILQHPRUH
WKDQRQHDUJXPHQWOLVWIRUDPHWKRG7KLVLVUHTXLUHGIRUFXUU\LQJPHWKRGVZKLFKZH¦OO
GLVFXVVLQ£&XUU\LQJ¤RQSDJH,WLVDOVRYHU\XVHIXOIRUGHILQLQJ\RXURZQ'RPDLQ
6SHFLILF/DQJXDJHV '6/V DVZH¦OOVHHLQ&KDSWHU1RWHWKDWHDFKDUJXPHQWOLVWLV
VXUURXQGHGE\SDUHQWKHVHVDQGWKHDUJXPHQWVDUHVHSDUDWHGE\FRPPDV
,IDPHWKRGERG\KDVPRUHWKDQRQHH[SUHVVLRQ\RXPXVWVXUURXQGLWZLWKFXUO\EUDFHV
{...} <RXFDQRPLWWKHEUDFHVLIWKHPHWKRGERG\KDVMXVWRQHH[SUHVVLRQ

Method Default and Named Arguments (Scala Version 2.8)


0DQ\ ODQJXDJHV OHW \RX GHILQH GHIDXOW YDOXHV IRU VRPH RU DOO RI WKH DUJXPHQWV WR D
PHWKRG&RQVLGHUWKHIROORZLQJVFULSWZLWKDStringUtilREMHFWWKDWOHWV\RXMRLQDOLVW
RIVWULQJVZLWKDXVHUVSHFLILHGVHSDUDWRU
// code-examples/TypeLessDoMore/string-util-v1-script.scala
// Version 1 of "StringUtil".

object StringUtil {
def joiner(strings: List[String], separator: String): String =
strings.mkString(separator)

def joiner(strings: List[String]): String = joiner(strings, " ")


}
import StringUtil._ // Import the joiner methods.

println( joiner(List("Programming", "Scala")) )

7KHUHDUHDFWXDOO\WZR£RYHUORDGHG¤ joinerPHWKRGV7KHVHFRQGRQHXVHVDVLQJOH
VSDFHDVWKH£GHIDXOW¤VHSDUDWRU+DYLQJWZRPHWKRGVVHHPVDELWZDVWHIXO,WZRXOG
EH QLFH LI ZH FRXOG HOLPLQDWH WKH VHFRQG joiner PHWKRG DQG GHFODUH WKDW WKH
separatorDUJXPHQWLQWKHILUVWjoinerKDVDGHIDXOWYDOXH,QIDFWLQ6FDODYHUVLRQ
\RXFDQQRZGRWKLV
// code-examples/TypeLessDoMore/string-util-v2-v28-script.scala
// Version 2 of "StringUtil" for Scala v2.8 only.

object StringUtil {
def joiner(strings: List[String], separator: String = " "): String =
strings.mkString(separator)
}
import StringUtil._ // Import the joiner methods.

println(joiner(List("Programming", "Scala")))

7KHUHLVDQRWKHUDOWHUQDWLYHIRUHDUOLHUYHUVLRQVRI6FDOD<RXFDQXVHLPSOLFLWDUJXPHQWV
ZKLFKZHZLOOGLVFXVVLQ£,PSOLFLW)XQFWLRQ3DUDPHWHUV¤RQSDJH

26 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
6FDODYHUVLRQRIIHUVDQRWKHUHQKDQFHPHQWIRUPHWKRGDUJXPHQWOLVWVQDPHGDUJX
PHQWV:HFRXOGDFWXDOO\ZULWHWKHODVWOLQHRIWKHSUHYLRXVH[DPSOHLQVHYHUDOZD\V
$OORIWKHIROORZLQJprintlnVWDWHPHQWVDUHIXQFWLRQDOO\HTXLYDOHQW
println(joiner(List("Programming", "Scala")))
println(joiner(strings = List("Programming", "Scala")))
println(joiner(List("Programming", "Scala"), " ")) // #1
println(joiner(List("Programming", "Scala"), separator = " ")) // #2
println(joiner(strings = List("Programming", "Scala"), separator = " "))

:K\LVWKLVXVHIXO")LUVWLI\RXFKRRVHJRRGQDPHVIRUWKHPHWKRGDUJXPHQWVWKHQ
\RXUFDOOVWRWKRVHPHWKRGVGRFXPHQWHDFKDUJXPHQWZLWKDQDPH)RUH[DPSOHFRP
SDUHWKHWZROLQHVZLWKFRPPHQWVDQG,QWKHILUVWOLQHLWPD\QRWEHREYLRXV
ZKDW WKH VHFRQG " " DUJXPHQW LV IRU ,Q WKH VHFRQG FDVH ZH VXSSO\ WKH QDPH
separatorZKLFKVXJJHVWVWKHSXUSRVHRIWKHDUJXPHQW
7KHVHFRQGEHQHILWLVWKDW\RXFDQVSHFLI\WKHSDUDPHWHUVLQDQ\RUGHUZKHQ\RXVSHFLI\
WKHPE\QDPH&RPELQHGZLWKGHIDXOWYDOXHV\RXFDQZULWHFRGHOLNHWKHIROORZLQJ
// code-examples/TypeLessDoMore/user-profile-v28-script.scala
// Scala v2.8 only.

object OptionalUserProfileInfo {
val UnknownLocation = ""
val UnknownAge = -1
val UnknownWebSite = ""
}

class OptionalUserProfileInfo(
location: String = OptionalUserProfileInfo.UnknownLocation,
age: Int = OptionalUserProfileInfo.UnknownAge,
webSite: String = OptionalUserProfileInfo.UnknownWebSite)

println( new OptionalUserProfileInfo )


println( new OptionalUserProfileInfo(age = 29) )
println( new OptionalUserProfileInfo(age = 29, location="Earth") )

OptionalUserProfileInfoUHSUHVHQWVDOOWKH£RSWLRQDO¤XVHUSURILOHGDWDLQ\RXUQH[W
:HEVRFLDOQHWZRUNLQJVLWH,WGHILQHVGHIDXOWYDOXHVIRUDOOLWVILHOGV7KHVFULSW
FUHDWHVLQVWDQFHVZLWK]HURRUPRUHQDPHGSDUDPHWHUV7KHRUGHURIWKRVHSDUDPHWHUV
LVDUELWUDU\
7KHH[DPSOHVZHKDYHVKRZQXVHFRQVWDQWYDOXHVDVWKHGHIDXOWV0RVWODQJXDJHVZLWK
GHIDXOWDUJXPHQWYDOXHVRQO\DOORZFRQVWDQWVRURWKHUYDOXHVWKDWFDQEHGHWHUPLQHG
DWSDUVHWLPH+RZHYHULQ6FDODDQ\H[SUHVVLRQFDQEHXVHGDVWKHGHIDXOWDVORQJDV
LWFDQFRPSLOHZKHUHXVHG)RUH[DPSOHDQH[SUHVVLRQFRXOGQRWUHIHUWRDQLQVWDQFH
ILHOGWKDWZLOOEHFRPSXWHGLQVLGHWKHFODVVRUREMHFWERG\EXWLWFRXOGLQYRNHDPHWKRG
RQDVLQJOHWRQREMHFW
$UHODWHGOLPLWDWLRQLVWKDWDGHIDXOWH[SUHVVLRQIRURQHSDUDPHWHUFDQ¦WUHIHUWRDQRWKHU
SDUDPHWHULQWKHOLVWXQOHVVWKHSDUDPHWHUWKDWLVUHIHUHQFHGDSSHDUVHDUOLHULQWKHOLVW
DQGWKHSDUDPHWHUVDUHFXUULHGDFRQFHSWZH¦OOGLVFXVVLQ£&XUU\LQJ¤RQSDJH

Method Declarations | 27

Download at WoweBook.Com
)LQDOO\DQRWKHUFRQVWUDLQWRQQDPHGSDUDPHWHUVLVWKDWRQFH\RXSURYLGHDQDPHIRU
DSDUDPHWHULQDPHWKRGLQYRFDWLRQWKHUHVWRIWKHSDUDPHWHUVDSSHDULQJDIWHULWPXVW
DOVREHQDPHG)RUH[DPSOHnew OptionalUserProfileInfo(age = 29, "Earth")ZRXOG
QRWFRPSLOHEHFDXVHWKHVHFRQGDUJXPHQWLVQRWLQYRNHGE\QDPH
:H¦OOVHHDQRWKHUXVHIXOH[DPSOHRIQDPHGDQGGHIDXOWDUJXPHQWVZKHQZHGLVFXVV
FDVHFODVVHVLQ£&DVH&ODVVHV¤RQSDJH

Nesting Method Definitions


0HWKRGGHILQLWLRQVFDQDOVREHQHVWHG+HUHLVDQLPSOHPHQWDWLRQRIDIDFWRULDOFDOFX
ODWRUZKHUHZHXVHDFRQYHQWLRQDOWHFKQLTXHRIFDOOLQJDVHFRQGQHVWHGPHWKRGWRGR
WKHZRUN
// code-examples/TypeLessDoMore/factorial-script.scala

def factorial(i: Int): Int = {


def fact(i: Int, accumulator: Int): Int = {
if (i <= 1)
accumulator
else
fact(i - 1, i * accumulator)
}

fact(i, 1)
}

println( factorial(0) )
println( factorial(1) )
println( factorial(2) )
println( factorial(3) )
println( factorial(4) )
println( factorial(5) )

7KHVHFRQGPHWKRGFDOOVLWVHOIUHFXUVLYHO\SDVVLQJDQ accumulatorSDUDPHWHUZKHUH
WKHUHVXOWRIWKHFDOFXODWLRQLV£DFFXPXODWHG¤1RWHWKDWZHUHWXUQWKHDFFXPXODWHG
YDOXH ZKHQ WKH FRXQWHU i UHDFKHV  :H¦UH LJQRULQJ LQYDOLG QHJDWLYH LQWHJHUV 7KH
IXQFWLRQ DFWXDOO\ UHWXUQV  IRU i < 0  $IWHU WKH GHILQLWLRQ RI WKH QHVWHG PHWKRG
factorialFDOOVLWZLWKWKHSDVVHGLQYDOXHiDQGWKHLQLWLDODFFXPXODWRUYDOXHRI
/LNHDORFDOYDULDEOHGHFODUDWLRQLQPDQ\ODQJXDJHVDQHVWHGPHWKRGLVRQO\YLVLEOH
LQVLGHWKHHQFORVLQJPHWKRG,I\RXWU\WRFDOOfactRXWVLGHRIfactorial\RXZLOOJHWD
FRPSLOHUHUURU
'LG\RXQRWLFHWKDWZHXVHiDVDSDUDPHWHUQDPHWZLFHILUVWLQWKHfactorialPHWKRG
DQGDJDLQLQWKHQHVWHGfactPHWKRG"$VLQPDQ\ODQJXDJHVWKHXVHRIiDVDSDUDPHWHU
QDPHIRUfact£VKDGRZV¤WKHRXWHUXVHRIiDVDSDUDPHWHUQDPHIRUfactorial7KLVLV
ILQHEHFDXVHZHGRQ¦WQHHGWKHRXWHUYDOXHRI iLQVLGH fact:HRQO\XVHLWWKHILUVW
WLPHZHFDOOfactDWWKHHQGRIfactorial

28 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
:KDWLIZHQHHGWRXVHDYDULDEOHWKDWLVGHILQHGRXWVLGHDQHVWHGIXQFWLRQ"&RQVLGHU
WKLVFRQWULYHGH[DPSOH
// code-examples/TypeLessDoMore/count-to-script.scala

def countTo(n: Int):Unit = {


def count(i: Int): Unit = {
if (i <= n) {
println(i)
count(i + 1)
}
}
count(1)
}

countTo(5)

1RWHWKDWWKHQHVWHG countPHWKRGXVHVWKH nYDOXHWKDWLVSDVVHGDVDSDUDPHWHUWR


countTo7KHUHLVQRQHHGWRSDVV nDVDQDUJXPHQWWR count%HFDXVH countLVQHVWHG
LQVLGHcountTonLVYLVLEOHWRLW
7KHGHFODUDWLRQRIDILHOG PHPEHUYDULDEOH FDQEHSUHIL[HGZLWKNH\ZRUGVLQGLFDWLQJ
WKHYLVLELOLW\MXVWDVLQODQJXDJHVOLNH-DYDDQG&6LPLODUO\WKHGHFODUDWLRQRIDQRQ
QHVWHGPHWKRGFDQEHSUHIL[HGZLWKWKHVDPHNH\ZRUGV:HZLOOGLVFXVVWKHYLVLELOLW\
UXOHVDQGNH\ZRUGVLQ£9LVLELOLW\5XOHV¤RQSDJH

Inferring Type Information


6WDWLFDOO\W\SHGODQJXDJHVFDQEHYHU\YHUERVH&RQVLGHUWKLVW\SLFDOGHFODUDWLRQLQ-DYD
import java.util.Map;
import java.util.HashMap;
...
Map<Integer, String> intToStringMap = new HashMap<Integer, String>();

:HKDYHWRVSHFLI\WKHW\SHSDUDPHWHUV<Integer, String>WZLFH 6FDODXVHVWKHWHUP


W\SHDQQRWDWLRQVIRUH[SOLFLWW\SHGHFODUDWLRQVOLNHHashMap<Integer, String>
6FDODVXSSRUWVW\SHLQIHUHQFH VHHIRUH[DPSOH>7\SH,QIHUHQFH@DQG>3LHUFH@ 7KH
ODQJXDJH¦VFRPSLOHUFDQGLVFHUQTXLWHDELWRIW\SHLQIRUPDWLRQIURPWKHFRQWH[WZLWK
RXWH[SOLFLWW\SHDQQRWDWLRQV+HUH¦VWKHVDPHGHFODUDWLRQUHZULWWHQLQ6FDODZLWKLQ
IHUUHGW\SHLQIRUPDWLRQ
import java.util.Map
import java.util.HashMap
...
val intToStringMap: Map[Integer, String] = new HashMap

5HFDOOIURP&KDSWHUWKDW6FDODXVHVVTXDUHEUDFNHWV [...] IRUJHQHULFW\SHSDUDP


HWHUV:HVSHFLI\Map[Integer, String]RQWKHOHIWKDQGVLGHRIWKHHTXDOVVLJQ :HDUH
VWLFNLQJZLWK-DYDW\SHVIRUWKHH[DPSOH 2QWKHULJKWKDQGVLGHZHLQVWDQWLDWHWKH
DFWXDOW\SHZHZDQWDHashMapEXWZHGRQ¦WKDYHWRUHSHDWWKHW\SHSDUDPHWHUV

Inferring Type Information | 29

Download at WoweBook.Com
)RUFRPSOHWHQHVVVXSSRVHZHGRQ¦WDFWXDOO\FDUHLIWKHLQVWDQFHLVRIW\SHMap WKH-DYD
LQWHUIDFHW\SH ,WFDQEHRIW\SHHashMapIRUDOOZHFDUH
import java.util.Map
import java.util.HashMap
...
val intToStringMap2 = new HashMap[Integer, String]

7KLVGHFODUDWLRQUHTXLUHVQRW\SHDQQRWDWLRQVRQWKHOHIWKDQGVLGHEHFDXVHDOORIWKH
W\SHLQIRUPDWLRQQHHGHGLVRQWKHULJKWKDQGVLGH7KHFRPSLOHUDXWRPDWLFDOO\PDNHV
intToStringMap2DHashMap[Integer,String]
7\SHLQIHUHQFHLVXVHGIRUPHWKRGVWRR,QPRVWFDVHVWKHUHWXUQW\SHRIWKHPHWKRG
FDQEHLQIHUUHGVRWKH :DQGUHWXUQW\SHFDQEHRPLWWHG+RZHYHUW\SHDQQRWDWLRQV
DUHUHTXLUHGIRUDOOPHWKRGSDUDPHWHUV
3XUHIXQFWLRQDOODQJXDJHVOLNH+DVNHOO VHHHJ>2¦6XOOLYDQ@ XVHW\SHLQIHUHQFH
DOJRULWKPVOLNH+LQGOH\0LOQHU VHH>6SLHZDN@IRUDQHDVLO\GLJHVWHGH[SODQDWLRQ 
&RGHZULWWHQLQWKHVHODQJXDJHVUHTXLUHW\SHDQQRWDWLRQVOHVVRIWHQWKDQLQ6FDODEH
FDXVH6FDOD¦VW\SHLQIHUHQFHDOJRULWKPKDVWRVXSSRUWREMHFWRULHQWHGW\SLQJDVZHOODV
IXQFWLRQDOW\SLQJ6R6FDODUHTXLUHVPRUHW\SHDQQRWDWLRQVWKDQODQJXDJHVOLNH+DVNHOO
+HUHLVDVXPPDU\RIWKHUXOHVIRUZKHQH[SOLFLWW\SHDQQRWDWLRQVDUHUHTXLUHGLQ6FDOD

When Explicit Type Annotations Are Required


,Q SUDFWLFDO WHUPV \RX KDYH WR SURYLGH H[SOLFLW W\SH DQQRWDWLRQV IRU WKH IROORZLQJ
VLWXDWLRQV
 $YDULDEOHGHFODUDWLRQXQOHVV\RXDVVLJQDYDOXHWRWKHYDULDEOH HJ val name =
"Programming Scala"
 $OOPHWKRGSDUDPHWHUV HJdef deposit(amount: Money)...
 0HWKRGUHWXUQYDOXHVLQWKHIROORZLQJFDVHV
D :KHQ\RXH[SOLFLWO\FDOOreturnLQDPHWKRG HYHQDWWKHHQG
E :KHQDPHWKRGLVUHFXUVLYH
F :KHQ D PHWKRG LV RYHUORDGHG DQG RQH RI WKH PHWKRGV FDOOV DQRWKHU WKH
FDOOLQJPHWKRGQHHGVDUHWXUQW\SHDQQRWDWLRQ
G :KHQWKHLQIHUUHGUHWXUQW\SHZRXOGEHPRUHJHQHUDOWKDQ\RXLQWHQGHGHJ
Any

7KHAnyW\SHLVWKHURRWRIWKH6FDODW\SHKLHUDUFK\ VHH£7KH6FDOD7\SH
+LHUDUFK\¤RQSDJHIRUPRUHGHWDLOV ,IDEORFNRIFRGHUHWXUQVD
YDOXHRIW\SHAnyXQH[SHFWHGO\FKDQFHVDUHJRRGWKDWWKHW\SHLQIHUHQFHU
FRXOGQ¦WILJXUHRXWZKDWW\SHWRUHWXUQVRLWFKRVHWKHPRVWJHQHULFW\SH
SRVVLEOH

30 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
/HW¦VORRNDWH[DPSOHVZKHUHH[SOLFLWGHFODUDWLRQVRIPHWKRGUHWXUQW\SHVDUHUHTXLUHG
,QWKHIROORZLQJVFULSWWKHupCasePHWKRGKDVDFRQGLWLRQDOUHWXUQVWDWHPHQWIRU]HUR
OHQJWKVWULQJV
// code-examples/TypeLessDoMore/method-nested-return-script.scala
// ERROR: Won't compile until you put a String return type on upCase.

def upCase(s: String) = {


if (s.length == 0)
return s
else
s.toUpperCase()
}

println( upCase("") )
println( upCase("Hello") )

5XQQLQJWKLVVFULSWJLYHV\RXWKHIROORZLQJHUURU
... 6: error: method upCase has return statement; needs result type
return s
^

<RXFDQIL[WKLVHUURUE\FKDQJLQJWKHILUVWOLQHRIWKHPHWKRGWRWKHIROORZLQJ
def upCase(s: String): String = {

$FWXDOO\IRUWKLVSDUWLFXODUVFULSWDQDOWHUQDWLYHIL[LVWRUHPRYHWKH returnNH\ZRUG
IURPWKHOLQH,WLVQRWQHHGHGIRUWKHFRGHWRZRUNSURSHUO\EXWLWLOOXVWUDWHVRXUSRLQW
5HFXUVLYHPHWKRGVDOVRUHTXLUHDQH[SOLFLWUHWXUQW\SH5HFDOORXU factorialPHWKRG
LQ£1HVWLQJ0HWKRG'HILQLWLRQV¤RQSDJH/HW¦VUHPRYHWKH: IntUHWXUQW\SHRQWKH
QHVWHGfactPHWKRG
// code-examples/TypeLessDoMore/method-recursive-return-script.scala
// ERROR: Won't compile until you put an Int return type on "fact".

def factorial(i: Int) = {


def fact(i: Int, accumulator: Int) = {
if (i <= 1)
accumulator
else
fact(i - 1, i * accumulator)
}

fact(i, 1)
}

1RZLWIDLOVWRFRPSLOH
... 9: error: recursive method fact needs result type
fact(i - 1, i * accumulator)
^

Inferring Type Information | 31

Download at WoweBook.Com
2YHUORDGHGPHWKRGVFDQVRPHWLPHVUHTXLUHDQH[SOLFLWUHWXUQW\SH:KHQRQHVXFK
PHWKRGFDOOVDQRWKHUZHKDYHWRDGGDUHWXUQW\SHWRWKHRQHGRLQJWKHFDOOLQJDVLQ
WKLVH[DPSOH
// code-examples/TypeLessDoMore/method-overloaded-return-script.scala
// Version 1 of "StringUtil" (with a compilation error).
// ERROR: Won't compile: needs a String return type on the second "joiner".

object StringUtil {
def joiner(strings: List[String], separator: String): String =
strings.mkString(separator)

def joiner(strings: List[String]) = joiner(strings, " ")


}
import StringUtil._ // Import the joiner methods.

println( joiner(List("Programming", "Scala")) )

7KHWZRjoinerPHWKRGVFRQFDWHQDWHDListRIVWULQJVWRJHWKHU7KHILUVWPHWKRGDOVR
WDNHVDQDUJXPHQWIRUWKHVHSDUDWRUVWULQJ7KHVHFRQGPHWKRGFDOOVWKHILUVWZLWKD
£GHIDXOW¤VHSDUDWRURIDVLQJOHVSDFH
,I\RXUXQWKLVVFULSW\RXJHWWKHIROORZLQJHUURU
... 9: error: overloaded method joiner needs result type
def joiner(strings: List[String]) = joiner(strings, "")
^

6LQFHWKHVHFRQGjoinerPHWKRGFDOOVWKHILUVWLWUHTXLUHVDQH[SOLFLWStringUHWXUQW\SH
,WVKRXOGORRNOLNHWKLV
def joiner(strings: List[String]): String = joiner(strings, " ")

7KHILQDOVFHQDULRFDQEHVXEWOHZKHQDPRUHJHQHUDOUHWXUQW\SHLVLQIHUUHGWKDQZKDW
\RXH[SHFWHG<RXXVXDOO\VHHWKLVHUURUZKHQ\RXDVVLJQDYDOXHUHWXUQHGIURPDIXQF
WLRQ WR D YDULDEOH ZLWK D PRUH VSHFLILF W\SH )RU H[DPSOH \RX ZHUH H[SHFWLQJ D
StringEXWWKHIXQFWLRQLQIHUUHGDQ AnyIRUWKHUHWXUQHGREMHFW/HW¦VVHHDFRQWULYHG
H[DPSOHWKDWUHIOHFWVDEXJZKHUHWKLVVFHQDULRFDQRFFXU
// code-examples/TypeLessDoMore/method-broad-inference-return-script.scala
// ERROR: Won't compile; needs a String return type on the second "joiner".

def makeList(strings: String*) = {


if (strings.length == 0)
List(0) // #1
else
strings.toList
}

val list: List[String] = makeList()

5XQQLQJWKLVVFULSWUHWXUQVWKHIROORZLQJHUURU
...11: error: type mismatch;
found : List[Any]
required: List[String]

32 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
val list: List[String] = makeList()
^

:HLQWHQGHGIRU makeListWRUHWXUQD List[String]EXWZKHQ strings.lengthHTXDOV


]HURZHUHWXUQHG List(0)LQFRUUHFWO\£DVVXPLQJ¤WKDWWKLVH[SUHVVLRQLVWKHFRUUHFW
ZD\WRFUHDWHDQHPSW\OLVW,QIDFWZHUHWXUQHGDList[Int]ZLWKRQHHOHPHQW0:H
VKRXOG KDYH UHWXUQHG List() 6LQFH WKH else H[SUHVVLRQ UHWXUQV D List[String] WKH
UHVXOWRIstrings.toListWKHLQIHUUHGUHWXUQW\SHIRUWKHPHWKRGLVWKHFORVHVWFRPPRQ
VXSHUW\SHRIList[Int]DQGList[String]ZKLFKLVList[Any]1RWHWKDWWKHFRPSLOD
WLRQHUURUGRHVQ¦WRFFXULQWKHIXQFWLRQGHILQLWLRQ:HRQO\VHHLWZKHQZHDWWHPSWWR
DVVLJQWKHYDOXHUHWXUQHGIURPmakeListWRDList[String]YDULDEOH
,QWKLVFDVHIL[LQJWKHEXJLVWKHVROXWLRQ$OWHUQDWLYHO\ZKHQWKHUHLVQ¦WDEXJLWPD\
EHWKDWWKHFRPSLOHUMXVWQHHGVWKH£KHOS¤RIDQH[SOLFLWUHWXUQW\SHGHFODUDWLRQ,QYHV
WLJDWHWKHPHWKRGWKDWDSSHDUVWRUHWXUQWKHXQH[SHFWHGW\SH,QRXUH[SHULHQFH\RX
RIWHQILQGWKDW\RXPRGLILHGWKDWPHWKRG RUDQRWKHURQHLQWKHFDOOSDWK LQVXFKD
ZD\WKDWWKHFRPSLOHUQRZLQIHUVDPRUHJHQHUDOUHWXUQW\SHWKDQQHFHVVDU\$GGWKH
H[SOLFLWUHWXUQW\SHLQWKLVFDVH
$QRWKHUZD\WRSUHYHQWWKHVHSUREOHPVLVWRDOZD\VGHFODUHUHWXUQW\SHVIRUPHWKRGV
HVSHFLDOO\ZKHQGHILQLQJPHWKRGVIRUDSXEOLF$3,/HW¦VUHYLVLWRXUStringUtilH[DPSOH
DQGVHHZK\H[SOLFLWGHFODUDWLRQVDUHDJRRGLGHD DGDSWHGIURP>6PLWKD@ 
+HUHLVRXUStringUtil£$3,¤DJDLQZLWKDQHZPHWKRGtoCollection
// code-examples/TypeLessDoMore/string-util-v3.scala
// Version 3 of "StringUtil" (for all versions of Scala).

object StringUtil {
def joiner(strings: List[String], separator: String): String =
strings.mkString(separator)

def joiner(strings: List[String]): String = strings.mkString(" ")

def toCollection(string: String) = string.split(' ')


}

7KHtoCollectionPHWKRGVSOLWVDVWULQJRQVSDFHVDQGUHWXUQVDQArrayFRQWDLQLQJWKH
VXEVWULQJV7KHUHWXUQW\SHLVLQIHUUHGZKLFKLVDSRWHQWLDOSUREOHPDVZHZLOOVHH7KH
PHWKRG LV VRPHZKDW FRQWULYHG EXW LW ZLOO LOOXVWUDWH RXU SRLQW +HUH LV D FOLHQW RI
StringUtilWKDWXVHVWKLVPHWKRG
// code-examples/TypeLessDoMore/string-util-client.scala

import StringUtil._

object StringUtilClient {
def main(args: Array[String]) = {
args foreach { s => toCollection(s).foreach { x => println(x) } }
}
}

Inferring Type Information | 33

Download at WoweBook.Com
,I\RXFRPSLOHWKHVHILOHVZLWKscala\RXFDQUXQWKHFOLHQWDVIROORZV
$ scala -cp ... StringUtilClient "Programming Scala"
Programming
Scala

)RUWKH -cp ...FODVVSDWKDUJXPHQWXVHWKHGLUHFWRU\ZKHUH scalac


ZURWHWKHFODVVILOHVZKLFKGHIDXOWVWRWKHFXUUHQWGLUHFWRU\ LHXVH
-cp . ,I\RXXVHGWKHEXLOGSURFHVVLQWKHGRZQORDGHGFRGHH[DPSOHV
WKH FODVV ILOHV DUH ZULWWHQ WR WKH EXLOG GLUHFWRU\ XVLQJ scalac -d
build ... ,QWKLVFDVHXVH-cp build

(YHU\WKLQJ LV ILQH DW WKLV SRLQW EXW QRZ LPDJLQH WKDW WKH FRGH EDVH KDV JURZQ
StringUtilDQGLWVFOLHQWVDUHQRZEXLOWVHSDUDWHO\DQGEXQGOHGLQWRGLIIHUHQW-$5V
,PDJLQHDOVRWKDWWKHPDLQWDLQHUVRIStringUtilGHFLGHWRUHWXUQDListLQVWHDGRIWKH
GHIDXOW
object StringUtil {
...

def toCollection(string: String) = string.split(' ').toList // changed!


}

7KHRQO\GLIIHUHQFHLVWKHILQDOFDOOWR toListWKDWFRQYHUWVWKHFRPSXWHG ArrayWRD


List<RXUHFRPSLOH StringUtilDQGUHGHSOR\LWV-$57KHQ\RXUXQWKHVDPHFOLHQW
ZLWKRXWUHFRPSLOLQJLWILUVW
$ scala -cp ... StringUtilClient "Programming Scala"
java.lang.NoSuchMethodError: StringUtil$.toCollection(...
at StringUtilClient$$anonfun$main$1.apply(string-util-client.scala:6)
at StringUtilClient$$anonfun$main$1.apply(string-util-client.scala:6)
...

:KDWKDSSHQHG":KHQWKHFOLHQWZDVFRPSLOHGStringUtil.toCollectionUHWXUQHGDQ
Array7KHQ toCollectionZDVFKDQJHGWRUHWXUQ List,QERWKYHUVLRQVWKHPHWKRG
UHWXUQYDOXHZDVLQIHUUHG7KHUHIRUHWKHFOLHQWVKRXOGKDYHEHHQUHFRPSLOHGWRR
+RZHYHUKDGDQH[SOLFLWUHWXUQW\SHRISeqEHHQGHFODUHGZKLFKLVDSDUHQWIRUERWK
ArrayDQGListWKHQWKHLPSOHPHQWDWLRQFKDQJHZRXOGQRWKDYHIRUFHGDUHFRPSLODWLRQ
RIWKHFOLHQW

:KHQGHYHORSLQJ$3,VWKDWDUHEXLOWVHSDUDWHO\IURPWKHLUFOLHQWVGH
FODUHPHWKRGUHWXUQW\SHVH[SOLFLWO\DQGXVHWKHPRVWJHQHUDOUHWXUQW\SH
\RXFDQ7KLVLVHVSHFLDOO\LPSRUWDQWZKHQ$3,VGHFODUHDEVWUDFWPHWK
RGV VHHHJ&KDSWHU 

7KHUH LV DQRWKHU VFHQDULR WR ZDWFK IRU ZKHQ XVLQJ GHFODUDWLRQV RI FROOHFWLRQV OLNH
val map = Map()DVLQWKHIROORZLQJH[DPSOH

34 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
val map = Map()

map.update("book", "Programming Scala")


... 3: error: type mismatch;
found : java.lang.String("book")
required: Nothing
map.update("book", "Programming Scala")
^

:KDW KDSSHQHG" 7KH W\SH SDUDPHWHUV RI WKH JHQHULF W\SH Map ZHUH LQIHUUHG DV
[Nothing,Nothing]ZKHQWKHPDSZDVFUHDWHG :H¦OOGLVFXVV NothingLQ£7KH6FDOD
7\SH+LHUDUFK\¤RQSDJHEXWLWVQDPHLVVXJJHVWLYH :HDWWHPSWHGWRLQVHUWDQ
LQFRPSDWLEOHNH\YDOXHSDLURIW\SHVStringDQGString&DOOLWDMapWRQRZKHUH7KH
VROXWLRQ LV WR SDUDPHWHUL]H WKH LQLWLDO PDS GHFODUDWLRQ HJ val map = Map[String,
String]()RUWRVSHFLI\LQLWLDOYDOXHVVRWKDWWKHPDSSDUDPHWHUVDUHLQIHUUHGHJval
map = Map("Programming" → "Scala")
)LQDOO\WKHUHLVDVXEWOHEHKDYLRUZLWKLQIHUUHGUHWXUQW\SHVWKDWFDQFDXVHXQH[SHFWHG
DQGEDIIOLQJUHVXOWV VHH>6FDOD7LSV@ &RQVLGHUWKHIROORZLQJH[DPSOHscalaVHVVLRQ
scala> def double(i: Int) { 2 * i }
double: (Int)Unit

scala> println(double(2))
()

:K\GLGWKHVHFRQGFRPPDQGSULQW()LQVWHDGRI4"/RRNFDUHIXOO\DWZKDWWKHscala
LQWHUSUHWHUVDLGWKHILUVWFRPPDQGUHWXUQHGdouble (Int)Unit:HGHILQHGDPHWKRG
QDPHGdoubleWKDWWDNHVDQIntDUJXPHQWDQGUHWXUQVUnit7KHPHWKRGGRHVQ¦WUHWXUQ
DQIntDVZHZRXOGH[SHFW
7KHFDXVHRIWKLVXQH[SHFWHGEHKDYLRULVDPLVVLQJHTXDOVVLJQLQWKHPHWKRGGHILQLWLRQ
+HUHLVWKHGHILQLWLRQZHDFWXDOO\LQWHQGHG
scala> def double(i: Int) = { 2 * i }
double: (Int)Int

scala> println(double(2))
4

1RWHWKHHTXDOVVLJQEHIRUHWKHERG\RIdouble1RZWKHRXWSXWVD\VZHKDYHGHILQHG
doubleWRUHWXUQDQIntDQGWKHVHFRQGFRPPDQGGRHVZKDWZHH[SHFWLWWRGR
7KHUHLVDUHDVRQIRUWKLVEHKDYLRU6FDODUHJDUGVDPHWKRGZLWKWKHHTXDOVVLJQEHIRUH
WKHERG\DVDIXQFWLRQGHILQLWLRQDQGDIXQFWLRQDOZD\VUHWXUQVDYDOXHLQIXQFWLRQDO
SURJUDPPLQJ2QWKHRWKHUKDQGZKHQ6FDODVHHVDPHWKRGERG\ZLWKRXWWKHOHDGLQJ
HTXDOV VLJQ LW DVVXPHV WKH SURJUDPPHU LQWHQGHG WKH PHWKRG WR EH D £SURFHGXUH¤
GHILQLWLRQPHDQWIRUSHUIRUPLQJVLGHHIIHFWVRQO\ZLWKWKHUHWXUQYDOXHUnit,QSUDFWLFH
LWLVPRUHOLNHO\WKDWWKHSURJUDPPHUVLPSO\IRUJRWWRLQVHUWWKHHTXDOVVLJQ

Inferring Type Information | 35

Download at WoweBook.Com
:KHQWKHUHWXUQW\SHRIDPHWKRGLVLQIHUUHGDQG\RXGRQ¦WXVHDQHTXDOV
VLJQEHIRUHWKHRSHQLQJSDUHQWKHVLVIRUWKHPHWKRGERG\6FDODLQIHUVD
UnitUHWXUQW\SHHYHQZKHQWKHODVWH[SUHVVLRQLQWKHPHWKRGLVDYDOXH
RIDQRWKHUW\SH

%\WKHZD\ZKHUHGLGWKDW()FRPHIURPWKDWZDVSULQWHGEHIRUHZHIL[HGWKHEXJ",W
LV DFWXDOO\ WKH UHDO QDPH RI WKH VLQJOHWRQ LQVWDQFH RI WKH Unit W\SH 7KLV QDPH LV D
IXQFWLRQDOSURJUDPPLQJFRQYHQWLRQ

Literals
2IWHQDQHZREMHFWLVLQLWLDOL]HGZLWKDOLWHUDOYDOXHVXFKDVval book = "Programming
Scala"/HW¦VGLVFXVVWKHNLQGVRIOLWHUDOYDOXHVVXSSRUWHGE\6FDOD+HUHZH¦OOOLPLW
RXUVHOYHV WR OH[LFDO V\QWD[ OLWHUDOV :H¦OO FRYHU OLWHUDO V\QWD[ IRU IXQFWLRQV XVHG DV
YDOXHVQRWPHPEHUPHWKRGV WXSOHVDQGFHUWDLQW\SHVOLNHListsDQGMapsDVZHFRPH
WRWKHP

Integer Literals
,QWHJHUOLWHUDOVFDQEHH[SUHVVHGLQGHFLPDOKH[DGHFLPDORURFWDO7KHGHWDLOVDUHVXP
PDUL]HGLQ7DEOH
7DEOH,QWHJHUOLWHUDOV
Kind Format Examples
Decimal 0 or a nonzero digit followed by zero or more digits (0–9) 0, 1, 321
Hexadecimal 0x followed by one or more hexadecimal digits (0–9, A–F, a–f) 0xFF, 0x1a3b
Octal 0 followed by one or more octal digits (0–7) 013, 077

)RULongOLWHUDOVLWLVQHFHVVDU\WRDSSHQGWKHLRUlFKDUDFWHUDWWKHHQGRIWKHOLWHUDO
2WKHUZLVHDQ IntLVXVHG7KHYDOLGYDOXHVIRUDQLQWHJHUOLWHUDODUHERXQGHGE\WKH
W\SHRIWKHYDULDEOHWRZKLFKWKHYDOXHZLOOEHDVVLJQHG7DEOHGHILQHVWKHOLPLWV
ZKLFKDUHLQFOXVLYH
7DEOH5DQJHVRIDOORZHGYDOXHVIRULQWHJHUOLWHUDOV ERXQGDULHVDUHLQFOXVLYH
Target type Minimum (inclusive) Maximum (inclusive)
Long −263 263 − 1
Int −231 231 − 1
Short −215 215 − 1
Char 0 216 − 1
Byte −27 27 − 1

36 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
$FRPSLOHWLPHHUURURFFXUVLIDQLQWHJHUOLWHUDOQXPEHULVVSHFLILHGWKDWLVRXWVLGHWKHVH
UDQJHVDVLQWKHIROORZLQJH[DPSOHV
scala > val i = 12345678901234567890
<console>:1: error: integer number too large
val i = 12345678901234567890
scala> val b: Byte = 128
<console>:4: error: type mismatch;
found : Int(128)
required: Byte
val b: Byte = 128
^

scala> val b: Byte = 127


b: Byte = 127

Floating-Point Literals
)ORDWLQJSRLQWOLWHUDOVDUHH[SUHVVLRQVZLWK]HURRUPRUHGLJLWVIROORZHGE\DSHULRG
. IROORZHGE\]HURRUPRUHGLJLWV,IWKHUHDUHQRGLJLWVEHIRUHWKHSHULRGLHWKH
QXPEHULVOHVVWKDQWKHQWKHUHPXVWEHRQHRUPRUHGLJLWVDIWHUWKHSHULRG)RU
Float OLWHUDOV DSSHQG WKH F RU f FKDUDFWHU DW WKH HQG RI WKH OLWHUDO 2WKHUZLVH D
DoubleLVDVVXPHG<RXFDQRSWLRQDOO\DSSHQGDDRUdIRUDDouble
)ORDWLQJSRLQWOLWHUDOVFDQEHH[SUHVVHGZLWKRUZLWKRXWH[SRQHQWLDOV7KHIRUPDWRI
WKHH[SRQHQWLDOSDUWLVeRUEIROORZHGE\DQRSWLRQDO+RU-IROORZHGE\RQHRUPRUH
GLJLWV
+HUHDUHVRPHH[DPSOHIORDWLQJSRLQWOLWHUDOV
0.
.0
0.0
3.
3.14
.14
0.14
3e5
3E5
3.E5
3.e5
3.e+5
3.e-5
3.14e-5
3.14e-5f
3.14e-5F
3.14e-5d
3.14e-5D

Float FRQVLVWV RI DOO ,(((  ELW VLQJOHSUHFLVLRQ ELQDU\ IORDWLQJSRLQW YDOXHV
DoubleFRQVLVWVRIDOO,(((ELWGRXEOHSUHFLVLRQELQDU\IORDWLQJSRLQWYDOXHV

Literals | 37

Download at WoweBook.Com
7RDYRLGSDUVLQJDPELJXLWLHV\RXPXVWKDYHDWOHDVWRQHVSDFHDIWHUD
IORDWLQJSRLQWOLWHUDOLILWLVIROORZHGE\DWRNHQWKDWVWDUWVZLWKDOHWWHU
$OVRWKHH[SUHVVLRQ 1.toStringUHWXUQVWKHLQWHJHUYDOXH 1DVDVWULQJ
ZKLOH1. toStringXVHVWKHRSHUDWRUQRWDWLRQWRLQYRNHtoStringRQWKH
IORDWLQJSRLQWOLWHUDO1.

Boolean Literals
7KH ERROHDQ OLWHUDOV DUH true DQG false 7KH W\SH RI WKH YDULDEOH WR ZKLFK WKH\ DUH
DVVLJQHGZLOOEHLQIHUUHGWREHBoolean
scala> val b1 = true
b1: Boolean = true

scala> val b2 = false


b2: Boolean = false

Character Literals
$FKDUDFWHUOLWHUDOLVHLWKHUDSULQWDEOH8QLFRGHFKDUDFWHURUDQHVFDSHVHTXHQFHZULWWHQ
EHWZHHQVLQJOHTXRWHV$FKDUDFWHUZLWKD8QLFRGHYDOXHEHWZHHQDQGPD\DOVR
EHUHSUHVHQWHGE\DQRFWDOHVFDSHLHDEDFNVODVK \ IROORZHGE\DVHTXHQFHRIXSWR
WKUHHRFWDOFKDUDFWHUV,WLVDFRPSLOHWLPHHUURULIDEDFNVODVKFKDUDFWHULQDFKDUDFWHU
RUVWULQJOLWHUDOGRHVQRWVWDUWDYDOLGHVFDSHVHTXHQFH
+HUHDUHVRPHH[DPSOHV
'A'
'\u0041' // 'A' in Unicode
'\n'
'\012' // '\n' in octal
'\t'

7KHYDOLGHVFDSHVHTXHQFHVDUHVKRZQLQ7DEOH
7DEOH&KDUDFWHUHVFDSHVHTXHQFHV
Sequence Unicode Meaning
\b \u0008 Backspace (BS)
\t \u0009 Horizontal tab (HT)
\n \u000a Line feed (LF)
\f \u000c Form feed (FF)
\r \u000d Carriage return (CR)
\" \u0022 Double quote (")
\’ \u0027 Single quote (’)
\\ \u0009 Backslash (\)

38 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
String Literals
$VWULQJOLWHUDOLVDVHTXHQFHRIFKDUDFWHUVHQFORVHGLQGRXEOHTXRWHVRUWULSOHVRIGRXEOH
TXRWHVLH"""..."""
)RUVWULQJOLWHUDOVLQGRXEOHTXRWHVWKHDOORZHGFKDUDFWHUVDUHWKHVDPHDVWKHFKDUDFWHU
OLWHUDOV +RZHYHU LI D GRXEOH TXRWH " FKDUDFWHU DSSHDUV LQ WKH VWULQJ LW PXVW EH
£HVFDSHG¤ZLWKD\FKDUDFWHU+HUHDUHVRPHH[DPSOHV
"Programming\nScala"
"He exclaimed, \"Scala is great!\""
"First\tSecond"

7KHVWULQJOLWHUDOVERXQGHGE\WULSOHVRIGRXEOHTXRWHVDUHDOVRFDOOHGPXOWLOLQHVWULQJ
OLWHUDOV7KHVHVWULQJVFDQFRYHUVHYHUDOOLQHVWKHOLQHIHHGVZLOOEHSDUWRIWKHVWULQJ
7KH\FDQLQFOXGHDQ\FKDUDFWHUVLQFOXGLQJRQHRUWZRGRXEOHTXRWHVWRJHWKHUEXWQRW
WKUHHWRJHWKHU7KH\DUHXVHIXOIRUVWULQJVZLWK\FKDUDFWHUVWKDWGRQ¦WIRUPYDOLG8QL
FRGHRUHVFDSHVHTXHQFHVOLNHWKHYDOLGVHTXHQFHVOLVWHGLQ7DEOH5HJXODUH[SUHV
VLRQV DUH D W\SLFDO H[DPSOH ZKLFK ZH¦OO GLVFXVV LQ &KDSWHU  +RZHYHU LI HVFDSH
VHTXHQFHVDSSHDUWKH\DUHQ¦WLQWHUSUHWHG
+HUHDUHWKUHHH[DPSOHVWULQJV
"""Programming\nScala"""
"""He exclaimed, "Scala is great!" """
"""First line\n
Second line\t

Fourth line"""

1RWHWKDWZHKDGWRDGGDVSDFHEHIRUHWKHWUDLOLQJ"""LQWKHVHFRQGH[DPSOHWRSUHYHQW
DSDUVHHUURU7U\LQJWRHVFDSHWKHVHFRQG"WKDWHQGVWKH"Scala is great!"TXRWHLH
"Scala is great!\"GRHVQ¦WZRUN
&RS\DQGSDVWHWKHVHVWULQJVLQWRWKH scalaLQWHUSUHWHU'RWKHVDPHIRUWKHSUHYLRXV
VWULQJH[DPSOHV+RZDUHWKH\LQWHUSUHWHGGLIIHUHQWO\"

Symbol Literals
6FDODVXSSRUWVV\PEROVZKLFKDUHLQWHUQHGVWULQJVPHDQLQJWKDWWZRV\PEROVZLWKWKH
VDPH£QDPH¤ LHWKHVDPHFKDUDFWHUVHTXHQFH ZLOODFWXDOO\UHIHUWRWKHVDPHREMHFW
LQPHPRU\6\PEROVDUHXVHGOHVVRIWHQLQ6FDODWKDQLQVRPHRWKHUODQJXDJHVOLNH
5XE\6PDOOWDONDQG/LVS7KH\DUHXVHIXODVPDSNH\VLQVWHDGRIVWULQJV
$V\PEROOLWHUDOLVDVLQJOHTXRWH ' IROORZHGE\DOHWWHUIROORZHGE\]HURRUPRUH
GLJLWVDQGOHWWHUV1RWHWKDWDQH[SUHVVLRQOLNH'1LVLQYDOLGEHFDXVHWKHFRPSLOHUWKLQNV
LWLVDQLQFRPSOHWHFKDUDFWHUOLWHUDO
$V\PEROOLWHUDO'idLVDVKRUWKDQGIRUWKHH[SUHVVLRQscala.Symbol("id")

Literals | 39

Download at WoweBook.Com
,I \RX ZDQW WR FUHDWH D V\PERO WKDW FRQWDLQV ZKLWHVSDFH XVH HJ
scala.Symbol(" Programming Scala ")$OOWKHZKLWHVSDFHLVSUHVHUYHG

Tuples
+RZPDQ\WLPHVKDYH\RXZDQWHGWRUHWXUQWZRRUPRUHYDOXHVIURPDPHWKRG",Q
PDQ\ODQJXDJHVOLNH-DYD\RXRQO\KDYHDIHZRSWLRQVQRQHRIZKLFKLVYHU\DSSHDOLQJ
<RXFRXOGSDVVLQSDUDPHWHUVWRWKHPHWKRGWKDWZLOOEHPRGLILHGIRUDOORUVRPHRIWKH
£UHWXUQ¤YDOXHVZKLFKLVXJO\2U\RXFRXOGGHFODUHVRPHVPDOO£VWUXFWXUDO¤FODVVWKDW
KROGVWKHWZRRUPRUHYDOXHVWKHQUHWXUQDQLQVWDQFHRIWKDWFODVV
6FDODVXSSRUWVWXSOHVDJURXSLQJRIWZRRUPRUHLWHPVXVXDOO\FUHDWHGZLWKWKHOLWHUDO
V\QWD[RIDFRPPDVHSDUDWHGOLVWRIWKHLWHPVLQVLGHSDUHQWKHVHVHJ(x1, x2, ...)
7KHW\SHVRIWKHxLHOHPHQWVDUHXQUHODWHGWRHDFKRWKHU\RXFDQPL[DQGPDWFKW\SHV
7KHVH OLWHUDO £JURXSLQJV¤ DUH LQVWDQWLDWHG DV scala.TupleN LQVWDQFHV ZKHUH N LV WKH
QXPEHURILWHPVLQWKHWXSOH7KH6FDOD$3,GHILQHVVHSDUDWHTupleNFODVVHVIRUNEHWZHHQ
DQGLQFOXVLYH7XSOHLQVWDQFHVDUHLPPXWDEOHILUVWFODVVYDOXHVVR\RXFDQDVVLJQ
WKHPWRYDULDEOHVSDVVWKHPDVYDOXHVDQGUHWXUQWKHPIURPPHWKRGV
7KHIROORZLQJH[DPSOHGHPRQVWUDWHVWKHXVHRIWXSOHV
// code-examples/TypeLessDoMore/tuple-example-script.scala

def tupleator(x1: Any, x2: Any, x3: Any) = (x1, x2, x3)

val t = tupleator("Hello", 1, 2.3)


println( "Print the whole tuple: " + t )
println( "Print the first item: " + t._1 )
println( "Print the second item: " + t._2 )
println( "Print the third item: " + t._3 )

val (t1, t2, t3) = tupleator("World", '!', 0x22)


println( t1 + " " + t2 + " " + t3 )

5XQQLQJWKLVVFULSWZLWKscalaSURGXFHVWKHIROORZLQJRXWSXW
Print the whole tuple: (Hello,1,2.3)
Print the first item: Hello
Print the second item: 1
Print the third item: 2.3
World ! 34

7KHtupleatorPHWKRGVLPSO\UHWXUQVD£WXSOH¤ZLWKWKHLQSXWDUJXPHQWV7KHILUVW
VWDWHPHQWWKDWXVHVWKLVPHWKRGDVVLJQVWKHUHWXUQHGWXSOHWRDVLQJOHYDULDEOH t7KH
QH[W IRXU VWDWHPHQWV SULQW t LQ YDULRXV ZD\V 7KH ILUVW SULQW VWDWHPHQW FDOOV
Tuple3.toStringZKLFKZUDSVSDUHQWKHVHVDURXQGWKHLWHPOLVW7KHIROORZLQJWKUHH
VWDWHPHQWVSULQWHDFKLWHPLQ tVHSDUDWHO\7KHH[SUHVVLRQ t._NUHWULHYHVWKH NLWHP
VWDUWLQJDWQRW WKLVFKRLFHIROORZVIXQFWLRQDOSURJUDPPLQJFRQYHQWLRQV 

40 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
7KHODVWWZROLQHVVKRZWKDWZHFDQXVHDWXSOHH[SUHVVLRQRQWKHOHIWKDQGVLGHRIWKH
DVVLJQPHQW:HGHFODUHWKUHHvalV¢t1t2DQGt3¢WRKROGWKHLQGLYLGXDOLWHPVLQWKH
WXSOH,QHVVHQFHWKHWXSOHLWHPVDUHH[WUDFWHGDXWRPDWLFDOO\
1RWLFHKRZZHPL[HGW\SHVLQWKHWXSOHV<RXFDQVHHWKHW\SHVPRUHFOHDUO\LI\RXXVH
WKHLQWHUDFWLYHPRGHRIWKHscalaFRPPDQGZKLFKZHLQWURGXFHGLQ&KDSWHU
,QYRNH WKH scala FRPPDQG ZLWK QR VFULSW DUJXPHQW $W WKH scala> SURPSW HQWHU
val t = ("Hello",1,2.3)DQGVHHWKDW\RXJHWWKHIROORZLQJUHVXOWZKLFKVKRZV\RX
WKHW\SHRIHDFKHOHPHQWLQWKHWXSOH
scala> val t = ("Hello",1,2.3)
t: (java.lang.String, Int, Double) = (Hello,1,2.3)

,W¦VZRUWKQRWLQJWKDWWKHUH¦VPRUHWKDQRQHZD\WRGHILQHDWXSOH:H¦YHEHHQXVLQJ
WKHPRUHFRPPRQSDUHQWKHVL]HGV\QWD[EXW\RXFDQDOVRXVHWKHDUURZRSHUDWRUEH
WZHHQWZRYDOXHVDVZHOODVVSHFLDOIDFWRU\PHWKRGVRQWKHWXSOHUHODWHGFODVVHV
scala> 1 -> 2
res0: (Int, Int) = (1,2)

scala> Tuple2(1, 2)
res1: (Int, Int) = (1,2)

scala> Pair(1, 2)
res2: (Int, Int) = (1,2)

Option, Some, and None: Avoiding nulls


:H¦OO GLVFXVV WKH VWDQGDUG W\SH KLHUDUFK\ IRU 6FDOD LQ £7KH 6FDOD 7\SH +LHUDU
FK\¤ RQ SDJH  +RZHYHU WKUHH XVHIXO FODVVHV WR XQGHUVWDQG QRZ DUH WKH Option
FODVVDQGLWVWZRVXEFODVVHVSomeDQGNone
0RVWODQJXDJHVKDYHDVSHFLDONH\ZRUGRUREMHFWWKDW¦VDVVLJQHGWRUHIHUHQFHYDULDEOHV
ZKHQWKHUH¦VQRWKLQJHOVHIRUWKHPWRUHIHUWR,Q-DYDWKLVLVnullLQ5XE\LW¦Vnil,Q
-DYD nullLVDNH\ZRUGQRWDQREMHFWDQGWKXVLW¦VLOOHJDOWRFDOODQ\PHWKRGVRQLW
%XWWKLVLVDFRQIXVLQJFKRLFHRQWKHODQJXDJHGHVLJQHU¦VSDUW:K\UHWXUQDNH\ZRUG
ZKHQWKHSURJUDPPHUH[SHFWVDQREMHFW"
7REHPRUHFRQVLVWHQWZLWKWKHJRDORIPDNLQJHYHU\WKLQJDQREMHFWDVZHOODVWRFRQ
IRUP ZLWK IXQFWLRQDO SURJUDPPLQJ FRQYHQWLRQV 6FDOD HQFRXUDJHV \RX WR XVH WKH
OptionW\SHIRUYDULDEOHVDQGIXQFWLRQUHWXUQYDOXHVZKHQWKH\PD\RUPD\QRWUHIHUWR
DYDOXH:KHQWKHUHLVQRYDOXHXVHNoneDQobjectWKDWLVDVXEFODVVRIOption:KHQ
WKHUHLVDYDOXHXVHSomeZKLFKZUDSVWKHYDOXHSomeLVDOVRDVXEFODVVRIOption

NoneLVGHFODUHGDVDQobjectQRWDclassEHFDXVHZHUHDOO\RQO\QHHG
RQHLQVWDQFHRILW,QWKDWVHQVHLW¦VOLNHWKHnullNH\ZRUGEXWLWLVDUHDO
REMHFWZLWKPHWKRGV

Option, Some, and None: Avoiding nulls | 41

Download at WoweBook.Com
<RXFDQVHHOptionSomeDQGNoneLQDFWLRQLQWKHIROORZLQJH[DPSOHZKHUHZHFUHDWH
DPDSRIVWDWHFDSLWDOVLQWKH8QLWHG6WDWHV
// code-examples/TypeLessDoMore/state-capitals-subset-script.scala

val stateCapitals = Map(


"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
// ...
"Wyoming" -> "Cheyenne")

println( "Get the capitals wrapped in Options:" )


println( "Alabama: " + stateCapitals.get("Alabama") )
println( "Wyoming: " + stateCapitals.get("Wyoming") )
println( "Unknown: " + stateCapitals.get("Unknown") )

println( "Get the capitals themselves out of the Options:" )


println( "Alabama: " + stateCapitals.get("Alabama").get )
println( "Wyoming: " + stateCapitals.get("Wyoming").getOrElse("Oops!") )
println( "Unknown: " + stateCapitals.get("Unknown").getOrElse("Oops2!") )

7KHFRQYHQLHQW ->V\QWD[IRUGHILQLQJQDPHYDOXHSDLUVWRLQLWLDOL]HD MapZLOOEHGLV


FXVVHGLQ£7KH3UHGHI2EMHFW¤RQSDJH)RUQRZZHZDQWWRIRFXVRQWKHWZR
JURXSVRI printlnVWDWHPHQWVZKHUHZHVKRZZKDWKDSSHQVZKHQ\RXUHWULHYHWKH
YDOXHVIURPWKHPDS,I\RXUXQWKLVVFULSWZLWKWKH scalaFRPPDQG\RX¦OOJHWWKH
IROORZLQJRXWSXW
Get the capitals wrapped in Options:
Alabama: Some(Montgomery)
Wyoming: Some(Cheyenne)
Unknown: None
Get the capitals themselves out of the Options:
Alabama: Montgomery
Wyoming: Cheyenne
Unknown: Oops2!

7KHILUVWJURXSRI printlnVWDWHPHQWVLQYRNH toStringLPSOLFLWO\RQWKHLQVWDQFHVUH


WXUQHGE\ get:HDUHFDOOLQJ toStringRQ SomeRU NoneLQVWDQFHVEHFDXVHWKHYDOXHV
UHWXUQHGE\Map.getDUHDXWRPDWLFDOO\ZUDSSHGLQDSomeZKHQWKHUHLVDYDOXHLQWKH
PDSIRUWKHVSHFLILHGNH\1RWHWKDWWKH6FDODOLEUDU\GRHVQ¦WVWRUHWKHSomeLQWKHPDS
LWZUDSVWKHYDOXHLQD SomeXSRQUHWULHYDO&RQYHUVHO\ZKHQZHDVNIRUDPDSHQWU\
WKDWGRHVQ¦WH[LVWWKH NoneREMHFWLVUHWXUQHGUDWKHUWKDQ null7KLVRFFXUUHGLQWKH
ODVWprintlnRIWKHWKUHH
7KHVHFRQGJURXSRIprintlnVWDWHPHQWVJRHVDVWHSIXUWKHU$IWHUFDOOLQJMap.getWKH\
FDOO get RU getOrElse RQ HDFK Option LQVWDQFH WR UHWULHYH WKH YDOXH LW FRQWDLQV
Option.getUHTXLUHVWKDWWKH OptionLVQRWHPSW\¢WKDWLVWKH OptionLQVWDQFHPXVW
DFWXDOO\EHDSome,QWKLVFDVHgetUHWXUQVWKHYDOXHZUDSSHGE\WKHSomeDVGHPRQ
VWUDWHGLQWKH printlnZKHUHZHSULQWWKHFDSLWDORI$ODEDPD+RZHYHULIWKH Option
LVDFWXDOO\NoneWKHQNone.getWKURZVDNoSuchElementException

42 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
:HDOVRVKRZWKHDOWHUQDWLYHPHWKRG getOrElseLQWKHODVWWZR printlnVWDWHPHQWV
7KLVPHWKRGUHWXUQVHLWKHUWKHYDOXHLQWKHOptionLILWLVDSomeLQVWDQFHRULWUHWXUQV
WKHVHFRQGDUJXPHQWZHSDVVHGWR getOrElseLILWLVD NoneLQVWDQFH,QRWKHUZRUGV
WKHVHFRQGDUJXPHQWWRgetOrElseIXQFWLRQVDVWKHGHIDXOWUHWXUQYDOXH
6R getOrElseLVWKHPRUHGHIHQVLYHRIWKHWZRPHWKRGV,WDYRLGVDSRWHQWLDOWKURZQ
H[FHSWLRQ:H¦OOGLVFXVVWKHPHULWVRIDOWHUQDWLYHVOLNHgetYHUVXVgetOrElseLQ£([FHS
WLRQVDQGWKH$OWHUQDWLYHV¤RQSDJH
1RWHWKDWEHFDXVHWKHMap.getPHWKRGUHWXUQVDQOptionLWDXWRPDWLFDOO\GRFXPHQWV
WKHIDFWWKDWWKHUHPD\QRWEHDQLWHPPDWFKLQJWKHVSHFLILHGNH\7KHPDSKDQGOHV
WKLVVLWXDWLRQE\UHWXUQLQJDNone0RVWODQJXDJHVZRXOGUHWXUQnull RUWKHHTXLYDOHQW
ZKHQWKHUHLVQR£UHDO¤YDOXHWRUHWXUQ<RXOHDUQIURPH[SHULHQFHWRH[SHFWDSRVVLEOH
null8VLQJ OptionPDNHVWKHEHKDYLRUPRUHH[SOLFLWLQWKHPHWKRGVLJQDWXUHVRLW¦V
PRUHVHOIGRFXPHQWLQJ
$OVRWKDQNVWR6FDOD¦VVWDWLFW\SLQJ\RXFDQ¦WPDNHWKHPLVWDNHRIDWWHPSWLQJWRFDOO
DPHWKRGRQDYDOXHWKDWPLJKWDFWXDOO\EH null:KLOHWKLVPLVWDNHLVHDV\WRGRLQ
-DYD LW ZRQ¦W FRPSLOH LQ 6FDOD EHFDXVH \RX PXVW ILUVW H[WUDFW WKH YDOXH IURP WKH
Option6RWKHXVHRIOptionVWURQJO\HQFRXUDJHVPRUHUHVLOLHQWSURJUDPPLQJ
%HFDXVH6FDODUXQVRQWKH-90DQG1(7DQGEHFDXVHLWPXVWLQWHURSHUDWHZLWKRWKHU
OLEUDULHV6FDODKDVWRVXSSRUW null6WLOO\RXVKRXOGDYRLGXVLQJ nullLQ\RXUFRGH
7RQ\ +RDUH ZKR LQYHQWHG WKH QXOO UHIHUHQFH LQ  ZKLOH ZRUNLQJ RQ DQ REMHFW
RULHQWHGODQJXDJHFDOOHG$/*2/:FDOOHGLWVLQYHQWLRQKLV£ELOOLRQGROODUPLVWDNH¤
VHH>+RDUH@ 'RQ¦WFRQWULEXWHWRWKDWILJXUH
6RKRZZRXOG\RXZULWHDPHWKRGWKDWUHWXUQVDQ Option"+HUHLVDSRVVLEOHLPSOH
PHQWDWLRQ RI get WKDW FRXOG EH XVHG E\ D FRQFUHWH VXEFODVV RI Map Map.get LWVHOI LV
DEVWUDFW  )RU D PRUH VRSKLVWLFDWHG YHUVLRQ VHH WKH LPSOHPHQWDWLRQ RI get LQ
scala.collection.immutable.HashMapLQWKH6FDODOLEUDU\VRXUFHFRGHGLVWULEXWLRQ
def get(key: A): Option[B] = {
if (contains(key))
new Some(getValue(key))
else
None
}

7KHcontainsPHWKRGLVDOVRGHILQHGIRUMap,WUHWXUQVtrueLIWKHPDSFRQWDLQVDYDOXH
IRUWKHVSHFLILHGNH\7KHgetValuePHWKRGLVLQWHQGHGWREHDQLQWHUQDOPHWKRGWKDW
UHWULHYHVWKHYDOXHIURPWKHXQGHUO\LQJVWRUDJHZKDWHYHULWLV
1RWHKRZWKHYDOXHUHWXUQHGE\getValueLVZUDSSHGLQDSome[B]ZKHUHWKHW\SH BLV
LQIHUUHG+RZHYHULIWKHFDOOWR contains(key)UHWXUQV falseWKHQWKH object NoneLV
UHWXUQHG
<RXFDQXVHWKLVVDPHLGLRPZKHQ\RXUPHWKRGVUHWXUQDQOption:H¦OOH[SORUHRWKHU
XVHV IRU Option LQ VXEVHTXHQW VHFWLRQV ,WV SHUYDVLYH XVH LQ 6FDOD FRGH PDNHV LW DQ
LPSRUWDQWFRQFHSWWRJUDVS

Option, Some, and None: Avoiding nulls | 43

Download at WoweBook.Com
Organizing Code in Files and Namespaces
6FDODDGRSWVWKHSDFNDJHFRQFHSWWKDW-DYDXVHVIRUQDPHVSDFHVEXW6FDODRIIHUVDPRUH
IOH[LEOHV\QWD[-XVWDVILOHQDPHVGRQ¦WKDYHWRPDWFKWKHW\SHQDPHVWKHSDFNDJH
VWUXFWXUHGRHVQRWKDYHWRPDWFKWKHGLUHFWRU\VWUXFWXUH6R\RXFDQGHILQHSDFNDJHV
LQILOHVLQGHSHQGHQWRIWKHLU£SK\VLFDO¤ORFDWLRQ
7KHIROORZLQJH[DPSOHGHILQHVDFODVV MyClassLQDSDFNDJH com.example.mypkgXVLQJ
WKHFRQYHQWLRQDO-DYDV\QWD[
// code-examples/TypeLessDoMore/package-example1.scala

package com.example.mypkg

class MyClass {
// ...
}

7KHQH[WH[DPSOHVKRZVDFRQWULYHGH[DPSOHWKDWGHILQHVSDFNDJHVXVLQJWKHQHVWHG
SDFNDJHV\QWD[LQ6FDODZKLFKLVVLPLODUWRWKHnamespaceV\QWD[LQ&DQGWKHXVHRI
modulesDVQDPHVSDFHVLQ5XE\
// code-examples/TypeLessDoMore/package-example2.scala

package com {
package example {
package pkg1 {
class Class11 {
def m = "m11"
}
class Class12 {
def m = "m12"
}
}

package pkg2 {
class Class21 {
def m = "m21"
def makeClass11 = {
new pkg1.Class11
}
def makeClass12 = {
new pkg1.Class12
}
}
}

package pkg3.pkg31.pkg311 {
class Class311 {
def m = "m21"
}
}
}
}

44 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
7ZR SDFNDJHV pkg1 DQG pkg2 DUH GHILQHG XQGHU WKH com.example SDFNDJH $ WRWDO
RI WKUHH FODVVHV DUH GHILQHG EHWZHHQ WKH WZR SDFNDJHV 7KH makeClass11 DQG
makeClass12 PHWKRGV LQ Class21 LOOXVWUDWH KRZ WR UHIHUHQFH D W\SH LQ WKH £VLEOLQJ¤
SDFNDJH pkg1 <RX FDQ DOVR UHIHUHQFH WKHVH FODVVHV E\ WKHLU IXOO SDWKV
com.example.pkg1.Class11DQGcom.example.pkg1.Class12UHVSHFWLYHO\
7KHSDFNDJHpkg3.pkg31.pkg311VKRZVWKDW\RXFDQ£FKDLQ¤VHYHUDOSDFNDJHVWRJHWKHU
LQRQHFODXVH,WLVQRWQHFHVVDU\WRXVHDVHSDUDWHpackageFODXVHIRUHDFKSDFNDJH
)ROORZLQJWKHFRQYHQWLRQVRI-DYDWKHURRWSDFNDJHIRU6FDOD¦VOLEUDU\FODVVHVLVQDPHG
scala

6FDODGRHVQRWDOORZSDFNDJHGHFODUDWLRQVLQVFULSWVWKDWDUHH[HFXWHG
GLUHFWO\ZLWKWKH scalaLQWHUSUHWHU7KHUHDVRQKDVWRGRZLWKWKHZD\
WKH LQWHUSUHWHU FRQYHUWV VWDWHPHQWV LQ VFULSWV WR YDOLG 6FDOD FRGH
EHIRUH FRPSLOLQJ WR E\WH FRGH 6HH £7KH VFDOD &RPPDQG/LQH
7RRO¤RQSDJHIRUPRUHGHWDLOV

Importing Types and Their Members


7RXVHGHFODUDWLRQVLQSDFNDJHV\RXKDYHWRLPSRUWWKHPMXVWDV\RXGRLQ-DYDDQG
VLPLODUO\IRURWKHUODQJXDJHV+RZHYHUFRPSDUHGWR-DYD6FDODJUHDWO\H[SDQGV\RXU
RSWLRQV7KHIROORZLQJH[DPSOHLOOXVWUDWHVVHYHUDOZD\VWRLPSRUW-DYDW\SHV
// code-examples/TypeLessDoMore/import-example1.scala

import java.awt._
import java.io.File
import java.io.File._
import java.util.{Map, HashMap}

<RXFDQLPSRUWDOOW\SHVLQDSDFNDJHXVLQJWKHXQGHUVFRUH _ DVDZLOGFDUGDVVKRZQ
RQWKHILUVWOLQH<RXFDQDOVRLPSRUWLQGLYLGXDO6FDODRU-DYDW\SHVDVVKRZQRQWKH
VHFRQGOLQH
-DYDXVHVWKH£VWDU¤FKDUDFWHU * DVWKHZLOGFDUGIRUPDWFKLQJDOOW\SHVLQDSDFNDJHRU
DOOVWDWLFPHPEHUVRIDW\SHZKHQGRLQJ£VWDWLFLPSRUWV¤,Q6FDODWKLVFKDUDFWHULV
DOORZHGLQPHWKRGQDPHVVR_LVXVHGDVDZLOGFDUGDVZHVDZSUHYLRXVO\
$VVKRZQRQWKHWKLUGOLQH\RXFDQLPSRUWDOOWKHVWDWLFPHWKRGVDQGILHOGVLQ-DYD
W\SHV,I java.io.FileZHUHDFWXDOO\D6FDOD objectDVGLVFXVVHGSUHYLRXVO\WKHQWKLV
OLQHZRXOGLPSRUWWKHILHOGVDQGPHWKRGVIURPWKHREMHFW
)LQDOO\\RXFDQVHOHFWLYHO\LPSRUWMXVWWKHW\SHV\RXFDUHDERXW2QWKHIRXUWKOLQHZH
LPSRUWMXVWWKH java.util.MapDQG java.util.HashMapW\SHVIURPWKH java.utilSDFN
DJH&RPSDUHWKLVRQHOLQHLPSRUWVWDWHPHQWZLWKWKHWZROLQHLPSRUWVWDWHPHQWVZH
XVHG LQ RXU ILUVW H[DPSOH LQ £,QIHUULQJ 7\SH ,QIRUPDWLRQ¤ RQ SDJH  7KH\ DUH
IXQFWLRQDOO\HTXLYDOHQW

Importing Types and Their Members | 45

Download at WoweBook.Com
7KHQH[WH[DPSOHVKRZVPRUHDGYDQFHGRSWLRQVIRULPSRUWVWDWHPHQWV
// code-examples/TypeLessDoMore/import-example2-script.scala

def writeAboutBigInteger() = {

import java.math.BigInteger.{
ONE => _,
TEN,
ZERO => JAVAZERO }

// ONE is effectively undefined


// println( "ONE: "+ONE )
println( "TEN: "+TEN )
println( "ZERO: "+JAVAZERO )
}

writeAboutBigInteger()

7KLVH[DPSOHGHPRQVWUDWHVWZRIHDWXUHV)LUVWZHFDQSXWLPSRUWVWDWHPHQWVDOPRVW
DQ\ZKHUHZHZDQWQRWMXVWDWWKHWRSRIWKHILOHDVUHTXLUHGE\-DYD7KLVIHDWXUHDOORZV
XVWRVFRSHWKHLPSRUWVPRUHQDUURZO\)RUH[DPSOHZHFDQ¦WUHIHUHQFHWKHLPSRUWHG
BigIntegerGHILQLWLRQVRXWVLGHWKHVFRSHRIWKHPHWKRG$QRWKHUDGYDQWDJHRIWKLVIHD
WXUHLVWKDWLWSXWVDQLPSRUWVWDWHPHQWFORVHUWRZKHUHWKHLPSRUWHGLWHPVDUHDFWXDOO\
XVHG
7KH VHFRQG IHDWXUH VKRZQ LV WKH DELOLW\ WR UHQDPH LPSRUWHG LWHPV )LUVW WKH
java.math.BigInteger.ONEFRQVWDQWLVUHQDPHGWRWKHXQGHUVFRUHZLOGFDUG7KLVHIIHF
WLYHO\PDNHVLWLQYLVLEOHDQGXQDYDLODEOHWRWKHLPSRUWLQJVFRSH7KLVLVDXVHIXOWHFK
QLTXHZKHQ\RXZDQWWRLPSRUWHYHU\WKLQJH[FHSWDIHZSDUWLFXODULWHPV
1H[WWKHjava.math.BigInteger.TENFRQVWDQWLVLPSRUWHGZLWKRXWUHQDPLQJVRLWFDQ
EHUHIHUHQFHGVLPSO\DVTEN
)LQDOO\WKHjava.math.BigInteger.ZEROFRQVWDQWLVJLYHQWKH£DOLDV¤JAVAZERO
$OLDVLQJLVXVHIXOLI\RXZDQWWRJLYHWKHLWHPDPRUHFRQYHQLHQWQDPHRU\RXZDQWWR
DYRLGDPELJXLWLHVZLWKRWKHULWHPVLQVFRSHWKDWKDYHWKHVDPHQDPH

Imports are Relative


7KHUH¦VRQHRWKHULPSRUWDQWWKLQJWRNQRZDERXWLPSRUWVWKH\DUHUHODWLYH1RWHWKH
FRPPHQWVIRUWKHIROORZLQJLPSRUWV
// code-examples/TypeLessDoMore/relative-imports.scala
import scala.collection.mutable._
import collection.immutable._ // Since "scala" is already imported
import _root_.scala.collection.jcl._ // full path from real "root"
package scala.actors {
import remote._ // We're in the scope of "scala.actors"
}

46 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
1RWHWKDWWKHODVWLPSRUWVWDWHPHQWQHVWHGLQWKHscala.actorSDFNDJHVFRSHLVUHODWLYH
WRWKDWVFRSH
7KH>6FDOD:LNL@KDVRWKHUH[DPSOHVDWKWWSVFDODV\JQHFDFRPIDTVODQJXDJHKRZGR
LLPSRUW
,W¦VIDLUO\UDUHWKDW\RX¦OOKDYHSUREOHPVZLWKUHODWLYHLPSRUWVEXWWKHSUREOHPZLWK
WKLVFRQYHQWLRQLVWKDWWKH\VRPHWLPHVFDXVHVXUSULVHVHVSHFLDOO\LI\RXDUHDFFXVWRPHG
WRODQJXDJHVOLNH-DYDZKHUHLPSRUWVDUHDEVROXWH,I\RXJHWDP\VWLI\LQJFRPSLOHU
HUURUWKDWDSDFNDJHZDVQ¦WIRXQGFKHFNWKDWWKHVWDWHPHQWLVSURSHUO\UHODWLYHWRWKH
ODVWLPSRUWVWDWHPHQWRUDGGWKH _root_.SUHIL[$OVR\RXPLJKWVHHDQ,'(RURWKHU
WRROLQVHUWDQimport _root_...VWDWHPHQWLQ\RXUFRGH1RZ\RXNQRZZKDWLWPHDQV

5HPHPEHUWKDWLPSRUWVWDWHPHQWVDUHUHODWLYHQRWDEVROXWH7RFUHDWH
DQDEVROXWHSDWKVWDUWZLWK_root_

Abstract Types And Parameterized Types


:H PHQWLRQHG LQ £$ 7DVWH RI 6FDOD¤ RQ SDJH  WKDW 6FDOD VXSSRUWV SDUDPHWHUL]HG
W\SHVZKLFKDUHYHU\VLPLODUWRJHQHULFVLQ-DYD :HFRXOGXVHWKHWZRWHUPVLQWHU
FKDQJHDEO\ EXW LW¦V PRUH FRPPRQ WR XVH £SDUDPHWHUL]HG W\SHV¤ LQ WKH 6FDOD FRP
PXQLW\DQG£JHQHULFV¤LQWKH-DYDFRPPXQLW\ 7KHPRVWREYLRXVGLIIHUHQFHLVLQWKH
V\QWD[ZKHUH6FDODXVHVVTXDUHEUDFNHWV [...] ZKLOH-DYDXVHVDQJOHEUDFNHWV <...> 
)RUH[DPSOHDOLVWRIVWULQJVZRXOGEHGHFODUHGDVIROORZV
val languages: List[String] = ...

7KHUH DUH RWKHU LPSRUWDQW GLIIHUHQFHV ZLWK -DYD¦V JHQHULFV ZKLFK ZH¦OO H[SORUH LQ
£8QGHUVWDQGLQJ3DUDPHWHUL]HG7\SHV¤RQSDJH
)RUQRZZH¦OOPHQWLRQRQHRWKHUXVHIXOGHWDLOWKDW\RX¦OOHQFRXQWHUEHIRUHZHFDQ
H[SODLQLWLQGHSWKLQ&KDSWHU,I\RXORRNDWWKHGHFODUDWLRQRI scala.ListLQWKH
6FDODGRFV\RX¦OOVHHWKDWWKHGHFODUDWLRQLVZULWWHQDV ... class List[+A]7KH +LQ
IURQWRIWKHAPHDQVWKDWList[B]LVDVXEW\SHRIList[A]IRUDQ\BWKDWLVDVXEW\SHRI
A,IWKHUHLVD-LQIURQWRIDW\SHSDUDPHWHUWKHQWKHUHODWLRQVKLSJRHVWKHRWKHUZD\
Foo[B]ZRXOGEHDVXSHUW\SHRIFoo[A]LIWKHGHFODUDWLRQLVFoo[-A]
6FDODVXSSRUWVDQRWKHUW\SHDEVWUDFWLRQPHFKDQLVPFDOOHGDEVWUDFWW\SHVXVHGLQPDQ\
IXQFWLRQDOSURJUDPPLQJODQJXDJHVVXFKDV+DVNHOO$EVWUDFWW\SHVZHUHDOVRFRQVLG
HUHGIRULQFOXVLRQLQ-DYDZKHQJHQHULFVZHUHDGRSWHG:HZDQWWRLQWURGXFHWKHP
QRZ EHFDXVH \RX¦OO VHH PDQ\ H[DPSOHV RI WKHP EHIRUH ZH GLYH LQWR WKHLU GHWDLOV LQ
&KDSWHU)RUDYHU\GHWDLOHGFRPSDULVRQRIWKHVHWZRPHFKDQLVPVVHH>%UXFH@
$EVWUDFWW\SHVFDQEHDSSOLHGWRPDQ\RIWKHVDPHGHVLJQSUREOHPVIRUZKLFKSDUD
PHWHUL]HGW\SHVDUHXVHG+RZHYHUZKLOHWKHWZRPHFKDQLVPVRYHUODSWKH\DUHQRW
UHGXQGDQW(DFKKDVVWUHQJWKVDQGZHDNQHVVHVIRUFHUWDLQGHVLJQSUREOHPV

Abstract Types And Parameterized Types | 47

Download at WoweBook.Com
+HUHLVDQH[DPSOHWKDWXVHVDQDEVWUDFWW\SH
// code-examples/TypeLessDoMore/abstract-types-script.scala

import java.io._

abstract class BulkReader {


type In
val source: In
def read: String
}

class StringBulkReader(val source: String) extends BulkReader {


type In = String
def read = source
}

class FileBulkReader(val source: File) extends BulkReader {


type In = File
def read = {
val in = new BufferedInputStream(new FileInputStream(source))
val numBytes = in.available()
val bytes = new Array[Byte](numBytes)
in.read(bytes, 0, numBytes)
new String(bytes)
}
}

println( new StringBulkReader("Hello Scala!").read )


println( new FileBulkReader(new File("abstract-types-script.scala")).read )

5XQQLQJWKLVVFULSWZLWKscalaSURGXFHVWKHIROORZLQJRXWSXW
Hello Scala!
import java.io._

abstract class BulkReader {


...

7KH BulkReader DEVWUDFW FODVV GHFODUHV WKUHH DEVWUDFW PHPEHUV D type QDPHG In D
valILHOGsourceDQGDreadPHWKRG$VLQ-DYDLQVWDQFHVLQ6FDODFDQRQO\EHFUHDWHG
IURPFRQFUHWHFODVVHVZKLFKPXVWKDYHGHILQLWLRQVIRUDOOPHPEHUV
7KH GHULYHG FODVVHV StringBulkReader DQG FileBulkReader SURYLGH FRQFUHWH GHILQL
WLRQVIRUWKHVHDEVWUDFWPHPEHUV:H¦OOFRYHUWKHGHWDLOVRIFODVVGHFODUDWLRQVLQ&KDS
WHUDQGWKHSDUWLFXODUVRIRYHUULGLQJPHPEHUGHFODUDWLRQVLQ£2YHUULGLQJ0HPEHUV
RI&ODVVHVDQG7UDLWV¤RQSDJHLQ&KDSWHU
)RUQRZQRWHWKDWWKHtypeILHOGZRUNVYHU\PXFKOLNHDW\SHSDUDPHWHULQDSDUDPH
WHUL]HGW\SH,QIDFWZHFRXOGUHZULWHWKLVH[DPSOHDVIROORZVZKHUHZHVKRZRQO\
ZKDWZRXOGEHGLIIHUHQW
abstract class BulkReader[In] {
val source: In
...

48 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
}

class StringBulkReader(val source: String) extends BulkReader[String] {...}

class FileBulkReader(val source: File) extends BulkReader[File] {...}

-XVWDVIRUSDUDPHWHUL]HGW\SHVLIZHGHILQHWKHInW\SHWREHStringWKHQWKHsource
ILHOGPXVWDOVREHGHILQHGDVDString1RWHWKDWWKHStringBulkReader¦VreadPHWKRG
VLPSO\UHWXUQVWKHsourceILHOGZKLOHWKHFileBulkReader¦VreadPHWKRGUHDGVWKHFRQ
WHQWVRIWKHILOH
$VGHPRQVWUDWHGE\>%UXFH@SDUDPHWHUL]HGW\SHVWHQGWREHEHVWIRUFROOHFWLRQV
ZKLFKLVKRZWKH\DUHPRVWRIWHQXVHGLQ-DYDFRGHZKHUHDVDEVWUDFWW\SHVDUHPRVW
XVHIXOIRUW\SH£IDPLOLHV¤DQGRWKHUW\SHVFHQDULRV
:H¦OOH[SORUHWKHGHWDLOVRI6FDOD¦VDEVWUDFWW\SHVLQ&KDSWHU)RUH[DPSOHZH¦OOVHH
KRZWRFRQVWUDLQWKHSRVVLEOHFRQFUHWHW\SHVWKDWFDQEHXVHG

Reserved Words
7DEOHOLVWVWKHUHVHUYHGZRUGVLQ6FDODZKLFKZHVRPHWLPHVFDOO£NH\ZRUGV¤DQG
EULHIO\GHVFULEHVKRZWKH\DUHXVHG VHH>6FDOD6SHF@ 
7DEOH5HVHUYHGZRUGV
Word Description See …
abstract Makes a declaration abstract. Unlike Java, the keyword is usually “Class and Object Basics” on page 89
not required for abstract members.
case Start a case clause in a match expression. “Pattern Matching” on page 63
catch Start a clause for catching thrown exceptions. “Using try, catch, and finally Clau-
ses” on page 70
class Start a class declaration. “Class and Object Basics” on page 89
def Start a method declaration. “Method Declarations” on page 25
do Start a do...while loop. “Other Looping Constructs”
on page 61
else Start an else clause for an if clause. “Scala if Statements” on page 58
extends Indicates that the class or trait that follows is the parent type of the “Parent Classes” on page 91
class or trait being declared.
false Boolean false. “The Scala Type Hierarchy”
on page 155
final Applied to a class or trait to prohibit deriving child types from it. “Attempting to Override final Declara-
Applied to a member to prohibit overriding it in a derived class or tions” on page 112
trait.
finally Start a clause that is executed after the corresponding try clause, “Using try, catch, and finally Clau-
whether or not an exception is thrown by the try clause. ses” on page 70

Reserved Words | 49

Download at WoweBook.Com
Word Description See …
for Start a for comprehension (loop). “Scala for Comprehen-
sions” on page 59
forSome Used in existential type declarations to constrain the allowed “Existential Types” on page 284
concrete types that can be used.
if Start an if clause. “Scala if Statements” on page 58
implicit Marks a method as eligible to be used as an implicit type converter. “Implicit Conversions” on page 186
Marks a method parameter as optional, as long as a type-
compatible substitute object is in the scope where the method is
called.
import Import one or more types or members of types into the current “Importing Types and Their Mem-
scope. bers” on page 45
lazy Defer evaluation of a val. “Lazy Vals” on page 190
match Start a pattern matching clause. “Pattern Matching” on page 63
new Create a new instance of a class. “Class and Object Basics” on page 89
null Value of a reference variable that has not been assigned a value. “The Scala Type Hierarchy”
on page 155
object Start a singleton declaration: a class with only one instance. “Classes and Objects: Where Are the
Statics?” on page 148
override Override a concrete member of a class or trait, as long as the original “Overriding Members of Classes and
is not marked final. Traits” on page 111
package Start a package scope declaration. “Organizing Code in Files and Namespa-
ces” on page 44
private Restrict visibility of a declaration. “Visibility Rules” on page 96
protected Restrict visibility of a declaration. “Visibility Rules” on page 96
requires Deprecated. Was used for self typing. “The Scala Type Hierarchy”
on page 155
return Return from a function. “A Taste of Scala” on page 10
sealed Applied to a parent class to require all directly derived “Case Classes” on page 136
classes to be declared in the same source file.
super Analogous to this, but binds to the parent type. “Overriding Abstract and Concrete
Methods” on page 112
this How an object refers to itself. The method name for auxiliary “Class and Object Basics” on page 89
constructors.
throw Throw an exception. “Using try, catch, and finally Clau-
ses” on page 70
trait A mixin module that adds additional state and behavior to an Chapter 4
instance of a class.
try Start a block that may throw an exception. “Using try, catch, and finally Clau-
ses” on page 70

50 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
Word Description See …
true Boolean true. “The Scala Type Hierarchy”
on page 155
type Start a type declaration. “Abstract Types And Parameterized
Types” on page 47
val Start a read-only “variable” declaration. “Variable Declarations” on page 24
var Start a read-write variable declaration. “Variable Declarations” on page 24
while Start a while loop. “Other Looping Constructs”
on page 61
with Include the trait that follows in the class being declared or the object Chapter 4
being instantiated.
yield Return an element in a for comprehension that becomes part of “Yielding” on page 60
a sequence.
_ A placeholder, used in imports, function literals, etc. Many
: Separator between identifiers and type annotations. “A Taste of Scala” on page 10
= Assignment. “A Taste of Scala” on page 10
=> Used in function literals to separate the argument list from the “Function Literals and Clo-
function body. sures” on page 169
<- Used in for comprehensions in generator expressions. “Scala for Comprehen-
sions” on page 59
<: Used in parameterized and abstract type declarations to constrain “Type Bounds” on page 259
the allowed types.
<% Used in parameterized and abstract type “view bounds” “Type Bounds” on page 259
declarations.
>: Used in parameterized and abstract type declarations to constrain “Type Bounds” on page 259
the allowed types.
# Used in type projections. “Path-Dependent Types” on page 272
@ Marks an annotation. “Annotations” on page 289
º (Unicode \u21D2) Same as =>. “Function Literals and Clo-
sures” on page 169
← (Unicode \u2190) Same as <-. “Scala for Comprehen-
sions” on page 59

1RWLFHWKDW breakDQG continueDUHQRWOLVWHG7KHVHFRQWURONH\ZRUGVGRQ¦WH[LVWLQ


6FDOD,QVWHDG6FDODHQFRXUDJHV\RXWRXVHIXQFWLRQDOSURJUDPPLQJLGLRPVWKDWDUH
XVXDOO\PRUHVXFFLQFWDQGOHVVHUURUSURQH:H¦OOGLVFXVVDOWHUQDWLYHDSSURDFKHVZKHQ
ZHGLVFXVVforORRSV VHH£*HQHUDWRU([SUHVVLRQV¤RQSDJH 
6RPH -DYD PHWKRGV XVH QDPHV WKDW DUH UHVHUYHG E\ 6FDOD IRU H[DPSOH
java.util.Scanner.match7RDYRLGDFRPSLODWLRQHUURUVXUURXQGWKHQDPHZLWKVLQJOH
EDFNTXRWHVHJjava.util.Scanner.ÂmatchÂ

Reserved Words | 51

Download at WoweBook.Com
Recap and What’s Next
:HFRYHUHGVHYHUDOZD\VWKDW6FDOD¦VV\QWD[LVFRQFLVHIOH[LEOHDQGSURGXFWLYH:H
DOVRGHVFULEHGPDQ\6FDODIHDWXUHV,QWKHQH[WFKDSWHUZHZLOOURXQGRXWVRPH6FDOD
HVVHQWLDOV EHIRUH ZH GLYH LQWR 6FDOD¦V VXSSRUW IRU REMHFWRULHQWHG SURJUDPPLQJ DQG
IXQFWLRQDOSURJUDPPLQJ

52 | Chapter 2:—Type Less, Do More

Download at WoweBook.Com
CHAPTER 3
Rounding Out the Essentials

%HIRUHZHGLYHLQWR6FDOD¦VVXSSRUWIRUREMHFWRULHQWHGDQGIXQFWLRQDOSURJUDPPLQJ
OHW¦VILQLVKRXUGLVFXVVLRQRIWKHHVVHQWLDOIHDWXUHV\RX¦OOXVHLQPRVWRI\RXUSURJUDPV

Operator? Operator?
$QLPSRUWDQWIXQGDPHQWDOFRQFHSWLQ6FDODLVWKDWDOORSHUDWRUVDUHDFWXDOO\PHWKRGV
&RQVLGHUWKLVPRVWEDVLFRIH[DPSOHV
// code-examples/Rounding/one-plus-two-script.scala

1 + 2

7KDW SOXV VLJQ EHWZHHQ WKH QXPEHUV" ,W¦V D PHWKRG )LUVW 6FDOD DOORZV QRQ
DOSKDQXPHULFPHWKRGQDPHV<RXFDQFDOOPHWKRGV + - $RUZKDWHYHU\RXGHVLUH
6HFRQGWKLVH[SUHVVLRQLVLGHQWLFDOWR1 .+(2) :HSXWDVSDFHDIWHUWKH1EHFDXVH1.
ZRXOGEHLQWHUSUHWHGDVDDouble :KHQDPHWKRGWDNHVRQHDUJXPHQW6FDODOHWV\RX
GURS ERWK WKH SHULRG DQG WKH SDUHQWKHVHV VR WKH PHWKRG LQYRFDWLRQ ORRNV OLNH DQ
RSHUDWRULQYRFDWLRQ7KLVLVFDOOHG£LQIL[¤QRWDWLRQZKHUHWKHRSHUDWRULVEHWZHHQWKH
LQVWDQFHDQGWKHDUJXPHQW:H¦OOILQGRXWPRUHDERXWWKLVVKRUWO\
6LPLODUO\DPHWKRGZLWKQRDUJXPHQWVFDQEHLQYRNHGZLWKRXWWKHSHULRG7KLVLVFDOOHG
£SRVWIL[¤QRWDWLRQ
5XE\DQG6PDOOWDONSURJUDPPHUVVKRXOGQRZIHHOULJKWDWKRPH$VXVHUVRIWKRVH
ODQJXDJHVNQRZWKHVHVLPSOHUXOHVKDYHIDUUHDFKLQJEHQHILWVZKHQLWFRPHVWRFUHDWLQJ
SURJUDPVWKDWIORZQDWXUDOO\DQGHOHJDQWO\
6RZKDWFKDUDFWHUVFDQ\RXXVHLQLGHQWLILHUV"+HUHLVDVXPPDU\RIWKHUXOHVIRULGHQ
WLILHUV XVHG IRU PHWKRG DQG W\SH QDPHV YDULDEOHV HWF )RU WKH SUHFLVH GHWDLOV VHH
>6FDOD6SHF@6FDODDOORZVDOOWKHSULQWDEOH$6&,,FKDUDFWHUVVXFKDVOHWWHUVGLJLWV
WKHXQGHUVFRUH _ DQGWKHGROODUVLJQ $ ZLWKWKHH[FHSWLRQVRIWKH£SDUHQWKHWLFDO¤
FKDUDFWHUV¢()[]{DQG}¢DQGWKH£GHOLPLWHU¤FKDUDFWHUV¢`’'".;DQG,
6FDODDOORZVWKHRWKHUFKDUDFWHUVEHWZHHQ?X¡?X)WKDWDUHQRWLQWKHVHWVMXVW

53

Download at WoweBook.Com
VKRZQVXFKDVPDWKHPDWLFDOV\PEROVDQG£RWKHU¤V\PEROV7KHVHUHPDLQLQJFKDUDF
WHUVDUHFDOOHGRSHUDWRUFKDUDFWHUVDQGWKH\LQFOXGHFKDUDFWHUVVXFKDV/<HWF
5HVHUYHGZRUGVFDQ¦WEHXVHG
$VLQPRVWODQJXDJHV\RXFDQ¦WUHXVHUHVHUYHGZRUGVIRULGHQWLILHUV:HOLVWHGWKH
UHVHUYHGZRUGVLQ£5HVHUYHG:RUGV¤RQSDJH5HFDOOWKDWVRPHRIWKHPDUH
FRPELQDWLRQVRIRSHUDWRUDQGSXQFWXDWLRQFKDUDFWHUV)RUH[DPSOHDVLQJOHXQ
GHUVFRUH _ LVDUHVHUYHGZRUG
3ODLQLGHQWLILHUV¢FRPELQDWLRQVRIOHWWHUVGLJLWV$_DQGRSHUDWRUV
/LNH-DYDDQGPDQ\ODQJXDJHVDSODLQLGHQWLILHUFDQEHJLQZLWKDOHWWHURUXQGHU
VFRUH IROORZHG E\ PRUH OHWWHUV GLJLWV XQGHUVFRUHV DQG GROODU VLJQV 8QLFRGH
HTXLYDOHQWFKDUDFWHUVDUHDOVRDOORZHG+RZHYHUOLNH-DYD6FDODUHVHUYHVWKHGROODU
VLJQ IRU LQWHUQDO XVH VR \RX VKRXOGQ¦W XVH LW LQ \RXU RZQ LGHQWLILHUV $IWHU DQ
XQGHUVFRUH\RXFDQKDYHHLWKHUOHWWHUVDQGGLJLWVRUDVHTXHQFHRIRSHUDWRUFKDU
DFWHUV7KHXQGHUVFRUHLVLPSRUWDQW,WWHOOVWKHFRPSLOHUWRWUHDWDOOWKHFKDUDFWHUV
XSWRWKHQH[WZKLWHVSDFHDVSDUWRIWKHLGHQWLILHU)RUH[DPSOHval xyz_++= = 1
DVVLJQVWKHYDULDEOHxyz_++=WKHYDOXH1ZKLOHWKHH[SUHVVLRQval xyz++= = 1ZRQ¦W
FRPSLOHEHFDXVHWKH£LGHQWLILHU¤FRXOGDOVREHLQWHUSUHWHGDVxyz ++=ZKLFKORRNV
OLNHDQDWWHPSWWRDSSHQGVRPHWKLQJWRxyz6LPLODUO\LI\RXKDYHRSHUDWRUFKDU
DFWHUVDIWHUWKHXQGHUVFRUH\RXFDQ¦WPL[WKHPZLWKOHWWHUVDQGGLJLWV7KLVUH
VWULFWLRQSUHYHQWVDPELJXRXVH[SUHVVLRQVOLNHWKLV abc_=123,VWKDWDQLGHQWLILHU
abc_=123RUDQDVVLJQPHQWRIWKHYDOXH123WRabc_"
3ODLQLGHQWLILHUV¢RSHUDWRUV
,IDQLGHQWLILHUEHJLQVZLWKDQRSHUDWRUFKDUDFWHUWKHUHVWRIWKHFKDUDFWHUVPXVW
EHRSHUDWRUFKDUDFWHUV
£%DFNTXRWH¤OLWHUDOV
$QLGHQWLILHUFDQDOVREHDQDUELWUDU\VWULQJ VXEMHFWWRSODWIRUPOLPLWDWLRQV EH
WZHHQWZREDFNTXRWHFKDUDFWHUVHJval `this is a valid identifier` = "Hello
World!"5HFDOOWKDWWKLVV\QWD[LVDOVRWKHZD\WRLQYRNHDPHWKRGRQD-DYDRU1(7
FODVV ZKHQ WKH PHWKRG¦V QDPH LV LGHQWLFDO WR D 6FDOD UHVHUYHG ZRUG HJ
java.net.Proxy.ÂtypeÂ()
3DWWHUQPDWFKLQJLGHQWLILHUV
,Q SDWWHUQ PDWFKLQJ H[SUHVVLRQV WRNHQV WKDW EHJLQ ZLWK D ORZHUFDVH OHWWHU DUH
SDUVHGDVYDULDEOHLGHQWLILHUVZKLOHWRNHQVWKDWEHJLQZLWKDQXSSHUFDVHOHWWHUDUH
SDUVHGDVFRQVWDQWLGHQWLILHUV7KLVUHVWULFWLRQSUHYHQWVVRPHDPELJXLWLHVEHFDXVH
RIWKHYHU\VXFFLQFWYDULDEOHV\QWD[WKDWLVXVHGHJQRvalNH\ZRUGLVSUHVHQW

Syntactic Sugar
2QFH\RXNQRZWKDWDOORSHUDWRUVDUHPHWKRGVLW¦VHDVLHUWRUHDVRQDERXWXQIDPLOLDU
6FDODFRGH<RXGRQ¦WKDYHWRZRUU\DERXWVSHFLDOFDVHVZKHQ\RXVHHQHZRSHUDWRUV
:KHQZRUNLQJZLWK$FWRUVLQ£$7DVWHRI&RQFXUUHQF\¤RQSDJH\RXPD\KDYH
QRWLFHGWKDWZHXVHGDQH[FODPDWLRQSRLQW ! WRVHQGDPHVVDJHWRDQ$FWRU1RZ\RX

54 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
NQRZWKDWWKH!LVMXVWDQRWKHUPHWKRGDVDUHWKHRWKHUKDQG\VKRUWFXWRSHUDWRUV\RX
FDQXVHWRWDONWR$FWRUV6LPLODUO\6FDOD¦V;0/OLEUDU\SURYLGHVWKH\DQG\\RSHUDWRUV
WRGLYHLQWRGRFXPHQWVWUXFWXUHV7KHVHDUHMXVWPHWKRGVRQWKH scala.xml.NodeSeq
FODVV
7KLVIOH[LEOHPHWKRGQDPLQJJLYHV\RXWKHSRZHUWRZULWHOLEUDULHVWKDWIHHOOLNHDQDWXUDO
H[WHQVLRQRI6FDODLWVHOI<RXFRXOGZULWHDQHZPDWKOLEUDU\ZLWKQXPHULFW\SHVWKDW
DFFHSWDOOWKHXVXDOPDWKHPDWLFDORSHUDWRUVOLNHDGGLWLRQDQGVXEWUDFWLRQ<RXFRXOG
ZULWHDQHZFRQFXUUHQWPHVVDJLQJOD\HUWKDWEHKDYHVMXVWOLNH$FWRUV7KHSRVVLELOLWLHV
DUHFRQVWUDLQHGRQO\E\6FDOD¦VPHWKRGQDPLQJOLPLWDWLRQV

-XVWEHFDXVH\RXFDQGRHVQ¦WPHDQ\RXVKRXOG:KHQGHVLJQLQJ\RXU
RZQOLEUDULHVDQG$3,VLQ6FDODNHHSLQPLQGWKDWREVFXUHSXQFWXDWLRQDO
RSHUDWRUVDUHKDUGIRUSURJUDPPHUVWRUHPHPEHU2YHUXVHRIWKHVHFDQ
FRQWULEXWHD£OLQHQRLVH¤TXDOLW\RIXQUHDGDELOLW\WR\RXUFRGH6WLFNWR
FRQYHQWLRQVDQGHUURQWKHVLGHRIVSHOOLQJPHWKRGQDPHVRXWZKHQD
VKRUWFXWGRHVQ¦WFRPHUHDGLO\WRPLQG

Methods Without Parentheses and Dots


7RIDFLOLWDWHDYDULHW\RIUHDGDEOHSURJUDPPLQJVW\OHV6FDODLVIOH[LEOHDERXWWKHXVHRI
SDUHQWKHVHVLQPHWKRGV,IDPHWKRGWDNHVQRSDUDPHWHUV\RXFDQGHILQHLWZLWKRXW
SDUHQWKHVHV&DOOHUVPXVWLQYRNHWKHPHWKRGZLWKRXWSDUHQWKHVHV,I\RXDGGHPSW\
SDUHQWKHVHV WKHQ FDOOHUV PD\ RSWLRQDOO\ DGG SDUHQWKHVHV )RU H[DPSOH WKH size
PHWKRGIRUListKDVQRSDUHQWKHVHVVR\RXZULWHList(1, 2, 3).size,I\RXWU\List(1,
2, 3).size()\RX¦OOJHWDQHUURU+RZHYHUWKH lengthPHWKRGIRU java.lang.String
GRHV KDYH SDUHQWKHVHV LQ LWV GHILQLWLRQ EXW 6FDOD OHWV \RX ZULWH ERWK
"hello".length()DQG"hello".length
7KHFRQYHQWLRQLQWKH6FDODFRPPXQLW\LVWRRPLWSDUHQWKHVHVZKHQFDOOLQJDPHWKRG
WKDWKDVQRVLGHHIIHFWV6RDVNLQJIRUWKHVL]HRIDVHTXHQFHLVILQHZLWKRXWSDUHQWKHVHV
EXWGHILQLQJDPHWKRGWKDWWUDQVIRUPVWKHHOHPHQWVLQWKHVHTXHQFHVKRXOGEHZULWWHQ
ZLWKSDUHQWKHVHV7KLVFRQYHQWLRQVLJQDOVDSRWHQWLDOO\WULFN\PHWKRGIRUXVHUVRI\RXU
FRGH
,W¦VDOVRSRVVLEOHWRRPLWWKHGRW SHULRG ZKHQFDOOLQJDSDUDPHWHUOHVVPHWKRGRURQH
WKDWWDNHVRQO\RQHDUJXPHQW:LWKWKLVLQPLQGRXU List(1, 2, 3).sizeH[DPSOH
FRXOGEHZULWWHQDV
// code-examples/Rounding/no-dot-script.scala

List(1, 2, 3) size

1HDW EXW FRQIXVLQJ :KHQ GRHV WKLV V\QWDFWLFDO IOH[LELOLW\ EHFRPH XVHIXO" :KHQ
FKDLQLQJPHWKRGFDOOVWRJHWKHULQWRH[SUHVVLYHVHOIH[SODQDWRU\£VHQWHQFHV¤RIFRGH

Methods Without Parentheses and Dots | 55

Download at WoweBook.Com
// code-examples/Rounding/no-dot-better-script.scala

def isEven(n: Int) = (n % 2) == 0

List(1, 2, 3, 4) filter isEven foreach println

$V\RXPLJKWJXHVVUXQQLQJWKLVSURGXFHVWKHIROORZLQJRXWSXW
2
4

6FDOD¦VOLEHUDODSSURDFKWRSDUHQWKHVHVDQGGRWVRQPHWKRGVSURYLGHVRQHEXLOGLQJ
EORFNIRUZULWLQJ'RPDLQ6SHFLILF/DQJXDJHV:H¦OOOHDUQPRUHDERXWWKHPDIWHUDEULHI
GLVFXVVLRQRIRSHUDWRUSUHFHGHQFH

Precedence Rules
6RLIDQH[SUHVVLRQOLNH2.0 * 4.0 / 3.0 * 5.0LVDFWXDOO\DVHULHVRIPHWKRGFDOOVRQ
DoubleVZKDWDUHWKHRSHUDWRUSUHFHGHQFHUXOHV"+HUHWKH\DUHLQRUGHUIURPORZHVWWR
KLJKHVWSUHFHGHQFH VHH>6FDOD6SHF@ 
 $OOOHWWHUV
 |
 ^
 &
 < >
 = !
 :
 + -
 * / %
 $OORWKHUVSHFLDOFKDUDFWHUV
&KDUDFWHUVRQWKHVDPHOLQHKDYHWKHVDPHSUHFHGHQFH$QH[FHSWLRQLV =ZKHQXVHG
IRUDVVLJQPHQWZKHQLWKDVWKHORZHVWSUHFHGHQFH
6LQFH DQGKDYHWKHVDPHSUHFHGHQFHWKHWZROLQHVLQWKHIROORZLQJ scalaVHVVLRQ
EHKDYHWKHVDPH
scala> 2.0 * 4.0 / 3.0 * 5.0
res2: Double = 13.333333333333332

scala> (((2.0 * 4.0) / 3.0) * 5.0)


res3: Double = 13.333333333333332

,QDVHTXHQFHRIOHIWDVVRFLDWLYHPHWKRGLQYRFDWLRQVWKH\VLPSO\ELQGLQOHIWWRULJKW
RUGHU£/HIWDVVRFLDWLYH¤\RXVD\",Q6FDODDQ\PHWKRGZLWKDQDPHWKDWHQGVZLWKD
FRORQ:DFWXDOO\ELQGVWRWKHULJKWZKLOHDOORWKHUPHWKRGVELQGWRWKHOHIW)RUH[DPSOH

56 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
\RXFDQSUHSHQGDQHOHPHQWWRD ListXVLQJWKH ::PHWKRG FDOOHG£FRQV¤VKRUWIRU
£FRQVWUXFWRU¤ 
scala> val list = List('b', 'c', 'd')
list: List[Char] = List(b, c, d)

scala> 'a' :: list


res4: List[Char] = List(a, b, c, d)

7KHVHFRQGH[SUHVVLRQLVHTXLYDOHQWWR list.::(a),QDVHTXHQFHRIULJKWDVVRFLDWLYH
PHWKRGLQYRFDWLRQVWKH\ELQGIURPULJKWWROHIW:KDWDERXWDPL[WXUHRIOHIWELQGLQJ
DQGULJKWELQGLQJH[SUHVVLRQV"
scala> 'a' :: list ++ List('e', 'f')
res5: List[Char] = List(a, b, c, d, e, f)

7KH++PHWKRGDSSHQGVWZROLVWV ,QWKLVFDVHlistLVDGGHGWRWKHList(e, f)WKHQ


aLVSUHSHQGHGWRFUHDWHWKHILQDOOLVW,W¦VXVXDOO\EHWWHUWRDGGSDUHQWKHVHVWRUHPRYH
DQ\SRWHQWLDOXQFHUWDLQW\

$Q\PHWKRGZKRVHQDPHHQGVZLWKD:ELQGVWRWKHULJKWQRWWKHOHIW

)LQDOO\QRWHWKDWZKHQ\RXXVHWKHscalaFRPPDQGHLWKHULQWHUDFWLYHO\RUZLWKVFULSWV
LWPD\DSSHDUWKDW\RXFDQGHILQH£JOREDO¤YDULDEOHVDQGPHWKRGVRXWVLGHRIW\SHV7KLV
LVDFWXDOO\DQLOOXVLRQWKHLQWHUSUHWHUZUDSVDOOGHILQLWLRQVLQDQDQRQ\PRXVW\SHEHIRUH
JHQHUDWLQJ-90RU1(7&/5E\WHFRGH

Domain-Specific Languages
'RPDLQ6SHFLILF/DQJXDJHVRU'6/VSURYLGHDFRQYHQLHQWV\QWDFWLFDOPHDQVIRUH[
SUHVVLQJJRDOVLQDJLYHQSUREOHPGRPDLQ)RUH[DPSOH64/SURYLGHVMXVWHQRXJKRI
DSURJUDPPLQJODQJXDJHWRKDQGOHWKHSUREOHPVRIZRUNLQJZLWKGDWDEDVHVPDNLQJ
LWD'RPDLQ6SHFLILF/DQJXDJH
:KLOHVRPH'6/VOLNH64/DUHVHOIFRQWDLQHGLW¦VEHFRPHSRSXODUWRLPSOHPHQW'6/V
DVVXEVHWVRIIXOOIOHGJHGSURJUDPPLQJODQJXDJHV7KLVDOORZVSURJUDPPHUVWROHYHUDJH
WKHHQWLUHW\RIWKHKRVWODQJXDJHIRUHGJHFDVHVWKDWWKH'6/GRHVQRWFRYHUDQGVDYHV
WKHZRUNRIZULWLQJOH[HUVSDUVHUVDQGWKHRWKHUEXLOGLQJEORFNVRIDODQJXDJH
6FDOD¦VULFKIOH[LEOHV\QWD[PDNHVZULWLQJ'6/VDEUHH]H&RQVLGHUWKLVH[DPSOHRID
VW\OHRIWHVWZULWLQJFDOOHG%HKDYLRU'ULYHQ'HYHORSPHQW VHH>%''@ XVLQJWKH6SHFV
OLEUDU\ VHH£6SHFV¤RQSDJH 
// code-examples/Rounding/specs-script.scala

"nerd finder" should {

Domain-Specific Languages | 57

Download at WoweBook.Com
"identify nerds from a List" in {
val actors = List("Rick Moranis", "James Dean", "Woody Allen")
val finder = new NerdFinder(actors)
finder.findNerds mustEqual List("Rick Moranis", "Woody Allen")
}
}

1RWLFHKRZPXFKWKLVFRGHUHDGVOLNH(QJOLVK£7KLVVKRXOGWHVWWKDWLQWKHIROORZLQJ
VFHQDULR¤ £7KLV YDOXH PXVW HTXDO WKDW YDOXH¤ DQG VR IRUWK 7KLV H[DPSOH XVHV WKH
VXSHUE6SHFVOLEUDU\ZKLFKHIIHFWLYHO\SURYLGHVD'6/IRUWKH%HKDYLRU'ULYHQ'HYHO
RSPHQWWHVWLQJDQGHQJLQHHULQJPHWKRGRORJ\%\PDNLQJPD[LPXPXVHRI6FDOD¦VOLE
HUDOV\QWD[DQGULFKPHWKRGV6SHFVWHVWVXLWHVDUHUHDGDEOHHYHQE\QRQGHYHORSHUV
7KLVLVMXVWDWDVWHRIWKHSRZHURI'6/VLQ6FDOD:H¦OOVHHRWKHUH[DPSOHVODWHUDQG
OHDUQKRZWRZULWHRXURZQDVZHJHWPRUHDGYDQFHG VHH&KDSWHU 

Scala if Statements
(YHQWKHPRVWIDPLOLDUODQJXDJHIHDWXUHVDUHVXSHUFKDUJHGLQ6FDOD/HW¦VKDYHDORRN
DWWKHORZO\ifVWDWHPHQW$VLQPRVWHYHU\ODQJXDJH6FDOD¦VifHYDOXDWHVDFRQGLWLRQDO
H[SUHVVLRQWKHQSURFHHGVWRDEORFNLIWKHUHVXOWLV trueRUEUDQFKHVWRDQDOWHUQDWH
EORFNLIWKHUHVXOWLVfalse$VLPSOHH[DPSOH
// code-examples/Rounding/if-script.scala

if (2 + 2 == 5) {
println("Hello from 1984.")
} else if (2 + 2 == 3) {
println("Hello from Remedial Math class?")
} else {
println("Hello from a non-Orwellian future.")
}

:KDW¦VGLIIHUHQWLQ6FDODLVWKDWifDQGDOPRVWDOORWKHUVWDWHPHQWVDUHDFWXDOO\H[SUHV
VLRQVWKHPVHOYHV6RZHFDQDVVLJQWKHUHVXOWRIDQifH[SUHVVLRQDVVKRZQKHUH
// code-examples/Rounding/assigned-if-script.scala

val configFile = new java.io.File("~/.myapprc")

val configFilePath = if (configFile.exists()) {


configFile.getAbsolutePath()
} else {
configFile.createNewFile()
configFile.getAbsolutePath()
}

1RWHWKDW ifVWDWHPHQWVDUHH[SUHVVLRQVPHDQLQJWKH\KDYHYDOXHV,QWKLVH[DPSOH
WKHYDOXH configFilePathLVWKHUHVXOWRIDQ ifH[SUHVVLRQWKDWKDQGOHVWKHFDVHRID
FRQILJXUDWLRQILOHQRWH[LVWLQJLQWHUQDOO\WKHQUHWXUQVWKHDEVROXWHSDWKWRWKDWILOH7KLV
YDOXHFDQQRZEHUHXVHGWKURXJKRXWDQDSSOLFDWLRQDQGWKH ifH[SUHVVLRQZRQ¦WEH
UHHYDOXDWHGZKHQWKHYDOXHLVXVHG

58 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
%HFDXVH ifVWDWHPHQWVDUHH[SUHVVLRQVLQ6FDODWKHUHLVQRQHHGIRUWKHVSHFLDOFDVH
WHUQDU\FRQGLWLRQDOH[SUHVVLRQVWKDWH[LVWLQ&GHULYHGODQJXDJHV<RXZRQ¦WVHH x ?
doThis() : doThat()LQ6FDOD6FDODSURYLGHVDPHFKDQLVPWKDW¦VMXVWDVSRZHUIXODQG
PRUHUHDGDEOH
:KDW LI ZH RPLW WKH else FODXVH LQ WKH SUHYLRXV H[DPSOH" 7\SLQJ WKH FRGH LQ WKH
scalaLQWHUSUHWHUZLOOWHOOXVZKDWKDSSHQV
scala> val configFile = new java.io.File("~/.myapprc")
configFile: java.io.File = ~/.myapprc

scala> val configFilePath = if (configFile.exists()) {


| configFile.getAbsolutePath()
| }
configFilePath: Unit = ()

scala>

1RWHWKDWconfigFilePathLVQRZUnit ,WZDVStringEHIRUH 7KHW\SHLQIHUHQFHSLFNV


DW\SHWKDWZRUNVIRUDOORXWFRPHVRIWKHifH[SUHVVLRQUnitLVWKHRQO\SRVVLELOLW\VLQFH
QRYDOXHLVRQHSRVVLEOHRXWFRPH

Scala for Comprehensions


$QRWKHU IDPLOLDU FRQWURO VWUXFWXUH WKDW¦V SDUWLFXODUO\ IHDWXUHULFK LQ 6FDOD LV WKH for
ORRSUHIHUUHGWRLQWKH6FDODFRPPXQLW\DVDforFRPSUHKHQVLRQRUforH[SUHVVLRQ7KLV
FRUQHURIWKHODQJXDJHGHVHUYHVDWOHDVWRQHIDQF\QDPHEHFDXVHLWFDQGRVRPHJUHDW
SDUW\WULFNV
$FWXDOO\WKHWHUPcomprehensionFRPHVIURPIXQFWLRQDOSURJUDPPLQJ,WH[SUHVVHVWKH
LGHDWKDWZHDUHWUDYHUVLQJDVHWRIVRPHNLQG£FRPSUHKHQGLQJ¤ZKDWZHILQGDQG
FRPSXWLQJVRPHWKLQJQHZIURPLW

A Dog-Simple Example
/HW¦VVWDUWZLWKDEDVLFforH[SUHVVLRQ
// code-examples/Rounding/basic-for-script.scala

val dogBreeds = List("Doberman", "Yorkshire Terrier", "Dachshund",


"Scottish Terrier", "Great Dane", "Portuguese Water Dog")

for (breed <- dogBreeds)


println(breed)

$V\RXPLJKWJXHVVWKLVFRGHVD\V£)RUHYHU\HOHPHQWLQWKHOLVW dogBreedsFUHDWHD
WHPSRUDU\YDULDEOHFDOOHGbreedZLWKWKHYDOXHRIWKDWHOHPHQWWKHQSULQWLW¤7KLQNRI
WKH<-RSHUDWRUDVDQDUURZGLUHFWLQJHOHPHQWVRIDFROOHFWLRQRQHE\RQHWRWKHVFRSHG
YDULDEOHE\ZKLFKZH¦OOUHIHUWRWKHPLQVLGHWKHforH[SUHVVLRQ7KHOHIWDUURZRSHUDWRU

Scala for Comprehensions | 59

Download at WoweBook.Com
LVFDOOHGDJHQHUDWRUVRQDPHGEHFDXVHLW¦VJHQHUDWLQJLQGLYLGXDOYDOXHVIURPDFROOHF
WLRQIRUXVHLQDQH[SUHVVLRQ

Filtering
:KDWLIZHZDQWWRJHWPRUHJUDQXODU"6FDOD¦VforH[SUHVVLRQVDOORZIRUILOWHUVWKDWOHW
XVVSHFLI\ZKLFKHOHPHQWVRIDFROOHFWLRQZHZDQWWRZRUNZLWK6RWRILQGDOOWHUULHUV
LQRXUOLVWRIGRJEUHHGVZHFRXOGPRGLI\WKHSUHYLRXVH[DPSOHWRWKHIROORZLQJ
// code-examples/Rounding/filtered-for-script.scala

for (breed <- dogBreeds


if breed.contains("Terrier")
) println(breed)

7RDGGPRUHWKDQRQHILOWHUWRDforH[SUHVVLRQVHSDUDWHWKHILOWHUVZLWKVHPLFRORQV
// code-examples/Rounding/double-filtered-for-script.scala

for (breed <- dogBreeds


if breed.contains("Terrier");
if !breed.startsWith("Yorkshire")
) println(breed)

<RX¦YHQRZIRXQGDOOWKHWHUULHUVWKDWGRQ¦WKDLOIURP<RUNVKLUHDQGKRSHIXOO\OHDUQHG
MXVWKRZXVHIXOILOWHUVFDQEHLQWKHSURFHVV

Yielding
:KDW LI UDWKHU WKDQ SULQWLQJ \RXU ILOWHUHG FROOHFWLRQ \RX QHHGHG WR KDQG LW RII WR
DQRWKHUSDUWRI\RXUSURJUDP"7KH yieldNH\ZRUGLV\RXUWLFNHWWRJHQHUDWLQJQHZ
FROOHFWLRQVZLWK forH[SUHVVLRQV,QWKHIROORZLQJH[DPSOHQRWHWKDWZH¦UHZUDSSLQJ
XSWKHforH[SUHVVLRQLQFXUO\EUDFHVDVZHZRXOGZKHQGHILQLQJDQ\EORFN
// code-examples/Rounding/yielding-for-script.scala

val filteredBreeds = for {


breed <- dogBreeds
if breed.contains("Terrier")
if !breed.startsWith("Yorkshire")
} yield breed

forH[SUHVVLRQVPD\EHGHILQHGZLWKSDUHQWKHVHVRUFXUO\EUDFHVEXW
XVLQJFXUO\EUDFHVPHDQV\RXGRQ¦WKDYHWRVHSDUDWH\RXUILOWHUVZLWK
VHPLFRORQV0RVWRIWKHWLPH\RX¦OOSUHIHUXVLQJFXUO\EUDFHVZKHQ\RX
KDYHPRUHWKDQRQHILOWHUDVVLJQPHQWHWF

(YHU\WLPHWKURXJKWKH forH[SUHVVLRQWKHILOWHUHGUHVXOWLV\LHOGHGDVDYDOXHQDPHG
breed7KHVHUHVXOWVDFFXPXODWHZLWKHYHU\UXQDQGWKHUHVXOWLQJFROOHFWLRQLVDVVLJQHG
WR WKH YDOXH filteredBreeds DV ZH GLG ZLWK if VWDWHPHQWV HDUOLHU  7KH W\SH RI WKH

60 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
FROOHFWLRQUHVXOWLQJIURPDfor-yieldH[SUHVVLRQLVLQIHUUHGIURPWKHW\SHRIWKHFROOHF
WLRQEHLQJLWHUDWHGRYHU,QWKLVFDVHfilteredBreedsLVRIW\SHList[String]VLQFHLWLV
DVXEVHWRIWKHdogBreedsOLVWZKLFKLVDOVRRIW\SHList[String]

Expanded Scope
2QHILQDOXVHIXOIHDWXUHRI6FDOD¦VforFRPSUHKHQVLRQVLVWKHDELOLW\WRGHILQHYDULDEOHV
LQVLGHWKHILUVWSDUWRI\RXUforH[SUHVVLRQVWKDWFDQEHXVHGLQWKHODWWHUSDUW7KLVLV
EHVWLOOXVWUDWHGZLWKDQH[DPSOH
// code-examples/Rounding/scoped-for-script.scala

for {
breed <- dogBreeds
upcasedBreed = breed.toUpperCase()
} println(upcasedBreed)

1RWHWKDWZLWKRXWGHFODULQJupcasedBreedDVDval\RXFDQUHXVHLWZLWKLQWKHERG\RI
\RXU forH[SUHVVLRQ7KLVDSSURDFKLVLGHDOIRUWUDQVIRUPLQJHOHPHQWVLQDFROOHFWLRQ
DV\RXORRSWKURXJKWKHP
)LQDOO\ LQ £2SWLRQV DQG IRU &RPSUHKHQVLRQV¤ RQ SDJH  ZH¦OO VHH KRZ XVLQJ
OptionsZLWK forFRPSUHKHQVLRQVFDQJUHDWO\UHGXFHFRGHVL]HE\HOLPLQDWLQJXQQHF
HVVDU\£QXOO¤DQG£PLVVLQJ¤FKHFNV

Other Looping Constructs


6FDODSURYLGHVVHYHUDORWKHUORRSLQJFRQVWUXFWV

Scala while Loops


)DPLOLDULQPDQ\ODQJXDJHVWKHwhileORRSH[HFXWHVDEORFNRIFRGHDVORQJDVDFRQ
GLWLRQLVWUXH)RUH[DPSOHWKHIROORZLQJFRGHSULQWVRXWDFRPSODLQWRQFHDGD\XQWLO
WKHQH[W)ULGD\WKHWKKDVDUULYHG
// code-examples/Rounding/while-script.scala
// WARNING: This script runs for a LOOOONG time!

import java.util.Calendar

def isFridayThirteen(cal: Calendar): Boolean = {


val dayOfWeek = cal.get(Calendar.DAY_OF_WEEK)
val dayOfMonth = cal.get(Calendar.DAY_OF_MONTH)

// Scala returns the result of the last expression in a method


(dayOfWeek == Calendar.FRIDAY) && (dayOfMonth == 13)
}

while (!isFridayThirteen(Calendar.getInstance())) {
println("Today isn't Friday the 13th. Lame.")

Other Looping Constructs | 61

Download at WoweBook.Com
// sleep for a day
Thread.sleep(86400000)
}

7DEOHODWHULQWKLVFKDSWHUVKRZVWKHFRQGLWLRQDORSHUDWRUVWKDWZRUNLQwhileORRSV

Scala do-while Loops


/LNHWKHwhileORRSDdo-whileORRSH[HFXWHVVRPHFRGHZKLOHDFRQGLWLRQDOH[SUHVVLRQ
LVWUXH7KHRQO\GLIIHUHQFHWKDWD do-whileFKHFNVWRVHHLIWKHFRQGLWLRQLVWUXHDIWHU
UXQQLQJWKHEORFN7RFRXQWXSWRZHFRXOGZULWHWKLV
// code-examples/Rounding/do-while-script.scala

var count = 0

do {
count += 1
println(count)
} while (count < 10)

$VLWWXUQVRXWWKHUH¦VDPRUHHOHJDQWZD\WRORRSWKURXJKFROOHFWLRQVLQ6FDODDVZH¦OO
VHHLQWKHQH[WVHFWLRQ

Generator Expressions
5HPHPEHUWKHDUURZRSHUDWRU <- IURPWKHGLVFXVVLRQDERXW forORRSV":HFDQSXW
LWWRZRUNKHUHWRR/HW¦VFOHDQXSWKHdo-whileH[DPSOHMXVWVKRZQ
// code-examples/Rounding/generator-script.scala

for (i <- 1 to 10) println(i)

<XS WKDW¦V DOO WKDW¦V QHFHVVDU\ 7KLV FOHDQ RQHOLQHU LV SRVVLEOH EHFDXVH RI 6FDOD¦V
RichIntFODVV$QLPSOLFLWFRQYHUVLRQLVLQYRNHGE\WKHFRPSLOHUWRFRQYHUWWKH 1DQ
Int LQWR D RichInt :H¦OO GLVFXVV WKHVH FRQYHUVLRQV LQ £7KH 6FDOD 7\SH +LHUDU
FK\¤RQSDJHDQGLQ£,PSOLFLW&RQYHUVLRQV¤RQSDJH  RichIntGHILQHVD to
PHWKRGWKDWWDNHVDQRWKHULQWHJHUDQGUHWXUQVDQLQVWDQFHRIRange.Inclusive7KDWLV
Inclusive LV D QHVWHG FODVV LQ WKH Range FRPSDQLRQ REMHFW D FRQFHSW ZH LQWURGXFHG
EULHIO\LQ&KDSWHUVHH&KDSWHUIRUGHWDLOV 7KLVVXEFODVVRIWKHFODVVRangeLQKHULWV
DQXPEHURIPHWKRGVIRUZRUNLQJZLWKVHTXHQFHVDQGLWHUDEOHGDWDVWUXFWXUHVLQFOXGLQJ
WKRVHQHFHVVDU\WRXVHLWLQDforORRS
%\WKHZD\LI\RXZDQWHGWRFRXQWIURPXSWREXWQRWLQFOXGLQJ\RXFRXOGXVH
untilLQVWHDGRIto)RUH[DPSOHfor (i <- 0 until 10)
7KLVVKRXOGSDLQWDFOHDUHUSLFWXUHRIKRZ6FDOD¦VLQWHUQDOOLEUDULHVFRPSRVHWRIRUP
HDV\WRXVHODQJXDJHFRQVWUXFWV

62 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
:KHQZRUNLQJZLWKORRSVLQPRVWODQJXDJHV\RXFDQ breakRXWRID
ORRSRUcontinueWKHLWHUDWLRQV6FDODGRHVQ¦WKDYHHLWKHURIWKHVHVWDWH
PHQWVEXWZKHQZULWLQJLGLRPDWLF6FDODFRGHWKH\¦UHQRWQHFHVVDU\
8VHFRQGLWLRQDOH[SUHVVLRQVWRWHVWLIDORRSVKRXOGFRQWLQXHRUPDNH
XVHRIUHFXUVLRQ%HWWHU\HWILOWHU\RXUFROOHFWLRQVDKHDGRIWLPHWRHOLP
LQDWHFRPSOH[FRQGLWLRQVZLWKLQ\RXUORRSV+RZHYHUEHFDXVHRIGH
PDQGIRULW6FDODYHUVLRQLQFOXGHVVXSSRUWIRUbreakLPSOHPHQWHG
DVDOLEUDU\PHWKRGUDWKHUWKDQDEXLOWLQbreakNH\ZRUG

Conditional Operators
6FDODERUURZVPRVWRIWKHFRQGLWLRQDORSHUDWRUVIURP-DYDDQGLWVSUHGHFHVVRUV<RX¦OO
ILQGWKHRQHVOLVWHGLQ7DEOHLQ ifVWDWHPHQWV whileORRSVDQGHYHU\ZKHUHHOVH
FRQGLWLRQVDSSO\
7DEOH&RQGLWLRQDORSHUDWRUV
Operator Operation Description
&& and The values on the left and right of the operator are true. The righthand side is only evaluated
if the lefthand side is true.
|| or At least one of the values on the left or right is true. The righthand side is only evaluated if the
lefthand side is false.
> greater than The value on the left is greater than the value on the right.
>= greater than or The value on the left is greater than or equal to the value on the right.
equals
< less than The value on the left is less than the value on the right.
<= less than or The value on the left is less than or equal to the value on the right.
equals
== equals The value on the left is the same as the value on the right.
!= not equal The value on the left is not the same as the value on the right.

1RWHWKDW&&DQG||DUH£VKRUWFLUFXLWLQJ¤RSHUDWRUV7KH\VWRSHYDOXDWLQJH[SUHVVLRQV
DVVRRQDVWKHDQVZHULVNQRZQ
:H¦OOGLVFXVVREMHFWHTXDOLW\LQPRUHGHWDLOLQ£(TXDOLW\RI2EMHFWV¤RQSDJH)RU
H[DPSOHZH¦OOVHHWKDW==KDVDGLIIHUHQWPHDQLQJLQ6FDODYHUVXV-DYD2WKHUZLVHWKHVH
RSHUDWRUVVKRXOGDOOEHIDPLOLDUVROHW¦VPRYHRQWRVRPHWKLQJQHZDQGH[FLWLQJ

Pattern Matching
$QLGHDERUURZHGIURPIXQFWLRQDOODQJXDJHVSDWWHUQPDWFKLQJLVDSRZHUIXO\HWFRQFLVH
ZD\WRPDNHDSURJUDPPDWLFFKRLFHEHWZHHQPXOWLSOHFRQGLWLRQV3DWWHUQPDWFKLQJLV
WKHIDPLOLDUcaseVWDWHPHQWIURP\RXUIDYRULWH&OLNHODQJXDJHEXWRQVWHURLGV,QWKH

Pattern Matching | 63

Download at WoweBook.Com
W\SLFDOcaseVWDWHPHQW\RX¦UHOLPLWHGWRPDWFKLQJDJDLQVWYDOXHVRIRUGLQDOW\SHV\LHOG
LQJWULYLDOH[SUHVVLRQVOLNHWKLV£,QWKHFDVHWKDWiLVSULQWDPHVVDJHLQWKHFDVHWKDW
iLVH[LWWKHSURJUDP¤:LWK6FDOD¦VSDWWHUQPDWFKLQJ\RXUFDVHVFDQLQFOXGHW\SHV
ZLOGFDUGVVHTXHQFHVUHJXODUH[SUHVVLRQVDQGHYHQGHHSLQVSHFWLRQVRIDQREMHFW¦V
YDULDEOHV

A Simple Match
7REHJLQZLWKOHW¦VVLPXODWHIOLSSLQJDFRLQE\PDWFKLQJWKHYDOXHRIDERROHDQ
// code-examples/Rounding/match-boolean-script.scala

val bools = List(true, false)

for (bool <- bools) {


bool match {
case true => println("heads")
case false => println("tails")
case _ => println("something other than heads or tails (yikes!)")
}
}

,WORRNVMXVWOLNHD&VW\OHcaseVWDWHPHQWULJKW"7KHRQO\GLIIHUHQFHLVWKHODVWcaseZLWK
WKHXQGHUVFRUH _ ZLOGFDUG,WPDWFKHVDQ\WKLQJQRWGHILQHGLQWKHFDVHVDERYHLWVR
LWVHUYHVWKHVDPHSXUSRVHDVWKHdefaultNH\ZRUGLQ-DYDDQG&switchVWDWHPHQWV
3DWWHUQPDWFKLQJLVHDJHUWKHILUVWPDWFKZLQV6RLI\RXWU\WRSXWD case _FODXVH
EHIRUHDQ\RWKHUcaseFODXVHVWKHFRPSLOHUZLOOWKURZDQ£XQUHDFKDEOHFRGH¤HUURURQ
WKHQH[WFODXVHEHFDXVHQRWKLQJZLOOJHWSDVWWKHGHIDXOWFODXVH

8VHcase _IRUWKHGHIDXOW£FDWFKDOO¤PDWFK

:KDWLIZHZDQWWRZRUNZLWKPDWFKHVDVYDULDEOHV"

Variables in Matches
,Q WKH IROORZLQJ H[DPSOH ZH DVVLJQ WKH ZLOGFDUG FDVH WR D YDULDEOH FDOOHG other
NumberWKHQSULQWLWLQWKHVXEVHTXHQWH[SUHVVLRQ,IZHJHQHUDWHDZH¦OOH[WROWKDW
QXPEHU¦VYLUWXHV2WKHUZLVHZH¦OOFXUVHIDWHIRUPDNLQJXVVXIIHUDQXQOXFN\QXPEHU
// code-examples/Rounding/match-variable-script.scala

import scala.util.Random

val randomInt = new Random().nextInt(10)

randomInt match {

64 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
case 7 => println("lucky seven!")
case otherNumber => println("boo, got boring ol' " + otherNumber)
}

Matching on Type
7KHVHVLPSOHH[DPSOHVGRQ¦WHYHQEHJLQWRVFUDWFKWKHVXUIDFHRI6FDOD¦VSDWWHUQPDWFK
LQJIHDWXUHV/HW¦VWU\PDWFKLQJEDVHGRQW\SH
// code-examples/Rounding/match-type-script.scala

val sundries = List(23, "Hello", 8.5, 'q')

for (sundry <- sundries) {


sundry match {
case i: Int => println("got an Integer: " + i)
case s: String => println("got a String: " + s)
case f: Double => println("got a Double: " + f)
case other => println("got something else: " + other)
}
}

+HUHZHSXOOHDFKHOHPHQWRXWRIDListRIAnyW\SHRIHOHPHQWLQWKLVFDVHFRQWDLQLQJ
DStringDDoubleDQIntDQGDChar)RUWKHILUVWWKUHHRIWKRVHW\SHVZHOHWWKHXVHU
NQRZVSHFLILFDOO\ZKLFKW\SHZHJRWDQGZKDWWKHYDOXHZDV:KHQZHJHWVRPHWKLQJ
HOVH WKHChar ZHMXVWOHWWKHXVHUNQRZWKHYDOXH:HFRXOGDGGIXUWKHUHOHPHQWVWR
WKHOLVWRIRWKHUW\SHVDQGWKH\¦GEHFDXJKWE\WKHotherZLOGFDUGFDVH

Matching on Sequences
6LQFHZRUNLQJLQ6FDODRIWHQPHDQVZRUNLQJZLWKVHTXHQFHVZRXOGQ¦WLWEHKDQG\WR
EHDEOHWRPDWFKDJDLQVWWKHOHQJWKDQGFRQWHQWVRIOLVWVDQGDUUD\V"7KHIROORZLQJ
H[DPSOHGRHVMXVWWKDWWHVWLQJWZROLVWVWRVHHLIWKH\FRQWDLQIRXUHOHPHQWVWKHVHFRQG
RIZKLFKLVWKHLQWHJHU3
// code-examples/Rounding/match-seq-script.scala

val willWork = List(1, 3, 23, 90)


val willNotWork = List(4, 18, 52)
val empty = List()

for (l <- List(willWork, willNotWork, empty)) {


l match {
case List(_, 3, _, _) => println("Four elements, with the 2nd being '3'.")
case List(_*) => println("Any other list with 0 or more elements.")
}
}

,QWKHVHFRQG caseZH¦YHXVHGDVSHFLDOZLOGFDUGSDWWHUQWRPDWFKD ListRIDQ\VL]H


HYHQ]HURHOHPHQWVDQGDQ\HOHPHQWYDOXHV<RXFDQXVHWKLVSDWWHUQDWWKHHQGRIDQ\
VHTXHQFHPDWFKWRUHPRYHOHQJWKDVDFRQGLWLRQ

Pattern Matching | 65

Download at WoweBook.Com
5HFDOOWKDWZHPHQWLRQHGWKH£FRQV¤PHWKRGIRU List ::7KHH[SUHVVLRQ a :: list
SUHSHQGVaWRDOLVW<RXFDQDOVRXVHWKLVRSHUDWRUWRH[WUDFWWKHKHDGDQGWDLORIDOLVW
// code-examples/Rounding/match-list-script.scala

val willWork = List(1, 3, 23, 90)


val willNotWork = List(4, 18, 52)
val empty = List()

def processList(l: List[Any]): Unit = l match {


case head :: tail =>
format("%s ", head)
processList(tail)
case Nil => println("")
}

for (l <- List(willWork, willNotWork, empty)) {


print("List: ")
processList(l)
}

7KHprocessListPHWKRGPDWFKHVRQWKHListDUJXPHQWO,WPD\ORRNVWUDQJHWRVWDUW
WKHPHWKRGGHILQLWLRQOLNHWKHIROORZLQJ
def processList(l: List[Any]): Unit = l match {
...
}

+RSHIXOO\KLGLQJWKHGHWDLOVZLWKWKHHOOLSVLVPDNHVWKHPHDQLQJDOLWWOHFOHDUHU7KH
processListPHWKRGLVDFWXDOO\RQHVWDWHPHQWWKDWFURVVHVVHYHUDOOLQHV
,WILUVWPDWFKHVRQ head :: tailZKHUH headZLOOEHDVVLJQHGWKHILUVWHOHPHQWLQWKH
OLVWDQGtailZLOOEHDVVLJQHGWKHUHVWRIWKHOLVW7KDWLVZH¦UHH[WUDFWLQJWKHKHDGDQG
WDLOIURPWKHOLVWXVLQJ:::KHQWKLVFDVHPDWFKHVLWSULQWVWKHheadDQGFDOOVprocess
ListUHFXUVLYHO\WRSURFHVVWKHWDLO
7KHVHFRQGFDVHPDWFKHVWKHHPSW\OLVWNil,WSULQWVDQHQGRIOLQHDQGWHUPLQDWHVWKH
UHFXUVLRQ

Matching on Tuples (and Guards)


$OWHUQDWHO\LIZHMXVWZDQWHGWRWHVWWKDWZHKDYHDWXSOHRIWZRLWHPVZHFRXOGGRD
WXSOHPDWFK
// code-examples/Rounding/match-tuple-script.scala

val tupA = ("Good", "Morning!")


val tupB = ("Guten", "Tag!")

for (tup <- List(tupA, tupB)) {


tup match {
case (thingOne, thingTwo) if thingOne == "Good" =>
println("A two-tuple starting with 'Good'.")
case (thingOne, thingTwo) =>

66 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
println("This has two things: " + thingOne + " and " + thingTwo)
}
}

,QWKHVHFRQGcaseLQWKLVH[DPSOHZH¦YHH[WUDFWHGWKHYDOXHVLQVLGHWKHWXSOHWRVFRSHG
YDULDEOHVWKHQUHXVHGWKHVHYDULDEOHVLQWKHUHVXOWLQJH[SUHVVLRQ
,QWKHILUVWFDVHZH¦YHDGGHGDQHZFRQFHSWJXDUGV7KHifFRQGLWLRQDIWHUWKHWXSOHLV
DJXDUG7KHJXDUGLVHYDOXDWHGZKHQPDWFKLQJEXWRQO\H[WUDFWLQJDQ\YDULDEOHVLQ
WKHSUHFHGLQJSDUWRIWKHFDVH*XDUGVSURYLGHDGGLWLRQDOJUDQXODULW\ZKHQFRQVWUXFWLQJ
FDVHV,QWKLVH[DPSOHWKHRQO\GLIIHUHQFHEHWZHHQWKHWZRSDWWHUQVLVWKHJXDUGH[
SUHVVLRQEXWWKDW¦VHQRXJKIRUWKHFRPSLOHUWRGLIIHUHQWLDWHWKHP

5HFDOOWKDWWKHFDVHVLQDSDWWHUQPDWFKDUHHYDOXDWHGLQRUGHU)RUH[
DPSOHLI\RXUILUVWFDVHLVEURDGHUWKDQ\RXUVHFRQGFDVHWKHVHFRQG
FDVH ZLOO QHYHU EH UHDFKHG 8QUHDFKDEOH FDVHV ZLOO FDXVH D FRPSLOHU
HUURU <RXPD\LQFOXGHD£GHIDXOW¤FDVHDWWKHHQGRIDSDWWHUQPDWFK
HLWKHUXVLQJWKHXQGHUVFRUHZLOGFDUGFKDUDFWHURUDPHDQLQJIXOO\QDPHG
YDULDEOH:KHQXVLQJDYDULDEOHLWVKRXOGKDYHQRH[SOLFLWW\SHRULW
VKRXOGEHGHFODUHGDVAnyVRLWFDQPDWFKDQ\WKLQJ2QWKHRWKHUKDQG
WU\WRGHVLJQ\RXUFRGHWRDYRLGDFDWFKDOOFODXVHE\HQVXULQJLWRQO\
UHFHLYHVVSHFLILFLWHPVWKDWDUHH[SHFWHG

Matching on Case Classes


/HW¦VWU\DGHHSPDWFKH[DPLQLQJWKHFRQWHQWVRIREMHFWVLQRXUSDWWHUQPDWFK
// code-examples/Rounding/match-deep-script.scala

case class Person(name: String, age: Int)

val alice = new Person("Alice", 25)


val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)

for (person <- List(alice, bob, charlie)) {


person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Who are you, " + age + " year-old person named " + name + "?")
}
}

3RRU&KDUOLHJHWVWKHFROGVKRXOGHUDVZHFDQVHHLQWKHRXWSXW
Hi Alice!
Hi Bob!
Who are you, 32 year-old person named Charlie?

Pattern Matching | 67

Download at WoweBook.Com
:HILUVWGHILQHDFDVHFODVVDVSHFLDOW\SHRIFODVVWKDWZH¦OOOHDUQPRUHDERXWLQ£&DVH
&ODVVHV¤RQSDJH)RUQRZLWZLOOVXIILFHWRVD\WKDWDFDVHFODVVDOORZVIRUYHU\
WHUVHFRQVWUXFWLRQRIVLPSOHREMHFWVZLWKVRPHSUHGHILQHGPHWKRGV2XUSDWWHUQPDWFK
WKHQORRNVIRU$OLFHDQG%REE\LQVSHFWLQJWKHYDOXHVSDVVHGWRWKHFRQVWUXFWRURIWKH
PersonFDVHFODVV&KDUOLHIDOOVWKURXJKWRWKHFDWFKDOOFDVHHYHQWKRXJKKHKDVWKH
VDPHageYDOXHDV%REZH¦UHPDWFKLQJRQWKHnameSURSHUW\DVZHOO
7KLVW\SHRISDWWHUQPDWFKEHFRPHVH[WUHPHO\XVHIXOZKHQZRUNLQJZLWK$FWRUVDV
ZH¦OO VHH ODWHU RQ &DVH FODVVHV DUH IUHTXHQWO\ VHQW WR $FWRUV DV PHVVDJHV DQG GHHS
SDWWHUQPDWFKLQJRQDQREMHFW¦VFRQWHQWVLVDFRQYHQLHQWZD\WR£SDUVH¤WKRVHPHVVDJHV

Matching on Regular Expressions


5HJXODUH[SUHVVLRQVDUHFRQYHQLHQWIRUH[WUDFWLQJGDWDIURPVWULQJVWKDWKDYHDQLQIRU
PDOVWUXFWXUHEXWDUHQRW£VWUXFWXUHGGDWD¤ WKDWLVLQDIRUPDWOLNH;0/RU-621IRU
H[DPSOH &RPPRQO\UHIHUUHGWRDVUHJH[HVUHJXODUH[SUHVVLRQVDUHDIHDWXUHRIQHDUO\
DOOPRGHUQSURJUDPPLQJODQJXDJHV7KH\SURYLGHDWHUVHV\QWD[IRUVSHFLI\LQJFRPSOH[
PDWFKHV RQH WKDW LV W\SLFDOO\ WUDQVODWHG LQWR D VWDWH PDFKLQH EHKLQG WKH VFHQHV IRU
RSWLPXPSHUIRUPDQFH
5HJH[HVLQ6FDODVKRXOGFRQWDLQQRVXUSULVHVLI\RX¦YHXVHGWKHPLQRWKHUSURJUDPPLQJ
ODQJXDJHV/HW¦VVHHDQH[DPSOH
// code-examples/Rounding/match-regex-script.scala

val BookExtractorRE = """Book: title=([^,]+),\s+authors=(.+)""".r


val MagazineExtractorRE = """Magazine: title=([^,]+),\s+issue=(.+)""".r

val catalog = List(


"Book: title=Programming Scala, authors=Dean Wampler, Alex Payne",
"Magazine: title=The New Yorker, issue=January 2009",
"Book: title=War and Peace, authors=Leo Tolstoy",
"Magazine: title=The Atlantic, issue=February 2009",
"BadData: text=Who put this here??"
)

for (item <- catalog) {


item match {
case BookExtractorRE(title, authors) =>
println("Book \"" + title + "\", written by " + authors)
case MagazineExtractorRE(title, issue) =>
println("Magazine \"" + title + "\", issue " + issue)
case entry => println("Unrecognized entry: " + entry)
}
}

:HVWDUWZLWKWZRUHJXODUH[SUHVVLRQVRQHIRUUHFRUGVRIERRNVDQGDQRWKHUIRUUHFRUGV
RIPDJD]LQHV&DOOLQJ.rRQDVWULQJWXUQVLWLQWRDUHJXODUH[SUHVVLRQZHXVHUDZ WULSOH
TXRWHG VWULQJVKHUHWRDYRLGKDYLQJWRGRXEOHHVFDSHEDFNVODVKHV6KRXOG\RXILQG

68 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
WKH.rWUDQVIRUPDWLRQPHWKRGRQVWULQJVXQFOHDU\RXFDQDOVRGHILQHUHJH[HVE\FUHDWLQJ
QHZLQVWDQFHVRIWKHRegexFODVVDVLQnew Regex("""\W""")
1RWLFHWKDWHDFKRIRXUUHJH[HVGHILQHVWZRFDSWXUHJURXSVFRQQRWHGE\SDUHQWKHVHV
(DFKJURXSFDSWXUHVWKHYDOXHRIDVLQJOHILHOGLQWKHUHFRUGVXFKDVDERRN¦VWLWOHRU
DXWKRU5HJH[HVLQ6FDODWUDQVODWHWKRVHFDSWXUHJURXSVWRH[WUDFWRUV(YHU\PDWFKVHWV
DILHOGWRWKHFDSWXUHGUHVXOWHYHU\PLVVLVVHWWRnull
:KDWGRHVWKLVPHDQLQSUDFWLFH",IWKHWH[WIHGWRWKHUHJXODUH[SUHVVLRQPDWFKHV
case BookExtractorRE(title, authors)ZLOODVVLJQWKHILUVWFDSWXUHJURXSWRtitleDQG
WKH VHFRQG WR authors :H FDQ WKHQ XVH WKRVH YDOXHV RQ WKH ULJKWKDQG VLGH RI WKH
case FODXVH DV ZH KDYH LQ WKH SUHYLRXV H[DPSOH 7KH YDULDEOH QDPHV title DQG
author ZLWKLQ WKH H[WUDFWRU DUH DUELWUDU\ PDWFKHV IURP FDSWXUH JURXSV DUH VLPSO\
DVVLJQHGIURPOHIWWRULJKWDQG\RXFDQFDOOWKHPZKDWHYHU\RX¦GOLNH
7KDW¦VUHJH[HVLQ6FDODLQQXWVKHOO7KHscala.util.matching.RegexFODVVVXSSOLHVVHY
HUDOKDQG\PHWKRGVIRUILQGLQJDQGUHSODFLQJPDWFKHVLQVWULQJVERWKDOORFFXUUHQFHV
RIDPDWFKDQGMXVWWKHILUVWRFFXUUHQFHVREHVXUHWRPDNHXVHRIWKHP
:KDWZHZRQ¦WFRYHULQWKLVVHFWLRQLVWKHGHWDLOVRIZULWLQJUHJXODUH[SUHVVLRQV6FDOD¦V
Regex FODVV XVHV WKH XQGHUO\LQJ SODWIRUP¦V UHJXODU H[SUHVVLRQ $3,V WKDW LV -DYD¦V
RU1(7¦V &RQVXOWUHIHUHQFHVRQWKRVH$3,VIRUWKHKDLU\GHWDLOVDVWKH\PD\EHVXEWO\
GLIIHUHQWIURPWKHUHJH[VXSSRUWLQ\RXUODQJXDJHRIFKRLFH

Binding Nested Variables in Case Clauses


6RPHWLPHV\RXZDQWWRELQGDYDULDEOHWRDQREMHFWHQFORVHGLQDPDWFKZKHUH\RXDUH
DOVRVSHFLI\LQJPDWFKFULWHULDRQWKHQHVWHGREMHFW6XSSRVHZHPRGLI\DSUHYLRXVH[
DPSOH VR ZH¦UH PDWFKLQJ RQ WKH NH\YDOXH SDLUV IURP D PDS :H¦OO VWRUH RXU VDPH
PersonREMHFWVDVWKHYDOXHVDQGXVHDQHPSOR\HH,'DVWKHNH\:H¦OODOVRDGGDQRWKHU
DWWULEXWHWRPersonDroleILHOGWKDWSRLQWVWRDQLQVWDQFHIURPDW\SHKLHUDUFK\
// code-examples/Rounding/match-deep-pair-script.scala

class Role
case object Manager extends Role
case object Developer extends Role

case class Person(name: String, age: Int, role: Role)

val alice = new Person("Alice", 25, Developer)


val bob = new Person("Bob", 32, Manager)
val charlie = new Person("Charlie", 32, Developer)

for (item <- Map(1 -> alice, 2 -> bob, 3 -> charlie)) {
item match {
case (id, p @ Person(_, _, Manager)) => format("%s is overpaid.\n", p)
case (id, p @ Person(_, _, _)) => format("%s is underpaid.\n", p)
}
}

Pattern Matching | 69

Download at WoweBook.Com
7KHcase objectsDUHMXVWVLQJOHWRQREMHFWVOLNHZH¦YHVHHQEHIRUHEXWZLWKWKHVSHFLDO
caseEHKDYLRU:H¦UHPRVWLQWHUHVWHGLQWKHHPEHGGHGp @ Person(...)LQVLGHWKHFDVH
FODXVH:H¦UHPDWFKLQJRQSDUWLFXODUNLQGVRIPersonREMHFWVLQVLGHWKHHQFORVLQJWXSOH
:HDOVRZDQWWRDVVLJQWKHPersonWRDYDULDEOHpVRZHFDQXVHLWIRUSULQWLQJ
Person(Alice,25,Developer) is underpaid.
Person(Bob,32,Manager) is overpaid.
Person(Charlie,32,Developer) is underpaid.

,IZHZHUHQ¦WXVLQJPDWFKLQJFULWHULDLQPersonLWVHOIZHFRXOGMXVWZULWHp: Person)RU
H[DPSOHWKHSUHYLRXVmatchFODXVHFRXOGEHZULWWHQWKLVZD\
item match {
case (id, p: Person) => p.role match {
case Manager => format("%s is overpaid.\n", p)
case _ => format("%s is underpaid.\n", p)
}
}

1RWHWKDWWKH p @ Person(...)V\QWD[JLYHVXVDZD\WRIODWWHQWKLVQHVWLQJRIPDWFK
VWDWHPHQWVLQWRRQHVWDWHPHQW,WLVDQDORJRXVWRXVLQJ£FDSWXUHJURXSV¤LQDUHJXODU
H[SUHVVLRQ WR SXOO RXW VXEVWULQJV ZH ZDQW LQVWHDG RI VSOLWWLQJ WKH VWULQJ LQ VHYHUDO
VXFFHVVLYHVWHSVWRH[WUDFWWKHVXEVWULQJVZHZDQW8VHZKLFKHYHUWHFKQLTXH\RXSUHIHU

Using try, catch, and finally Clauses


7KURXJKLWVXVHRIIXQFWLRQDOFRQVWUXFWVDQGVWURQJW\SLQJ6FDODHQFRXUDJHVDFRGLQJ
VW\OH WKDW OHVVHQV WKH QHHG IRU H[FHSWLRQV DQG H[FHSWLRQ KDQGOLQJ %XW ZKHUH 6FDOD
LQWHUDFWVZLWK-DYDH[FHSWLRQVDUHVWLOOSUHYDOHQW

6FDODGRHVQRWKDYHFKHFNHGH[FHSWLRQVOLNH-DYD(YHQ-DYD¦VFKHFNHG
H[FHSWLRQVDUHWUHDWHGDVXQFKHFNHGE\6FDOD7KHUHLVDOVRQR throws
FODXVHRQPHWKRGGHFODUDWLRQV+RZHYHUWKHUHLVD@throwsDQQRWDWLRQ
WKDW LV XVHIXO IRU -DYD LQWHURSHUDELOLW\ 6HH WKH VHFWLRQ £$QQRWD
WLRQV¤RQSDJH

7KDQNIXOO\6FDODWUHDWVH[FHSWLRQKDQGOLQJDVMXVWDQRWKHUSDWWHUQPDWFKDOORZLQJXV
WRPDNHVPDUWFKRLFHVZKHQSUHVHQWHGZLWKDPXOWLSOLFLW\RISRWHQWLDOH[FHSWLRQV/HW¦V
VHHWKLVLQDFWLRQ
// code-examples/Rounding/try-catch-script.scala

import java.util.Calendar

val then = null


val now = Calendar.getInstance()

try {
now.compareTo(then)
} catch {

70 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
case e: NullPointerException => println("One was null!"); System.exit(-1)
case unknown => println("Unknown exception " + unknown); System.exit(-1)
} finally {
println("It all worked out.")
System.exit(0)
}

,QWKLVH[DPSOHZHH[SOLFLWO\FDWFKWKH NullPointerExceptionWKURZQZKHQWU\LQJWR
FRPSDUHDCalendarLQVWDQFHZLWKnull:HDOVRGHILQHunknownDVDFDWFKDOOFDVHMXVW
WREHVDIH,IZHZHUHQ¦WKDUGFRGLQJWKLVSURJUDPWRIDLOWKH finallyEORFNZRXOGEH
UHDFKHGDQGWKHXVHUZRXOGEHLQIRUPHGWKDWHYHU\WKLQJZRUNHGRXWMXVWILQH

<RXFDQXVHDQXQGHUVFRUH 6FDOD¦VVWDQGDUGZLOGFDUGFKDUDFWHU DVD


SODFHKROGHUWRFDWFKDQ\W\SHRIH[FHSWLRQ UHDOO\WRPDWFKDQ\FDVHLQ
DSDWWHUQPDWFKLQJH[SUHVVLRQ +RZHYHU\RXZRQ¦WEHDEOHWRUHIHUWR
WKHH[FHSWLRQLQWKHVXEVHTXHQWH[SUHVVLRQ1DPHWKHH[FHSWLRQYDUL
DEOHLI\RXQHHGLWIRUH[DPSOHLI\RXQHHGWRSULQWWKHH[FHSWLRQDVZH
GRLQWKHFDWFKDOOFDVHRIWKHSUHYLRXVH[DPSOH

3DWWHUQPDWFKLQJDVLGH6FDOD¦VWUHDWPHQWRIH[FHSWLRQKDQGOLQJVKRXOGEHIDPLOLDUWR
WKRVHIOXHQWLQ-DYD5XE\3\WKRQDQGPRVWRWKHUPDLQVWUHDPODQJXDJHV$QG\HV
\RXWKURZDQH[FHSWLRQE\ZULWLQJthrow new MyBadException(...)7KDW¦VDOOWKHUHLV
WRLW

Concluding Remarks on Pattern Matching


3DWWHUQPDWFKLQJLVDSRZHUIXODQGHOHJDQWZD\RIH[WUDFWLQJLQIRUPDWLRQIURPREMHFWV
ZKHQXVHGDSSURSULDWHO\5HFDOOIURP&KDSWHUWKDWZHKLJKOLJKWHGWKHV\QHUJ\EH
WZHHQSDWWHUQPDWFKLQJDQGSRO\PRUSKLVP0RVWRIWKHWLPH\RXZDQWWRDYRLGWKH
SUREOHPVRI£VZLWFK¤VWDWHPHQWVWKDWNQRZDFODVVKLHUDUFK\EHFDXVHWKH\KDYHWREH
PRGLILHGHYHU\WLPHWKHKLHUDUFK\LVFKDQJHG
,QRXUGUDZLQJ$FWRUH[DPSOHZHXVHGSDWWHUQPDWFKLQJWRVHSDUDWHGLIIHUHQW£FDWH
JRULHV¤RIPHVVDJHVEXWZHXVHGSRO\PRUSKLVPWRGUDZWKHVKDSHVVHQWWRLW:HFRXOG
FKDQJHWKHShapeKLHUDUFK\DQGWKH$FWRUFRGHZRXOGQRWUHTXLUHFKDQJHV
3DWWHUQPDWFKLQJLVDOVRXVHIXOIRUWKHGHVLJQSUREOHPZKHUH\RXQHHGWRJHWDWGDWD
LQVLGHDQREMHFWEXWRQO\LQVSHFLDOFLUFXPVWDQFHV2QHRIWKHXQLQWHQGHGFRQVHTXHQ
FHVRIWKH-DYD%HDQV VHH>-DYD%HDQV6SHF@ VSHFLILFDWLRQZDVWKDWLWHQFRXUDJHGSHRSOH
WR H[SRVH ILHOGV LQ WKHLU REMHFWV WKURXJKJHWWHUV DQG VHWWHUV7KLV VKRXOG QHYHU EH D
GHIDXOWGHFLVLRQ$FFHVVWR£VWDWHLQIRUPDWLRQ¤VKRXOGEHHQFDSVXODWHGDQGH[SRVHG
RQO\LQZD\VWKDWPDNHORJLFDOVHQVHIRUWKHW\SHDVYLHZHGIURPWKHDEVWUDFWLRQLW
H[SRVHV
,QVWHDGFRQVLGHUXVLQJSDWWHUQPDWFKLQJIRUWKRVH£UDUH¤WLPHVZKHQ\RXQHHGWRH[
WUDFWLQIRUPDWLRQLQDFRQWUROOHGZD\$VZHZLOOVHHLQ£8QDSSO\¤RQSDJHWKH
SDWWHUQPDWFKLQJH[DPSOHVZHKDYHVKRZQXVH unapplyPHWKRGVGHILQHGWRH[WUDFW

Pattern Matching | 71

Download at WoweBook.Com
LQIRUPDWLRQIURPLQVWDQFHV7KHVHPHWKRGVOHW\RXH[WUDFWWKDWLQIRUPDWLRQZKLOHKLG
LQJWKHLPSOHPHQWDWLRQGHWDLOV,QIDFWWKHLQIRUPDWLRQUHWXUQHGE\unapplyPLJKWEH
DWUDQVIRUPDWLRQRIWKHDFWXDOLQIRUPDWLRQLQWKHW\SH
)LQDOO\ZKHQGHVLJQLQJSDWWHUQPDWFKLQJVWDWHPHQWVEHZDU\RIUHO\LQJRQDGHIDXOW
FDVHFODXVH8QGHUZKDWFLUFXPVWDQFHVZRXOG£QRQHRIWKHDERYH¤EHWKHFRUUHFWDQ
VZHU",WPD\LQGLFDWHWKDWWKHGHVLJQVKRXOGEHUHILQHGVR\RXNQRZPRUHSUHFLVHO\DOO
WKHSRVVLEOHPDWFKHVWKDWPLJKWRFFXU:H¦OOOHDUQRQHWHFKQLTXHWKDWKHOSVZKHQZH
GLVFXVVVHDOHGFODVVKLHUDUFKLHVLQ£6HDOHG&ODVV+LHUDUFKLHV¤RQSDJH

Enumerations
5HPHPEHURXUH[DPSOHVLQYROYLQJYDULRXVEUHHGVRIGRJ",QWKLQNLQJDERXWWKHW\SHV
LQWKHVHSURJUDPVZHPLJKWZDQWDWRSOHYHOBreedW\SHWKDWNHHSVWUDFNRIDQXPEHU
RIEUHHGV6XFKDW\SHLVFDOOHGDQHQXPHUDWHGW\SHDQGWKHYDOXHVLWFRQWDLQVDUHFDOOHG
HQXPHUDWLRQV
:KLOHHQXPHUDWLRQVDUHDEXLOWLQSDUWRIPDQ\SURJUDPPLQJODQJXDJHV6FDODWDNHVD
GLIIHUHQWURXWHDQGLPSOHPHQWVWKHPDVDFODVVLQLWVVWDQGDUGOLEUDU\7KLVPHDQVWKHUH
LVQRVSHFLDOV\QWD[IRUHQXPHUDWLRQVLQ6FDODDVLQ-DYDDQG&,QVWHDG\RXMXVW
GHILQHDQREMHFWWKDWH[WHQGVWKHEnumerationFODVV+HQFHDWWKHE\WHFRGHOHYHOWKHUH
LVQRFRQQHFWLRQEHWZHHQ6FDODHQXPHUDWLRQVDQGWKHenumFRQVWUXFWVLQ-DYDDQG&
+HUHLVDQH[DPSOH
// code-examples/Rounding/enumeration-script.scala

object Breed extends Enumeration {


val doberman = Value("Doberman Pinscher")
val yorkie = Value("Yorkshire Terrier")
val scottie = Value("Scottish Terrier")
val dane = Value("Great Dane")
val portie = Value("Portuguese Water Dog")
}

// print a list of breeds and their IDs


println("ID\tBreed")
for (breed <- Breed) println(breed.id + "\t" + breed)

// print a list of Terrier breeds


println("\nJust Terriers:")
Breed.filter(_.toString.endsWith("Terrier")).foreach(println)

:KHQUXQ\RX¦OOJHWWKHIROORZLQJRXWSXW
ID Breed
0 Doberman Pinscher
1 Yorkshire Terrier
2 Scottish Terrier
3 Great Dane
4 Portuguese Water Dog

72 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
Just Terriers:
Yorkshire Terrier
Scottish Terrier

:HFDQVHHWKDWRXUBreedHQXPHUDWHGW\SHFRQWDLQVVHYHUDOYDULDEOHVRIW\SHValueDV
LQWKHIROORZLQJH[DPSOH
val doberman = Value("Doberman Pinscher")

(DFKGHFODUDWLRQLVDFWXDOO\FDOOLQJDPHWKRGQDPHGValueWKDWWDNHVDVWULQJDUJXPHQW
:HXVHWKLVPHWKRGWRDVVLJQDORQJIRUPEUHHGQDPHWRHDFKHQXPHUDWLRQYDOXHZKLFK
LVZKDWWKHValue.toStringPHWKRGUHWXUQHGLQWKHRXWSXW
1RWHWKDWWKHUHLVQRQDPHVSDFHFROOLVLRQEHWZHHQWKHW\SHDQGPHWKRGWKDWERWKKDYH
WKHQDPHValue7KHUHDUHRWKHURYHUORDGHGYHUVLRQVRIWKHValuePHWKRG2QHRIWKHP
WDNHVQRDUJXPHQWVDQRWKHUWDNHVDQInt,'YDOXHDQGDQRWKHUWDNHVERWKDQIntDQG
String7KHVHValuePHWKRGVUHWXUQDValueREMHFWDQGWKH\DGGWKHYDOXHWRWKHHQX
PHUDWLRQ¦VFROOHFWLRQRIYDOXHV
,QIDFW6FDOD¦VEnumerationFODVVVXSSRUWVWKHXVXDOPHWKRGVIRUZRUNLQJZLWKFROOHF
WLRQVVRZHFDQHDVLO\LWHUDWHWKURXJKWKHEUHHGVZLWKDforORRSDQGfilterWKHPE\
QDPH7KHRXWSXWDERYHDOVRGHPRQVWUDWHGWKDWHYHU\ValueLQDQHQXPHUDWLRQLVDX
WRPDWLFDOO\ DVVLJQHG D QXPHULF LGHQWLILHU XQOHVV \RX FDOO RQH RI WKH Value PHWKRGV
ZKHUH\RXVSHFLI\\RXURZQ,'YDOXHH[SOLFLWO\
<RX¦OORIWHQZDQWWRJLYH\RXUHQXPHUDWLRQYDOXHVKXPDQUHDGDEOHQDPHVDVZHGLG
KHUH+RZHYHUVRPHWLPHV\RXPD\QRWQHHGWKHP+HUH¦VDQRWKHUHQXPHUDWLRQH[
DPSOHDGDSWHGIURPWKH6FDODGRFHQWU\IRUEnumeration
// code-examples/Rounding/days-enumeration-script.scala

object WeekDay extends Enumeration {


type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._

def isWorkingDay(d: WeekDay) = ! (d == Sat || d == Sun)

WeekDay filter isWorkingDay foreach println

5XQQLQJWKLVVFULSWZLWKscala\LHOGVWKHIROORZLQJRXWSXW
Main$$anon$1$WeekDay(0)
Main$$anon$1$WeekDay(1)
Main$$anon$1$WeekDay(2)
Main$$anon$1$WeekDay(3)
Main$$anon$1$WeekDay(4)

:KHQDQDPHLVQ¦WDVVLJQHGXVLQJRQHRIWKHValuePHWKRGVWKDWWDNHVDStringDUJX
PHQWValue.toStringSULQWVWKHQDPHRIWKHW\SHWKDWLVV\QWKHVL]HGE\WKHFRPSLOHU
DORQJZLWKWKH,'YDOXHWKDWZDVJHQHUDWHGDXWRPDWLFDOO\

Enumerations | 73

Download at WoweBook.Com
1RWHWKDWZHLPSRUWHGWeekDay._7KLVPDGHHDFKHQXPHUDWLRQYDOXH MonTuesHWF
LQVFRSH2WKHUZLVH\RXZRXOGKDYHWRZULWHWeekDay.MonWeekDay.TuesHWF
$OVRWKHLPSRUWPDGHWKHW\SHDOLDVtype Weekday = ValueLQVFRSHZKLFKZHXVHG
DVWKHW\SHIRUWKHDUJXPHQWIRUWKH isWorkingDayPHWKRG,I\RXGRQ¦WGHILQHDW\SH
DOLDV OLNH WKLV WKHQ \RX ZRXOG GHFODUH WKH PHWKRG DV def isWorkingDay(d: Week
Day.Value)
6LQFH6FDODHQXPHUDWLRQVDUHMXVWUHJXODUREMHFWV\RXFRXOGXVHDQ\REMHFWZLWK vals
WRLQGLFDWHGLIIHUHQW£HQXPHUDWLRQYDOXHV¤+RZHYHUH[WHQGLQJ EnumerationKDVVHY
HUDODGYDQWDJHV,WDXWRPDWLFDOO\PDQDJHVWKHYDOXHVDVDFROOHFWLRQWKDW\RXFDQLWHUDWH
RYHUHWFDVLQRXUH[DPSOHV,WDOVRDXWRPDWLFDOO\DVVLJQVXQLTXHLQWHJHU,'VWRHDFK
YDOXH
&DVHFODVVHV VHH£&DVH&ODVVHV¤RQSDJH DUHRIWHQXVHGLQVWHDGRIHQXPHUDWLRQV
LQ6FDODEHFDXVHWKH£XVHFDVH¤IRUWKHPRIWHQLQYROYHVSDWWHUQPDWFKLQJ:H¦OOUHYLVLW
WKLVWRSLFLQ£(QXPHUDWLRQV9HUVXV3DWWHUQ0DWFKLQJ¤RQSDJH

Recap and What’s Next


:H¦YHFRYHUHGDORWRIJURXQGLQWKLVFKDSWHU:HOHDUQHGKRZIOH[LEOH6FDOD¦VV\QWD[
FDQ EH DQG KRZ LW IDFLOLWDWHV WKH FUHDWLRQ RI 'RPDLQ6SHFLILF /DQJXDJHV 7KHQ ZH
H[SORUHG6FDOD¦VHQKDQFHPHQWVWRORRSLQJFRQVWUXFWVDQGFRQGLWLRQDOH[SUHVVLRQV:H
H[SHULPHQWHGZLWKGLIIHUHQWXVHVIRUSDWWHUQPDWFKLQJDSRZHUIXOLPSURYHPHQWRQWKH
IDPLOLDU case-switch VWDWHPHQW )LQDOO\ ZH OHDUQHG KRZ WR HQFDSVXODWH YDOXHV LQ
HQXPHUDWLRQV
<RXVKRXOGQRZEHSUHSDUHGWRUHDGDIDLUELWRI6FDODFRGHEXWWKHUH¦VSOHQW\PRUH
DERXWWKHODQJXDJHWRSXWLQ\RXUWRROEHOW,QWKHQH[WIRXUFKDSWHUVZH¦OOH[SORUH
6FDOD¦VDSSURDFKWRREMHFWRULHQWHGSURJUDPPLQJVWDUWLQJZLWKWUDLWV

74 | Chapter 3:—Rounding Out the Essentials

Download at WoweBook.Com
CHAPTER 4
Traits

Introducing Traits
%HIRUHZHGLYHLQWRREMHFWRULHQWHGSURJUDPPLQJWKHUH¦VRQHPRUHHVVHQWLDOIHDWXUHRI
6FDODWKDW\RXVKRXOGJHWDFTXDLQWHGZLWKWUDLWV8QGHUVWDQGLQJWKHYDOXHRIWKLVIHDWXUH
UHTXLUHVDOLWWOHEDFNVWRU\
,Q-DYDDFODVVFDQLPSOHPHQWDQDUELWUDU\QXPEHURILQWHUIDFHV7KLVPRGHOLVYHU\
XVHIXOIRUGHFODULQJWKDWDFODVVH[SRVHVPXOWLSOHDEVWUDFWLRQV8QIRUWXQDWHO\LWKDVRQH
PDMRUGUDZEDFN
)RUPDQ\LQWHUIDFHVPXFKRIWKHIXQFWLRQDOLW\FDQEHLPSOHPHQWHGZLWKERLOHUSODWH
FRGHWKDWZLOOEHYDOLGIRUDOOFODVVHVWKDWXVHWKHLQWHUIDFH-DYDSURYLGHVQREXLOWLQ
PHFKDQLVPIRUGHILQLQJDQGXVLQJVXFKUHXVDEOHFRGH,QVWHDG-DYDSURJUDPPHUVPXVW
XVHDGKRFFRQYHQWLRQVWRUHXVHLPSOHPHQWDWLRQFRGHIRUDJLYHQLQWHUIDFH,QWKHZRUVW
FDVHWKHGHYHORSHUMXVWFRSLHVDQGSDVWHVWKHVDPHFRGHLQWRHYHU\FODVVWKDWQHHGVLW
2IWHQWKHLPSOHPHQWDWLRQRIDQLQWHUIDFHKDVPHPEHUVWKDWDUHXQUHODWHG £RUWKRJR
QDO¤ WRWKHUHVWRIWKHLQVWDQFH¦VPHPEHUV7KHWHUPPL[LQLVRIWHQXVHGIRUVXFKIRFXVHG
DQGSRWHQWLDOO\UHXVDEOHSDUWVRIDQLQVWDQFHWKDWFRXOGEHLQGHSHQGHQWO\PDLQWDLQHG
+DYHDORRNDWWKHIROORZLQJFRGHIRUDEXWWRQLQDJUDSKLFDOXVHULQWHUIDFHZKLFKXVHV
FDOOEDFNVIRU£FOLFNV¤
// code-examples/Traits/ui/button-callbacks.scala

package ui

class ButtonWithCallbacks(val label: String,


val clickedCallbacks: List[() => Unit]) extends Widget {

require(clickedCallbacks != null, "Callback list can't be null!")

def this(label: String, clickedCallback: () => Unit) =


this(label, List(clickedCallback))

def this(label: String) = {

75

Download at WoweBook.Com
this(label, Nil)
println("Warning: button has no click callbacks!")
}

def click() = {
// ... logic to give the appearance of clicking a physical button ...
clickedCallbacks.foreach(f => f())
}
}

7KHUH¦VDORWJRLQJRQKHUH7KHSULPDU\FRQVWUXFWRUWDNHVDlabelDUJXPHQWDQGDOLVW
RIcallbacksWKDWDUHLQYRNHGZKHQWKHEXWWRQ¦VclickPHWKRGLVLQYRNHG:H¦OOH[SORUH
WKLVFODVVLQJUHDWHUGHWDLOLQ&KDSWHU)RUQRZZHZDQWWRIRFXVRQRQHSDUWLFXODU
SUREOHP 1RW RQO\ GRHV ButtonWithCallbacks KDQGOH EHKDYLRUV HVVHQWLDO WR EXWWRQV
OLNHFOLFNLQJ LWDOVRKDQGOHVQRWLILFDWLRQRIFOLFNHYHQWVE\LQYRNLQJWKHFDOOEDFNIXQF
WLRQV7KLVJRHVDJDLQVWWKH6LQJOH5HVSRQVLELOLW\3ULQFLSOH VHH>0DUWLQ@ DPHDQV
WRWKHGHVLJQJRDORI VHSDUDWLRQRIFRQFHUQV:HZRXOGOLNHWRVHSDUDWHWKHEXWWRQ
VSHFLILFORJLFIURPWKHFDOOEDFNORJLFVXFKWKDWHDFKORJLFDOFRPSRQHQWEHFRPHVVLP
SOHUPRUHPRGXODUDQGPRUHUHXVDEOH7KHFDOOEDFNORJLFLVDJRRGH[DPSOHRIDPL[LQ
7KLVVHSDUDWLRQLVGLIILFXOWWRGRLQ-DYDHYHQLIZHGHILQHDQLQWHUIDFHIRUWKHFDOOEDFN
EHKDYLRU :H VWLOO KDYH WR HPEHG WKH LPSOHPHQWDWLRQ FRGH LQ WKH FODVV VRPHKRZ
FRPSURPLVLQJPRGXODULW\7KHRQO\RWKHUDOWHUQDWLYHLVWRXVHDVSHFLDOL]HGWRROOLNH
DVSHFWRULHQWHG SURJUDPPLQJ $23 VHH >$26'@  DV LPSOHPHQWHG E\ $VSHFW- VHH
>$VSHFW-@ DQH[WHQVLRQRI-DYD$23LVSULPDULO\GHVLJQHGWRVHSDUDWHWKHLPSOHPHQ
WDWLRQVRI£SHUYDVLYH¤FRQFHUQVWKDWDUHUHSHDWHGWKURXJKRXWDQDSSOLFDWLRQ,WVHHNV
WRPRGXODUL]HWKHVHFRQFHUQV\HWHQDEOHWKHILQHJUDLQHG£PL[LQJ¤RIWKHLUEHKDYLRUV
ZLWKRWKHUFRQFHUQVLQFOXGLQJWKHFRUHGRPDLQORJLFRIWKHDSSOLFDWLRQHLWKHUDWEXLOG
RUUXQWLPH

Traits As Mixins
6FDODSURYLGHVDFRPSOHWHPL[LQVROXWLRQFDOOHGWUDLWV,QRXUH[DPSOHZHFDQGHILQH
WKHFDOOEDFNDEVWUDFWLRQLQDWUDLWDVLQD-DYDLQWHUIDFHEXWZHFDQDOVRLPSOHPHQWWKH
DEVWUDFWLRQLQWKHWUDLW RUDGHULYHGWUDLW :HFDQGHFODUHFODVVHVWKDW£PL[LQ¤WKH
WUDLWPXFKWKHZD\\RXFDQGHFODUHFODVVHVWKDWLPSOHPHQWDQLQWHUIDFHLQ-DYD+RZ
HYHULQ6FDODZHFDQHYHQPL[LQWUDLWVDWWKHVDPHWLPHZHFUHDWHLQVWDQFHV7KDWLV
ZHGRQ¦WKDYHWRGHFODUHDFODVVILUVWWKDWPL[HVLQDOOWKHWUDLWVZHZDQW6R6FDODWUDLWV
SUHVHUYH VHSDUDWLRQ RI FRQFHUQV ZKLOH JLYLQJ XV WKH DELOLW\ WR FRPSRVH EHKDYLRU RQ
GHPDQG
,I\RXFRPHIURPD-DYDEDFNJURXQG\RXFDQWKLQNRIWUDLWVDVLQWHUIDFHVZLWKRSWLRQDO
LPSOHPHQWDWLRQV2ULI\RXSUHIHU\RXFDQWKLQNRIWUDLWVDVD£FRQVWUDLQHG¤IRUPRI
PXOWLSOHLQKHULWDQFH2WKHUODQJXDJHVSURYLGHFRQVWUXFWVWKDWDUHVLPLODUWRWUDLWVVXFK
DVPRGXOHVLQ5XE\IRUH[DPSOH
/HW¦VXVHDWUDLWWRVHSDUDWHWKHFDOOEDFNKDQGOLQJIURPWKHEXWWRQORJLF:H¦OOJHQHUDOL]H
RXUDSSURDFKDOLWWOHELW&DOOEDFNVDUHUHDOO\DVSHFLDOFDVHRIWKH2EVHUYHU3DWWHUQ VHH

76 | Chapter 4:—Traits

Download at WoweBook.Com
>*2)@ 6ROHW¦VFUHDWHDWUDLWWKDWLPSOHPHQWVWKLVSDWWHUQDQGWKHQXVHLWWR
KDQGOH FDOOEDFN EHKDYLRU 7R VLPSOLI\ WKLQJV ZH¦OO VWDUW ZLWK D VLQJOH FDOOEDFN WKDW
FRXQWVWKHQXPEHURIEXWWRQFOLFNV
)LUVWOHW¦VGHILQHDVLPSOHButtonFODVV
// code-examples/Traits/ui/button.scala

package ui

class Button(val label: String) extends Widget {


def click() = {
// Logic to give the appearance of clicking a button...
}
}

+HUHLVWKHSDUHQWFODVVWidget
// code-examples/Traits/ui/widget.scala

package ui

abstract class Widget

7KHORJLFIRUPDQDJLQJFDOOEDFNV LHWKHclickedCallbacksOLVW LVRPLWWHGDVDUHWKH


WZRDX[LOLDU\FRQVWUXFWRUV2QO\WKHEXWWRQ¦V labelILHOGDQG clickPHWKRGUHPDLQ
7KHclickPHWKRGQRZRQO\FDUHVDERXWWKHYLVXDODSSHDUDQFHRID£SK\VLFDO¤EXWWRQ
EHLQJFOLFNHGButtonKDVRQO\RQHFRQFHUQKDQGOLQJWKH£HVVHQFH¤RIEHLQJDEXWWRQ
+HUHLVDWUDLWWKDWLPSOHPHQWVWKHORJLFRIWKH2EVHUYHU3DWWHUQ
// code-examples/Traits/observer/observer.scala

package observer

trait Subject {
type Observer = { def receiveUpdate(subject: Any) }

private var observers = List[Observer]()


def addObserver(observer:Observer) = observers ::= observer
def notifyObservers = observers foreach (_.receiveUpdate(this))
}

([FHSWIRUWKHtraitNH\ZRUGSubjectORRNVOLNHDQRUPDOFODVVSubjectGHILQHVDOOWKH
PHPEHUVLWGHFODUHV7UDLWVFDQGHFODUHDEVWUDFWPHPEHUVFRQFUHWHPHPEHUVRUERWK
MXVWDVFODVVHVFDQ VHH£2YHUULGLQJ0HPEHUVRI&ODVVHVDQG7UDLWV¤RQSDJHIRU
PRUHGHWDLOV $OVROLNHFODVVHVWUDLWVFDQFRQWDLQQHVWHGWUDLWDQGFODVVGHILQLWLRQVDQG
FODVVHVFDQFRQWDLQQHVWHGWUDLWGHILQLWLRQV
7KH ILUVW OLQH GHILQHV D type IRU DQ Observer 7KLV LV D VWUXFWXUDO W\SH RI WKH IRUP
{ def receiveUpdate(subject:Any) }6WUXFWXUDOW\SHVVSHFLI\RQO\WKHVWUXFWXUHDW\SH
PXVWVXSSRUW\RXFRXOGWKLQNRIWKHPDV£DQRQ\PRXV¤W\SHV

Introducing Traits | 77

Download at WoweBook.Com
,QWKLVFDVHWKHVWUXFWXUDOW\SHLVGHILQHGE\DPHWKRGZLWKDSDUWLFXODUVLJQDWXUH$Q\
W\SHWKDWKDVDPHWKRGZLWKWKLVVLJQDWXUHFDQEHXVHGDVDQREVHUYHU:H¦OOOHDUQPRUH
DERXWVWUXFWXUDOW\SHVLQ&KDSWHU,I\RX¦UHZRQGHULQJZK\ZHGLGQ¦WXVHSubject
DVWKHW\SHRIWKHDUJXPHQWLQVWHDGRIAnyZH¦OOUHYLVLWWKDWLVVXHLQ£6HOI7\SH$QQR
WDWLRQVDQG$EVWUDFW7\SH0HPEHUV¤RQSDJH
7KHPDLQWKLQJWRQRWLFHIRUQRZLVKRZWKLVVWUXFWXUDOW\SHPLQLPL]HVWKHFRXSOLQJ
EHWZHHQWKHSubjectWUDLWDQGDQ\SRWHQWLDOXVHUVRIWKHWUDLW

SubjectLVVWLOOFRXSOHGE\WKHQDPHRIWKHPHWKRGLQObserverWKURXJK
WKHVWUXFWXUDOW\SHLHWRDPHWKRGQDPHG receiveUpdate7KHUHDUH
VHYHUDOZD\VZHFDQUHGXFHWKLVUHPDLQLQJFRXSOLQJ:H¦OOVHHKRZLQ
£2YHUULGLQJ$EVWUDFW7\SHV¤RQSDJH

1H[WZHGHFODUHDOLVWRIREVHUYHUV:HPDNHLWDvarUDWKHUWKDQDvalEHFDXVHList
LV LPPXWDEOH VR ZH PXVW FUHDWH D QHZ OLVW ZKHQ DQ REVHUYHU LV DGGHG XVLQJ WKH
addObserverPHWKRG
:H¦OOGLVFXVV6FDOD ListVPRUHLQ£7KH6FDOD7\SH+LHUDUFK\¤RQSDJHDQGDOVR
LQ&KDSWHU)RUQRZQRWLFHWKDW addObserverXVHVWKHOLVWFRQV£RSHUDWRU¤PHWKRG
:: WRSUHSHQGDQobserverWRWKHOLVWRIobservers7KHscalaFRPSLOHULVVPDUWHQRXJK
WRWXUQWKHIROORZLQJVWDWHPHQW
observers ::= observer

LQWRWKLVVWDWHPHQW
observers = observer :: observers

1RWH WKDW ZH ZURWH observer :: observers ZLWK WKH H[LVWLQJ observers OLVW RQ WKH
ULJKWKDQG VLGH 5HFDOO WKDW DQ\ PHWKRG WKDW HQGV ZLWK : ELQGV WR WKH ULJKW 6R WKH
SUHYLRXVVWDWHPHQWLVHTXLYDOHQWWRWKHIROORZLQJVWDWHPHQW
observers = observers.::(observer)

7KHnotifyObserversPHWKRGLWHUDWHVWKURXJKWKHobserversXVLQJWKHforeachPHWKRG
DQGFDOOVreceiveUpdateRQHDFKRQH 1RWHWKDWZHDUHXVLQJWKH£LQIL[¤RSHUDWRUQR
WDWLRQLQVWHDGRIobservers.foreach :HXVHWKHSODFHKROGHU_WRVKRUWHQWKHIROORZLQJ
H[SUHVVLRQ
(obs) => obs.receiveUpdate(this)

LQWRWKLVH[SUHVVLRQ
_.receiveUpdate(this)

7KLV H[SUHVVLRQ LV DFWXDOO\ WKH ERG\ RI DQ £DQRQ\PRXV IXQFWLRQ¤ FDOOHG DIXQFWLRQ
OLWHUDO LQ 6FDOD 7KLV LV VLPLODU WR D ODPEGD DQG OLNH FRQVWUXFWV XVHG LQ PDQ\ RWKHU
ODQJXDJHV )XQFWLRQ OLWHUDOV DQG WKH UHODWHG FRQFHSW RI D FORVXUH DUH GLVFXVVHG LQ
£)XQFWLRQ/LWHUDOVDQG&ORVXUHV¤RQSDJH

78 | Chapter 4:—Traits

Download at WoweBook.Com
,Q-DYDWKHforeachPHWKRGZRXOGSUREDEO\WDNHDQLQWHUIDFHDQG\RXZRXOGSDVVDQ
LQVWDQFHRIDFODVVWKDWLPSOHPHQWVWKHLQWHUIDFH HJWKHZD\ComparableLVW\SLFDOO\
XVHG 
,Q6FDODWKHList[A].foreachPHWKRGH[SHFWVDQDUJXPHQWRIW\SH(A) => UnitZKLFK
LVDIXQFWLRQWDNLQJDQLQVWDQFHRIW\SHA¢ZKHUHAUHSUHVHQWVWKHW\SHRIWKHHOHPHQWV
RIWKHOLVW ObserverLQWKLVFDVH ¢DQGUHWXUQLQJUnit OLNHvoidLQ-DYD 

:HFKRVHWRXVHD varZLWKLPPXWDEOH ListsIRUWKHREVHUYHUVLQWKLV


H[DPSOH :H FRXOG KDYH XVHG D val ZLWK D PXWDEOH W\SH OLNH
ListBuffer 7KDW FKRLFH ZRXOG PDNH D OLWWOH PRUH VHQVH IRU D UHDO
DSSOLFDWLRQEXWZHZDQWHGWRDYRLGWKHGLVWUDFWLRQRIH[SODLQLQJQHZ
OLEUDU\FODVVHV

2QFH DJDLQ ZH OHDUQHG D ORW RI 6FDOD IURP D VPDOO H[DPSOH 1RZ OHW¦V SXW RXU
SubjectWUDLWWRXVH+HUHLV ObservableButtonZKLFKVXEFODVVHV ButtonDQGPL[HVLQ
Subject
// code-examples/Traits/ui/observable-button.scala

package ui
import observer._

class ObservableButton(name: String) extends Button(name) with Subject {


override def click() = {
super.click()
notifyObservers
}
}

:H VWDUW E\ LPSRUWLQJ HYHU\WKLQJ LQ WKH observer SDFNDJH XVLQJ WKH _ ZLOGFDUG
$FWXDOO\ZHKDYHRQO\GHILQHGWKHSubjectWUDLWLQWKHSDFNDJH
7KHQHZFODVVXVHVWKHwithNH\ZRUGWRDGGWKHSubjectWUDLWWRWKHFODVVObservable
ButtonRYHUULGHVWKHclickPHWKRG8VLQJWKHsuperNH\ZRUG VHH£2YHUULGLQJ$EVWUDFW
DQG &RQFUHWH 0HWKRGV¤ RQ SDJH   LW ILUVW LQYRNHV WKH £VXSHUFODVV¤ PHWKRG
Button.clickDQGWKHQLWQRWLILHVWKHREVHUYHUV6LQFHWKHQHZclickPHWKRGRYHUULGHV
Button¦VFRQFUHWHLPSOHPHQWDWLRQWKHoverrideNH\ZRUGLVUHTXLUHG
7KH withNH\ZRUGLVDQDORJRXVWR-DYD¦V implementsNH\ZRUGIRULQWHUIDFHV<RXFDQ
VSHFLI\DVPDQ\WUDLWVDV\RXZDQWHDFKZLWKLWVRZQwithNH\ZRUG
$FODVVFDQH[WHQGDWUDLWDQGDWUDLWFDQH[WHQGDFODVV,QIDFWRXUWidgetFODVVHDUOLHU
FRXOGKDYHEHHQGHFODUHGWREHDWUDLW

,I\RXGHFODUHDFODVVWKDWXVHVRQHRUPRUHWUDLWVDQGLWGRHVQ¦WH[WHQG
DQRWKHUFODVV\RXPXVWXVHWKHextendsNH\ZRUGIRUWKHILUVWWUDLWOLVWHG

Introducing Traits | 79

Download at WoweBook.Com
,I\RXGRQ¦WXVHextendsIRUWKHILUVWWUDLWHJ\RXZULWHWKHIROORZLQJ
// ERROR:
class ObservableButton(name: String) with Button(name) with Subject {...}

<RX¦OOJHWDQHUURUOLNHWKLV
... error: ';' expected but 'with' found.
class ObservableButton(name: String) with Button(name) with Subject {...}
^

7KHHUURUVKRXOGUHDOO\VD\£withIRXQGEXWextendsH[SHFWHG¤
7RGHPRQVWUDWHWKLVFRGHOHW¦VVWDUWZLWKDFODVVIRUREVHUYLQJEXWWRQFOLFNVWKDWVLPSO\
FRXQWVWKHQXPEHURIFOLFNV
// code-examples/Traits/ui/button-count-observer.scala

package ui
import observer._

class ButtonCountObserver {
var count = 0
def receiveUpdate(subject: Any) = count += 1
}

)LQDOO\OHW¦VZULWHDWHVWWKDWH[HUFLVHVDOOWKHVHFODVVHV:HZLOOXVHWKH6SHFVOLEUDU\
GLVFXVVHGLQ£6SHFV¤RQSDJH WRZULWHD%HKDYLRU'ULYHQ'HYHORSPHQW >%''@
£VSHFLILFDWLRQ¤WKDWH[HUFLVHVWKHFRPELQHGButtonDQGSubjectW\SHV
// code-examples/Traits/ui/button-observer-spec.scala

package ui
import org.specs._
import observer._

object ButtonObserverSpec extends Specification {


"A Button Observer" should {
"observe button clicks" in {
val observableButton = new ObservableButton("Okay")
val buttonObserver = new ButtonCountObserver
observableButton.addObserver(buttonObserver)

for (i <- 1 to 3) observableButton.click()


buttonObserver.count mustEqual 3
}
}
}

,I\RXGRZQORDGHGWKHFRGHH[DPSOHVIURPWKH2¦5HLOO\VLWH\RXFDQIROORZWKHGLUHF
WLRQVLQLWV5($'0(ILOHVIRUEXLOGLQJDQGUXQQLQJWKHH[DPSOHVLQWKLVFKDSWHU7KH
RXWSXWRIWKHspecs£WDUJHW¤RIWKHEXLOGVKRXOGLQFOXGHWKHIROORZLQJWH[W
Specification "ButtonCountObserverSpec"
A Button Observer should
+ observe button clicks

80 | Chapter 4:—Traits

Download at WoweBook.Com
Total for specification "ButtonCountObserverSpec":
Finished in 0 second, 10 ms
1 example, 1 expectation, 0 failure, 0 error

1RWLFHWKDWWKHVWULQJV A Button Observer shouldDQG observe button clicksFRUUH


VSRQGWRVWULQJVLQWKHH[DPSOH7KHRXWSXWRID6SHFVUXQSURYLGHVDQLFHVXPPDU\RI
WKHUHTXLUHPHQWVIRUWKHLWHPVEHLQJWHVWHGDVVXPLQJJRRGFKRLFHVZHUHPDGHIRUWKH
VWULQJV
7KHERG\RIWKHWHVWFUHDWHVDQ£2ND\¤ObservableButtonDQGDButtonCountObserver
ZKLFKJLYHVWKHREVHUYHUWRWKHEXWWRQ7KHEXWWRQLVFOLFNHGWKUHHWLPHVXVLQJWKH
forORRS7KHODVWOLQHUHTXLUHVWKHREVHUYHU¦VcountWRHTXDO,I\RXDUHDFFXVWRPHG
WRXVLQJDQ;8QLWVW\OH7''WRROOLNHJUnit VHH>-8QLW@ RUScalaTest VHH>6FDOD7HVW
7RRO@DQG£6FDOD7HVW¤RQSDJH WKHQWKHODVWOLQHLVHTXLYDOHQWWRWKHIROORZLQJ
JUnitDVVHUWLRQ
assertEquals(3, buttonObserver.count)

7KH6SHFVOLEUDU\ VHH£6SHFV¤RQSDJH DQGWKH6FDOD7HVWOLEUDU\


VHH£6FDOD7HVW¤RQSDJH ERWKVXSSRUW%HKDYLRU'ULYHQ'HYHORS
PHQW >%''@ DVW\OHRI7HVW'ULYHQ'HYHORSPHQW >7''@ WKDWHPSKD
VL]HVWKH£VSHFLILFDWLRQ¤UROHRIWHVWV

6XSSRVHZHQHHGRQO\RQH ObservableButtonLQVWDQFH":HDFWXDOO\GRQ¦WKDYHWRGH
FODUHDFODVVWKDWVXEFODVVHVButtonZLWKSubject:HFDQLQFRUSRUDWHWKHWUDLWZKHQZH
FUHDWHWKHLQVWDQFH
7KHQH[WH[DPSOHVKRZVDUHYLVHG6SHFVILOHWKDWLQVWDQWLDWHVD ButtonZLWK Subject
PL[HGLQDVSDUWRIWKHGHFODUDWLRQ
// code-examples/Traits/ui/button-observer-anon-spec.scala

package ui
import org.specs._
import observer._

object ButtonObserverAnonSpec extends Specification {


"A Button Observer" should {
"observe button clicks" in {
val observableButton = new Button("Okay") with Subject {
override def click() = {
super.click()
notifyObservers
}
}

val buttonObserver = new ButtonCountObserver


observableButton.addObserver(buttonObserver)

for (i <- 1 to 3) observableButton.click()


buttonObserver.count mustEqual 3

Introducing Traits | 81

Download at WoweBook.Com
}
}
}

7KHUHYLVHGGHFODUDWLRQRI observableButtonDFWXDOO\FUHDWHVDQDQRQ\PRXVFODVVLQ
ZKLFK ZH RYHUULGH WKH click PHWKRG DV EHIRUH 7KH PDLQ GLIIHUHQFH ZLWK FUHDWLQJ
DQRQ\PRXVFODVVHVLQ-DYDLVWKDWZHFDQLQFRUSRUDWHWUDLWVLQWKLVSURFHVV-DYDGRHV
QRWOHW\RXLPSOHPHQWDQHZLQWHUIDFHZKLOHLQVWDQWLDWLQJDFODVV
)LQDOO\QRWHWKDWWKHLQKHULWDQFHKLHUDUFK\IRUDQLQVWDQFHFDQEHFRPSOH[LILWPL[HV
LQ WUDLWV WKDW H[WHQG RWKHU WUDLWV HWF :H¦OO GLVFXVV WKH GHWDLOV RI WKH KLHUDUFK\ LQ
£/LQHDUL]DWLRQRIDQ2EMHFW¦V+LHUDUFK\¤RQSDJH

Stackable Traits
7KHUHDUHDFRXSOHRIUHILQHPHQWVZHFDQGRWRLPSURYHWKHUHXVDELOLW\RIRXUZRUNDQG
WRPDNHLWHDVLHUWRXVHPRUHWKDQRQHWUDLWDWDWLPHLHWR£VWDFN¤WKHP
)LUVWOHW¦VLQWURGXFHDQHZWUDLWClickableDQDEVWUDFWLRQIRUDQ\ZLGJHWWKDWUHVSRQGV
WRFOLFNV
// code-examples/Traits/ui2/clickable.scala

package ui2

trait Clickable {
def click()
}

:H¦UHVWDUWLQJZLWKDQHZSDFNDJHui2WRPDNHLWHDVLHUWRNHHSROGHU
DQGQHZHUYHUVLRQVRIWKHH[DPSOHVGLVWLQFWLQWKHGRZQORDGDEOHFRGH

7KHClickableWUDLWORRNVMXVWOLNHD-DYDLQWHUIDFHLWLVFRPSOHWHO\DEVWUDFW,WGHILQHV
DVLQJOHDEVWUDFWPHWKRG click7KHPHWKRGLVDEVWUDFWEHFDXVHLWKDVQRERG\,I
ClickableZHUHDFODVVZHZRXOGKDYHWRDGGWKH abstractNH\ZRUGLQIURQWRIWKH
classNH\ZRUG7KLVLVQRWQHFHVVDU\IRUWUDLWV
+HUHLVWKHUHIDFWRUHGEXWWRQZKLFKXVHVWKHWUDLW
// code-examples/Traits/ui2/button.scala

package ui2

import ui.Widget

class Button(val label: String) extends Widget with Clickable {


def click() = {
// Logic to give the appearance of clicking a button...

82 | Chapter 4:—Traits

Download at WoweBook.Com
}
}

7KLVFRGHLVOLNH-DYDFRGHWKDWLPSOHPHQWVDClickableLQWHUIDFH
:KHQZHSUHYLRXVO\GHILQHGObservableButton LQ£7UDLWV$V0L[LQV¤RQSDJH ZH
RYHUURGH Button.click WR QRWLI\ WKH REVHUYHUV :H KDG WR GXSOLFDWH WKDW ORJLF LQ
ButtonObserverAnonSpecZKHQZHGHFODUHGobservableButtonDVDButtonLQVWDQFHWKDW
PL[HGLQWKHSubjectWUDLWGLUHFWO\/HW¦VHOLPLQDWHWKLVGXSOLFDWLRQ
:KHQZHUHIDFWRUWKHFRGHWKLVZD\ZHUHDOL]HWKDWZHGRQ¦WUHDOO\FDUHDERXWREVHUYLQJ
EXWWRQVZHFDUHDERXWREVHUYLQJFOLFNV+HUHLVDWUDLWWKDWIRFXVHVVROHO\RQREVHUYLQJ
Clickable
// code-examples/Traits/ui2/observable-clicks.scala

package ui2
import observer._

trait ObservableClicks extends Clickable with Subject {


abstract override def click() = {
super.click()
notifyObservers
}
}

7KHObservableClicksWUDLWH[WHQGVClickableDQGPL[HVLQSubject,WWKHQRYHUULGHV
WKHclickPHWKRGZLWKDQLPSOHPHQWDWLRQWKDWORRNVDOPRVWWKHVDPHDVWKHRYHUULGGHQ
PHWKRG VKRZQ LQ £7UDLWV $V 0L[LQV¤ RQ SDJH  7KH LPSRUWDQW GLIIHUHQFH LV WKH
abstractNH\ZRUG
/RRNFORVHO\DWWKLVPHWKRG,WFDOOV super.click()EXWZKDWLV superLQWKLVFDVH"$W
WKLVSRLQWLWFRXOGRQO\DSSHDUWREHClickableZKLFKGHFODUHVEXWGRHVQRWGHILQHWKH
clickPHWKRGRULWFRXOGEH SubjectZKLFKGRHVQ¦WKDYHD clickPHWKRG6R super
FDQ¦WEHERXQGDWOHDVWQRW\HW
,QIDFW superZLOOEHERXQGZKHQWKLVWUDLWLVPL[HGLQWRDQLQVWDQFHWKDWGHILQHVD
FRQFUHWH clickPHWKRGVXFKDV Button7KHUHIRUHZHQHHGDQ abstractNH\ZRUGRQ
ObservableClicks.clickWRWHOOWKHFRPSLOHU DQGWKHUHDGHU WKDWclickLVQRW\HWIXOO\
LPSOHPHQWHGHYHQWKRXJKObservableClicks.clickKDVDERG\

([FHSWIRUGHFODULQJDEVWUDFWFODVVHVWKH abstractNH\ZRUGLVRQO\UH
TXLUHGRQDPHWKRGLQDWUDLWZKHQWKHPHWKRGKDVDERG\EXWLWFDOOV
WKH super PHWKRG WKDW GRHVQ¦W KDYH D FRQFUHWH LPSOHPHQWDWLRQ LQ
SDUHQWVRIWKHWUDLW

/HW¦VXVHWKLVWUDLWZLWKButtonDQGLWVFRQFUHWHclickPHWKRGLQD6SHFVWHVW
// code-examples/Traits/ui2/button-clickable-observer-spec.scala

package ui2

Stackable Traits | 83

Download at WoweBook.Com
import org.specs._
import observer._
import ui.ButtonCountObserver

object ButtonClickableObserverSpec extends Specification {


"A Button Observer" should {
"observe button clicks" in {
val observableButton = new Button("Okay") with ObservableClicks
val buttonClickCountObserver = new ButtonCountObserver
observableButton.addObserver(buttonClickCountObserver)

for (i <- 1 to 3) observableButton.click()


buttonClickCountObserver.count mustEqual 3
}
}
}

&RPSDUH WKLV FRGH WR ButtonObserverAnonSpec :H LQVWDQWLDWH D Button ZLWK WKH
ObservableClicksWUDLWPL[HGLQEXWQRZWKHUHLVQRRYHUULGHRIclickUHTXLUHG+HQFH
WKLVFOLHQWRIButtonGRHVQ¦WKDYHWRZRUU\DERXWSURSHUO\RYHUULGLQJclick7KHKDUG
ZRUNLVDOUHDG\GRQHE\ObservableClicks7KHGHVLUHGEHKDYLRULVFRPSRVHGGHFODUD
WLYHO\ZKHQQHHGHG
/HW¦V ILQLVK RXU H[DPSOH E\ DGGLQJ D VHFRQG WUDLW 7KH -DYD%HDQV VSHFLILFDWLRQ VHH
>-DYD%HDQV6SHF@ KDVWKHLGHDRI£YHWRDEOH¤HYHQWVZKHUHOLVWHQHUVIRUFKDQJHVWRD
-DYD%HDQ FDQ YHWR WKH FKDQJH /HW¦V LPSOHPHQW VRPHWKLQJ VLPLODU ZLWK D WUDLW WKDW
YHWRHVPRUHWKDQDVHWQXPEHURIFOLFNV
// code-examples/Traits/ui2/vetoable-clicks.scala

package ui2
import observer._

trait VetoableClicks extends Clickable {


val maxAllowed = 1 // default
private var count = 0

abstract override def click() = {


if (count < maxAllowed) {
count += 1
super.click()
}
}
}

2QFHDJDLQZHRYHUULGHWKH clickPHWKRG$VEHIRUHWKHRYHUULGHPXVWEHGHFODUHG
abstract7KHPD[LPXPDOORZHGQXPEHURIFOLFNVGHIDXOWVWR<RXPLJKWZRQGHU
ZKDW ZH PHDQ E\ £GHIDXOWV¤ KHUH ,VQ¦W WKH ILHOG GHFODUHG WR EH D val" 7KHUH LV QR
FRQVWUXFWRU GHILQHG WR LQLWLDOL]H LW WR DQRWKHU YDOXH :H¦OO UHYLVLW WKHVH TXHVWLRQV LQ
£2YHUULGLQJ0HPEHUVRI&ODVVHVDQG7UDLWV¤RQSDJH
7KLV WUDLW DOVR GHFODUHV D count YDULDEOH WR NHHS WUDFN RI WKH QXPEHU RI FOLFNV VHHQ
,W LV GHFODUHG private VR LW LV LQYLVLEOH RXWVLGH WKH WUDLW VHH £9LVLELOLW\

84 | Chapter 4:—Traits

Download at WoweBook.Com
5XOHV¤RQSDJH 7KHRYHUULGGHQ clickPHWKRGLQFUHPHQWV count,WRQO\FDOOVWKH
super.click()PHWKRGLIWKHFRXQWLVOHVVWKDQRUHTXDOWRWKHmaxAllowedFRXQW
+HUHLVD6SHFVREMHFWWKDWGHPRQVWUDWHVObservableClicksDQGVetoableClicksZRUNLQJ
WRJHWKHU1RWHWKDWDVHSDUDWH withNH\ZRUGLVUHTXLUHGIRUHDFKWUDLWDVRSSRVHGWR
XVLQJ RQH NH\ZRUG DQG VHSDUDWLQJ WKH QDPHV ZLWK FRPPDV DV -DYD GRHV IRU
implementsFODXVHV
// code-examples/Traits/ui2/button-clickable-observer-vetoable-spec.scala

package ui2
import org.specs._
import observer._
import ui.ButtonCountObserver

object ButtonClickableObserverVetoableSpec extends Specification {


"A Button Observer with Vetoable Clicks" should {
"observe only the first button click" in {
val observableButton =
new Button("Okay") with ObservableClicks with VetoableClicks
val buttonClickCountObserver = new ButtonCountObserver
observableButton.addObserver(buttonClickCountObserver)

for (i <- 1 to 3) observableButton.click()


buttonClickCountObserver.count mustEqual 1
}
}
}

7KHH[SHFWHGREVHUYHUFRXQWLV7KHobservableButtonLVGHFODUHGDVIROORZV
new Button("Okay") with ObservableClicks with VetoableClicks

:HFDQLQIHUWKDWWKHclickRYHUULGHLQVetoableClicksLVFDOOHGEHIRUHWKHclickRYHUULGH
LQ ObservableClicks /RRVHO\ VSHDNLQJ VLQFH RXU DQRQ\PRXV FODVV GRHVQ¦W GHILQH
clickLWVHOIWKHPHWKRGORRNXSSURFHHGVULJKWWROHIWDVGHFODUHG,W¦VDFWXDOO\PRUH
FRPSOLFDWHG WKDQ WKDW DV ZH¦OO VHH ODWHU LQ £/LQHDUL]DWLRQ RI DQ 2EMHFW¦V +LHUDU
FK\¤RQSDJH
,QWKHPHDQWLPHZKDWKDSSHQVLIZHXVHWKHWUDLWVLQWKHUHYHUVHRUGHU"
// code-examples/Traits/ui2/button-vetoable-clickable-observer-spec.scala

package ui2
import org.specs._
import observer._
import ui.ButtonCountObserver

object ButtonVetoableClickableObserverSpec extends Specification {


"A Vetoable Button with Click Observer" should {
"observe all the button clicks, even when some are vetoed" in {
val observableButton =
new Button("Okay") with VetoableClicks with ObservableClicks
val buttonClickCountObserver = new ButtonCountObserver
observableButton.addObserver(buttonClickCountObserver)

Stackable Traits | 85

Download at WoweBook.Com
for (i <- 1 to 3) observableButton.click()
buttonClickCountObserver.count mustEqual 3
}
}
}

1RZ WKH H[SHFWHG REVHUYHU FRXQW LV  ObservableClicks QRZ KDV SUHFHGHQFH RYHU
VetoableClicksVRWKHFRXQWRIFOLFNVLVLQFUHPHQWHGHYHQZKHQVRPHFOLFNVDUHVXE
VHTXHQWO\YHWRHG
6RWKHRUGHURIGHFODUDWLRQPDWWHUVZKLFKLVLPSRUWDQWWRUHPHPEHUIRUSUHYHQWLQJ
XQH[SHFWHGEHKDYLRUZKHQWUDLWVLPSDFWHDFKRWKHU3HUKDSVDQRWKHUOHVVRQWRQRWHLV
WKDWVSOLWWLQJREMHFWVLQWRWRRPDQ\ILQHJUDLQHGWUDLWVFDQREVFXUHWKHRUGHURIH[HFX
WLRQLQ\RXUFRGH
%UHDNLQJ XS \RXU DSSOLFDWLRQ LQWR VPDOO IRFXVHG WUDLWV LV D SRZHUIXO ZD\ WR FUHDWH
UHXVDEOHVFDODEOHDEVWUDFWLRQVDQG£FRPSRQHQWV¤&RPSOH[EHKDYLRUVFDQEHEXLOWXS
WKURXJKGHFODUDWLYHFRPSRVLWLRQRIWUDLWV:HZLOOH[SORUHWKLVLGHDLQJUHDWHUGHWDLOLQ
£6FDODEOH$EVWUDFWLRQV¤RQSDJH

Constructing Traits
7UDLWVGRQ¦WVXSSRUWDX[LOLDU\FRQVWUXFWRUVQRUGRWKH\DFFHSWDQDUJXPHQWOLVWIRUWKH
SULPDU\FRQVWUXFWRUWKHERG\RIDWUDLW7UDLWVFDQH[WHQGFODVVHVRURWKHUWUDLWV+RZ
HYHUWKH\FDQ¦WSDVVDUJXPHQWVWRWKHSDUHQWFODVVFRQVWUXFWRU HYHQOLWHUDOYDOXHV VR
WUDLWVFDQRQO\H[WHQGFODVVHVWKDWKDYHDQRDUJXPHQWSULPDU\RUDX[LOLDU\FRQVWUXFWRU
+RZHYHUOLNHFODVVHVWKHERG\RIDWUDLWLVH[HFXWHGHYHU\WLPHDQLQVWDQFHLVFUHDWHG
WKDWXVHVWKHWUDLWDVGHPRQVWUDWHGE\WKHIROORZLQJVFULSW
// code-examples/Traits/trait-construction-script.scala

trait T1 {
println( " in T1: x = " + x )
val x=1
println( " in T1: x = " + x )
}
trait T2 {
println( " in T2: y = " + y )
val y="T2"
println( " in T2: y = " + y )
}

class Base12 {
println( " in Base12: b = " + b )
val b="Base12"
println( " in Base12: b = " + b )
}
class C12 extends Base12 with T1 with T2 {
println( " in C12: c = " + c )
val c="C12"

86 | Chapter 4:—Traits

Download at WoweBook.Com
println( " in C12: c = " + c )
}
println( "Creating C12:" )
new C12
println( "After Creating C12" )

5XQQLQJWKLVVFULSWZLWKWKHscalaFRPPDQG\LHOGVWKHIROORZLQJRXWSXW
Creating C12:
in Base12: b = null
in Base12: b = Base12
in T1: x = 0
in T1: x = 1
in T2: y = null
in T2: y = T2
in C12: c = null
in C12: c = C12
After Creating C12

1RWLFHWKHRUGHURILQYRFDWLRQRIWKHFODVVDQGWUDLWFRQVWUXFWRUV6LQFHWKHGHFODUDWLRQ
RIC12LVextends Base12 with T1 with T2WKHRUGHURIFRQVWUXFWLRQIRUWKLVVLPSOHFODVV
KLHUDUFK\LVOHIWWRULJKWVWDUWLQJZLWKWKHEDVHFODVV Base12IROORZHGE\WKHWUDLWV T1
DQG T2 DQG HQGLQJ ZLWK WKH C12 FRQVWUXFWRU ERG\ )RU FRQVWUXFWLQJ DUELWUDULO\
FRPSOH[KLHUDUFKLHVVHH£/LQHDUL]DWLRQRIDQ2EMHFW¦V+LHUDUFK\¤RQSDJH
6RZKLOH\RXFDQ¦WSDVVFRQVWUXFWLRQSDUDPHWHUVWRWUDLWV\RXFDQLQLWLDOL]HILHOGVZLWK
GHIDXOWYDOXHVRUOHDYHWKHPDEVWUDFW:HDFWXDOO\VDZWKLVEHIRUHLQRXUSubjectWUDLW
ZKHUHWKHSubject.observersILHOGZDVLQLWLDOL]HGWRDQHPSW\OLVW
,IDFRQFUHWHILHOGLQDWUDLWGRHVQRWKDYHDVXLWDEOHGHIDXOWYDOXHWKHUHLVQR£IDLOVDIH¤
ZD\WRLQLWLDOL]HWKHYDOXH$OOWKHDOWHUQDWLYHDSSURDFKHVUHTXLUHVRPHDGKRFVWHSVE\
XVHUVRIWKHWUDLWZKLFKLVHUURUSURQHEHFDXVHWKH\PLJKWGRLWZURQJRUIRUJHWWRGR
LWDOO3HUKDSVWKHILHOGVKRXOGEHOHIWDEVWUDFWVRWKDWFODVVHVRURWKHUWUDLWVWKDWXVH
WKLVWUDLWDUHIRUFHGWRGHILQHWKHYDOXHDSSURSULDWHO\:H¦OOGLVFXVVRYHUULGLQJDEVWUDFW
DQGFRQFUHWHPHPEHUVLQGHWDLOLQ&KDSWHU
$QRWKHUVROXWLRQLVWRPRYHWKDWILHOGWRDVHSDUDWHFODVVZKHUHWKHFRQVWUXFWLRQSURFHVV
FDQJXDUDQWHHWKDWWKHFRUUHFWLQLWLDOL]DWLRQGDWDLVVXSSOLHGE\WKHXVHU,WPLJKWEH
WKDWWKHZKROHWUDLWVKRXOGDFWXDOO\EHDFODVVLQVWHDGVR\RXFDQGHILQHDFRQVWUXFWRU
IRULWWKDWLQLWLDOL]HVWKHILHOG

Class or Trait?
:KHQFRQVLGHULQJZKHWKHUD£FRQFHSW¤VKRXOGEHDWUDLWRUDFODVVNHHSLQPLQGWKDW
WUDLWVDVPL[LQVPDNHWKHPRVWVHQVHIRU£DGMXQFW¤EHKDYLRU,I\RXILQGWKDWDSDUWLFXODU
WUDLWLVXVHGPRVWRIWHQDVDSDUHQWRIRWKHUFODVVHVVRWKDWWKHFKLOGFODVVHVEHKDYHDV
WKHSDUHQWWUDLWWKHQFRQVLGHUGHILQLQJWKHWUDLWDVDFODVVLQVWHDGWRPDNHWKLVORJLFDO
UHODWLRQVKLSPRUHFOHDU :HVDLGEHKDYHVDVUDWKHUWKDQLVDEHFDXVHWKHIRUPHULVWKH
PRUHSUHFLVHGHILQLWLRQRILQKHULWDQFHEDVHGRQWKH/LVNRY6XEVWLWXWLRQ3ULQFLSOH¢VHH
>0DUWLQ@IRUH[DPSOH

Constructing Traits | 87

Download at WoweBook.Com
$YRLGFRQFUHWHILHOGVLQWUDLWVWKDWFDQ¦WEHLQLWLDOL]HGWRVXLWDEOHGHIDXOW
YDOXHV8VHDEVWUDFWILHOGVLQVWHDGRUFRQYHUWWKHWUDLWWRDFODVVZLWK
D FRQVWUXFWRU 2I FRXUVH VWDWHOHVV WUDLWV GRQ¦W KDYH DQ\ LVVXHV ZLWK
LQLWLDOL]DWLRQ

,W¦VDJHQHUDOSULQFLSOHRIJRRGREMHFWRULHQWHGGHVLJQWKDWDQLQVWDQFHVKRXOGDOZD\V
EHLQDNQRZQYDOLGVWDWHVWDUWLQJIURPWKHPRPHQWWKHFRQVWUXFWLRQSURFHVVILQLVKHV

Recap and What’s Next


,QWKLVFKDSWHUZHOHDUQHGKRZWRXVHWUDLWVWRHQFDSVXODWHDQGVKDUHFURVVFXWWLQJ
FRQFHUQVEHWZHHQFODVVHV:HFRYHUHGZKHQDQGKRZWRXVHWUDLWVKRZWR£VWDFN¤
PXOWLSOHWUDLWVDQGWKHUXOHVIRULQLWLDOL]LQJYDOXHVZLWKLQWUDLWV
,QWKHQH[WFKDSWHUZHH[SORUHKRZWKHIXQGDPHQWDOVRIREMHFWRULHQWHGSURJUDPPLQJ
ZRUNLQ6FDOD(YHQLI\RX¦UHDQROGKDQGDWREMHFWRULHQWHGSURJUDPPLQJ\RX¦OOZDQW
WRUHDGWKHQH[WVHYHUDOFKDSWHUVWRXQGHUVWDQGWKHSDUWLFXODUVRI6FDOD¦VDSSURDFKWR
223

88 | Chapter 4:—Traits

Download at WoweBook.Com
CHAPTER 5
Basic Object-Oriented Programming
in Scala

6FDODLVDQREMHFWRULHQWHGODQJXDJHOLNH-DYD3\WKRQ5XE\6PDOOWDONDQGRWKHUV,I
\RX¦UHFRPLQJIURPWKH-DYDZRUOG\RX¦OOQRWLFHVRPHQRWDEOHLPSURYHPHQWVRYHUWKH
OLPLWDWLRQVRI-DYD¦VREMHFWPRGHO
:HDVVXPH\RXKDYHVRPHSULRUH[SHULHQFHZLWKREMHFWRULHQWHGSURJUDPPLQJ 223 
VRZHZLOOQRWGLVFXVVWKHEDVLFSULQFLSOHVKHUHDOWKRXJKVRPHFRPPRQWHUPVDQG
FRQFHSWVDUHGLVFXVVHGLQWKH*ORVVDU\RQSDJH6HH>0H\HU@IRUDGHWDLOHG
LQWURGXFWLRQWR223VHH>0DUWLQ@IRUDUHFHQWWUHDWPHQWRI223SULQFLSOHVLQWKH
FRQWH[WRI£DJLOHVRIWZDUHGHYHORSPHQW¤VHH>*2)@WROHDUQDERXWGHVLJQSDW
WHUQVDQGVHH>:LUIV%URFN@IRUDGLVFXVVLRQRIREMHFWRULHQWHGGHVLJQFRQFHSWV

Class and Object Basics


/HW¦VUHYLHZWKHWHUPLQRORJ\RI223LQ6FDOD

:H VDZ SUHYLRXVO\ WKDW 6FDOD KDV WKH FRQFHSW RI D GHFODUHG object
ZKLFK ZH¦OO GLJ LQWR LQ £&ODVVHV DQG 2EMHFWV :KHUH $UH WKH 6WDW
LFV"¤RQSDJH:H¦OOXVHWKHWHUPLQVWDQFHWRUHIHUWRDFODVVLQVWDQFH
JHQHULFDOO\PHDQLQJHLWKHUDQobjectRUDQLQVWDQFHRIDclassWRDYRLG
WKHSRWHQWLDOIRUFRQIXVLRQEHWZHHQWKHVHWZRFRQFHSWV

&ODVVHVDUHGHFODUHGZLWKWKHNH\ZRUGclass:HZLOOVHHODWHUWKDWDGGLWLRQDONH\ZRUGV
FDQDOVREHXVHGOLNHfinalWRSUHYHQWFUHDWLRQRIGHULYHGFODVVHVDQGabstractWRLQGL
FDWHWKDWWKHFODVVFDQ¦WEHLQVWDQWLDWHGXVXDOO\EHFDXVHLWFRQWDLQVRULQKHULWVPHPEHU
GHFODUDWLRQVZLWKRXWSURYLGLQJFRQFUHWHGHILQLWLRQVIRUWKHP
$Q LQVWDQFH FDQ UHIHU WR LWVHOI XVLQJ WKH this NH\ZRUG MXVW DV LQ -DYD DQG VLPLODU
ODQJXDJHV

89

Download at WoweBook.Com
)ROORZLQJ6FDOD¦VFRQYHQWLRQZHXVHWKHWHUPPHWKRGIRUDIXQFWLRQWKDWLVWLHGWRDQ
LQVWDQFH 6RPH RWKHU REMHFWRULHQWHG ODQJXDJHV XVH WKH WHUP £PHPEHU IXQFWLRQ¤
0HWKRGGHILQLWLRQVVWDUWZLWKWKHdefNH\ZRUG
/LNH-DYDEXWXQOLNH5XE\DQG3\WKRQ6FDODDOORZVRYHUORDGHGPHWKRGV7ZRRUPRUH
PHWKRGVFDQKDYHWKHVDPHQDPHDVORQJDVWKHLUIXOOVLJQDWXUHVDUHXQLTXH7KHVLJ
QDWXUH LQFOXGHV WKH W\SH QDPH WKH OLVW RI SDUDPHWHUV ZLWK W\SHV DQG WKH PHWKRG¦V
UHWXUQYDOXH
7KHUHLVDQH[FHSWLRQWRWKLVUXOHGXHWRW\SHHUDVXUHZKLFKLVDIHDWXUHRIWKH-90
RQO\EXWLVXVHGE\6FDODRQERWKWKH-90DQG1(7SODWIRUPVWRPLQLPL]HLQFRP
SDWLELOLWLHV6XSSRVHWZRPHWKRGVDUHLGHQWLFDOH[FHSWWKDWRQHWDNHVDSDUDPHWHURI
W\SHList[String]ZKLOHWKHRWKHUWDNHVDSDUDPHWHURIW\SHList[Int]DVIROORZV
// code-examples/BasicOOP/type-erasure-wont-compile.scala
// WON'T COMPILE

object Foo {
def bar(list: List[String]) = list.toString
def bar(list: List[Int]) = list.size.toString
}

<RX¦OOJHWDFRPSLODWLRQHUURURQWKHVHFRQGPHWKRGEHFDXVHWKHWZRPHWKRGVZLOO
KDYHDQLGHQWLFDOVLJQDWXUHDIWHUW\SHHUDVXUH

7KHscalaLQWHUSUHWHUZLOOOHW\RXW\SHLQERWKPHWKRGV,WVLPSO\GURSV
WKHILUVWYHUVLRQ+RZHYHULI\RXWU\WRORDGWKHSUHYLRXVH[DPSOHXVLQJ
WKH:load fileFRPPDQG\RX¦OOJHWWKHVDPHHUURUscalacUDLVHV

:H¦OOGLVFXVVW\SHHUDVXUHLQPRUHGHWDLOLQ&KDSWHU
$OVRE\FRQYHQWLRQZHXVHWKHWHUPILHOGIRUDYDULDEOHWKDWLVWLHGWRDQLQVWDQFH7KH
WHUPDWWULEXWHLVRIWHQXVHGLQRWKHUODQJXDJHV OLNH5XE\ 1RWHWKDWWKHVWDWHRIDQ
LQVWDQFHLVWKHXQLRQRIDOOWKHYDOXHVFXUUHQWO\UHSUHVHQWHGE\WKHLQVWDQFH¦VILHOGV
$VZHGLVFXVVHGLQ£9DULDEOH'HFODUDWLRQV¤RQSDJHUHDGRQO\ £YDOXH¤ ILHOGVDUH
GHFODUHG XVLQJ WKH val NH\ZRUG DQG UHDGZULWH ILHOGV DUH GHFODUHG XVLQJ WKH var
NH\ZRUG
6FDODDOVRDOORZVW\SHVWREHGHFODUHGLQFODVVHVDVZHVDZLQ£$EVWUDFW7\SHV$QG
3DUDPHWHUL]HG7\SHV¤RQSDJH
:HXVHWKHWHUPPHPEHUWRUHIHUWRDILHOGPHWKRGRUW\SHLQDJHQHULFZD\1RWHWKDW
ILHOGDQGPHWKRGPHPEHUV EXWQRWW\SHPHPEHUV VKDUHWKHVDPHQDPHVSDFHXQOLNH
-DYD :H¦OO GLVFXVV WKLV PRUH LQ £:KHQ $FFHVVRU 0HWKRGV DQG )LHOGV $UH ,QGLVWLQ
JXLVKDEOH7KH8QLIRUP$FFHVV3ULQFLSOH¤RQSDJH
)LQDOO\QHZLQVWDQFHVRIUHIHUHQFHW\SHVDUHFUHDWHGIURPDFODVVXVLQJWKHnewNH\ZRUG
DVLQODQJXDJHVOLNH-DYDDQG&1RWHWKDW\RXFDQGURSWKHSDUHQWKHVHVZKHQXVLQJ
DGHIDXOWFRQVWUXFWRU LHRQHWKDWWDNHVQRDUJXPHQWV ,QVRPHFDVHVOLWHUDOYDOXHV

90 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
FDQEHXVHGLQVWHDGHJval name = "Programming Scala"LVHTXLYDOHQWWRval name =
new String("Programming Scala")
,QVWDQFHVRIYDOXHW\SHV IntDoubleHWF ZKLFKFRUUHVSRQGWRWKHSULPLWLYHVLQODQ
JXDJHVOLNH-DYDDUHDOZD\VFUHDWHGXVLQJOLWHUDOYDOXHVHJ13.14,QIDFWWKHUHDUH
QRSXEOLFFRQVWUXFWRUVIRUWKHVHW\SHVVRDQH[SUHVVLRQOLNHval i = new Int(1)ZRQ¦W
FRPSLOH
:H¦OO GLVFXVV WKH GLIIHUHQFH EHWZHHQ UHIHUHQFH DQG YDOXH W\SHV LQ £7KH 6FDOD 7\SH
+LHUDUFK\¤RQSDJH

Parent Classes
6FDODVXSSRUWVVLQJOHLQKHULWDQFHQRWPXOWLSOHLQKHULWDQFH$FKLOG RUGHULYHG FODVV
FDQKDYHRQHDQGRQO\RQHSDUHQW RUEDVH FODVV7KHVROHH[FHSWLRQLVWKHURRWRIWKH
6FDODFODVVKLHUDUFK\AnyZKLFKKDVQRSDUHQW
:H¦YHVHHQVHYHUDOH[DPSOHVRISDUHQWDQGFKLOGFODVVHV+HUHDUHVQLSSHWVRIRQHRI
WKHILUVWZHVDZLQ£$EVWUDFW7\SHV$QG3DUDPHWHUL]HG7\SHV¤RQSDJH
// code-examples/TypeLessDoMore/abstract-types-script.scala

import java.io._

abstract class BulkReader {


// ...
}

class StringBulkReader(val source: String) extends BulkReader {


// ...
}

class FileBulkReader(val source: File) extends BulkReader {


// ...
}

$VLQ-DYDWKHNH\ZRUGextendsLQGLFDWHVWKHSDUHQWFODVVLQWKLVFDVHBulkReader,Q
6FDODextendsLVDOVRXVHGZKHQDFODVVLQKHULWVDWUDLWDVLWVSDUHQW HYHQZKHQLWPL[HV
LQRWKHUWUDLWVXVLQJWKHwithNH\ZRUG $OVRextendsLVXVHGZKHQRQHWUDLWLVWKHFKLOG
RIDQRWKHUWUDLWRUFODVV<HVWUDLWVFDQLQKHULWFODVVHV
,I\RXGRQ¦W extendDSDUHQWFODVVWKHGHIDXOWSDUHQWLV AnyRefDGLUHFWFKLOGFODVVRI
Any :HGLVFXVVWKHGLIIHUHQFHEHWZHHQAnyDQGAnyRefZKHQZHGLVFXVVWKH6FDODW\SH
KLHUDUFK\LQ£7KH6FDOD7\SH+LHUDUFK\¤RQSDJH

Constructors in Scala
6FDODGLVWLQJXLVKHVEHWZHHQDSULPDU\FRQVWUXFWRUDQG]HURRUPRUHDX[LOLDU\FRQVWUXF
WRUV,Q6FDODWKHSULPDU\FRQVWUXFWRULVWKHHQWLUHERG\RIWKHFODVV$Q\SDUDPHWHUV

Constructors in Scala | 91

Download at WoweBook.Com
WKDWWKHFRQVWUXFWRUUHTXLUHVDUHOLVWHGDIWHUWKHFODVVQDPH:H¦YHVHHQPDQ\H[DPSOHV
RIWKLVDOUHDG\DVLQWKHButtonWithCallbacksH[DPSOHZHXVHGLQ&KDSWHU
// code-examples/Traits/ui/button-callbacks.scala

package ui

class ButtonWithCallbacks(val label: String,


val clickedCallbacks: List[() => Unit]) extends Widget {

require(clickedCallbacks != null, "Callback list can't be null!")

def this(label: String, clickedCallback: () => Unit) =


this(label, List(clickedCallback))

def this(label: String) = {


this(label, Nil)
println("Warning: button has no click callbacks!")
}

def click() = {
// ... logic to give the appearance of clicking a physical button ...
clickedCallbacks.foreach(f => f())
}
}

7KHButtonWithCallbacksFODVVUHSUHVHQWVDEXWWRQRQDJUDSKLFDOXVHULQWHUIDFH,WKDV
DODEHODQGDOLVWRIFDOOEDFNIXQFWLRQVWKDWDUHLQYRNHGLIWKHEXWWRQLVFOLFNHG(DFK
FDOOEDFN IXQFWLRQ WDNHV QR DUJXPHQWV DQG UHWXUQV Unit 7KH click PHWKRG LWHUDWHV
WKURXJKWKHOLVWRIFDOOEDFNVDQGLQYRNHVHDFKRQH
ButtonWithCallbacksGHILQHVWKUHHFRQVWUXFWRUV7KHSULPDU\FRQVWUXFWRUZKLFKLVWKH
ERG\RIWKHHQWLUHFODVVKDVDSDUDPHWHUOLVWWKDWWDNHVDODEHOVWULQJDQGDOLVWRIFDOOEDFN
IXQFWLRQV%HFDXVHHDFKSDUDPHWHULVGHFODUHGDVDvalWKHFRPSLOHUJHQHUDWHVDSULYDWH
ILHOGFRUUHVSRQGLQJWRHDFKSDUDPHWHU DGLIIHUHQWLQWHUQDOQDPHLVXVHG DORQJZLWKD
SXEOLFUHDGHUPHWKRGWKDWKDVWKHVDPHQDPHDVWKHSDUDPHWHU£3ULYDWH¤DQG£SXEOLF¤
KDYHWKHVDPHPHDQLQJKHUHDVLQPRVWREMHFWRULHQWHGODQJXDJHV:H¦OOGLVFXVVWKH
YDULRXV YLVLELOLW\ UXOHV DQG WKH NH\ZRUGV WKDW FRQWURO WKHP LQ £9LVLELOLW\
5XOHV¤RQSDJH
,IDSDUDPHWHUKDVWKHvarNH\ZRUGDSXEOLFZULWHUPHWKRGLVDOVRJHQHUDWHGZLWKWKH
SDUDPHWHU¦VQDPHDVDSUHIL[IROORZHGE\_=)RUH[DPSOHLIlabelZHUHGHFODUHGDVD
varWKHZULWHUPHWKRGZRXOGEHQDPHGlabel_=DQGLWZRXOGWDNHDVLQJOHDUJXPHQW
RIW\SHString
7KHUHDUHWLPHVZKHQ\RXGRQ¦WZDQWWKHDFFHVVRUPHWKRGVWREHJHQHUDWHGDXWRPDW
LFDOO\,QRWKHUZRUGV\RXZDQWWKHILHOGWREHSULYDWH$GGWKHprivateNH\ZRUGEHIRUH
WKHvalRUvarNH\ZRUGDQGWKHDFFHVVRUPHWKRGVZRQ¦WEHJHQHUDWHG 6HH£9LVLELOLW\
5XOHV¤RQSDJHIRUPRUHGHWDLOV

92 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
)RU\RX-DYDSURJUDPPHUV6FDODGRHVQ¦WIROORZWKH-DYD%HDQV>-DYD
%HDQV6SHF@FRQYHQWLRQWKDWILHOGUHDGHUDQGZULWHUPHWKRGVEHJLQZLWK
getDQGsetUHVSHFWLYHO\IROORZHGE\WKHILHOGQDPHZLWKWKHILUVWFKDU
DFWHUFDSLWDOL]HG:H¦OOVHHZK\ZKHQZHGLVFXVVWKH8QLIRUP$FFHVV
3ULQFLSOHLQ£:KHQ$FFHVVRU0HWKRGVDQG)LHOGV$UH,QGLVWLQJXLVKDEOH
7KH 8QLIRUP $FFHVV 3ULQFLSOH¤ RQ SDJH  +RZHYHU \RX FDQ JHW
-DYD%HDQVVW\OH JHWWHUV DQG VHWWHUV ZKHQ \RX QHHG WKHP XVLQJ WKH
scala.reflect.BeanPropertyDQQRWDWLRQDVZH¦OOGLVFXVVLQ£-DYD%HDQ
3URSHUWLHV¤RQSDJH

:KHQDQLQVWDQFHRIWKHFODVVLVFUHDWHGHDFKILHOGFRUUHVSRQGLQJWRDSDUDPHWHULQWKH
SDUDPHWHUOLVWZLOOEHLQLWLDOL]HGZLWKWKHSDUDPHWHUDXWRPDWLFDOO\1RFRQVWUXFWRUORJLF
LVUHTXLUHGWRLQLWLDOL]HWKHVHILHOGVLQFRQWUDVWWRPRVWRWKHUREMHFWRULHQWHGODQJXDJHV
7KHILUVWVWDWHPHQWLQWKHButtonWithCallbacksFODVV LHWKHFRQVWUXFWRU ERG\LVDWHVW
WRHQVXUHWKDWDQRQnullOLVWKDVEHHQSDVVHGWRWKHFRQVWUXFWRU ,WGRHVDOORZDQHPSW\
NilOLVWKRZHYHU ,WXVHVWKHFRQYHQLHQWrequireIXQFWLRQWKDWLVLPSRUWHGDXWRPDWL
FDOO\LQWRWKHFXUUHQWVFRSH DVZH¦OOGLVFXVVLQ£7KH3UHGHI2EMHFW¤RQSDJH ,I
WKHOLVWLVQXOOrequireZLOOWKURZDQH[FHSWLRQ7KHrequireIXQFWLRQDQGLWVFRPSDQLRQ
assumeDUHYHU\XVHIXOIRU 'HVLJQE\&RQWUDFWSURJUDPPLQJDVGLVFXVVHGLQ £%HWWHU
'HVLJQZLWK'HVLJQ%\&RQWUDFW¤RQSDJH
+HUH LV SDUW RI D IXOO VSHFLILFDWLRQ IRU ButtonWithCallbacks WKDW GHPRQVWUDWHV WKH
requireVWDWHPHQWLQXVH
// code-examples/Traits/ui/button-callbacks-spec.scala
package ui
import org.specs._

object ButtonWithCallbacksSpec extends Specification {


"A ButtonWithCallbacks" should {
// ...
"not be constructable with a null callback list" in {
val nullList:List[() => Unit] = null
val errorMessage =
"requirement failed: Callback list can't be null!"
(new ButtonWithCallbacks("button1", nullList)) must throwA(
new IllegalArgumentException(errorMessage))
}
}
}

6FDODHYHQPDNHVLWGLIILFXOWWRSDVVnullDVWKHVHFRQGSDUDPHWHUWRWKHFRQVWUXFWRULW
ZRQ¦WW\SHFKHFNZKHQ\RXFRPSLOHLW+RZHYHU\RXFDQDVVLJQ nullWRDYDOXHDV
VKRZQ ,I ZH GLGQ¦W KDYH WKH must throwA(...) FODXVH ZH ZRXOG VHH WKH IROORZLQJ
H[FHSWLRQWKURZQ
java.lang.IllegalArgumentException: requirement failed: Callback list can't be null!
at scala.Predef$.require(Predef.scala:112)
at ui.ButtonWithCallbacks.<init>(button-callbacks.scala:7)
...

Constructors in Scala | 93

Download at WoweBook.Com
ButtonWithCallbacksGHILQHVWZRDX[LOLDU\FRQVWUXFWRUVIRUWKHXVHU¦VFRQYHQLHQFH7KH
ILUVW DX[LOLDU\ FRQVWUXFWRU DFFHSWV D ODEHO DQG D VLQJOH FDOOEDFN ,W FDOOV WKH SULPDU\
FRQVWUXFWRUSDVVLQJWKHODEHODQGDQHZListWRZUDSWKHVLQJOHFDOOEDFN
7KHVHFRQGDX[LOLDU\FRQVWUXFWRUDFFHSWVMXVWDODEHO,WFDOOVWKHSULPDU\FRQVWUXFWRU
ZLWKNil ZKLFKUHSUHVHQWVDQHPSW\ListREMHFW 7KHFRQVWUXFWRUWKHQSULQWVDZDUQ
LQJPHVVDJHWKDWWKHUHDUHQRFDOOEDFNVVLQFHOLVWVDUHLPPXWDEOHDQGWKHUHLVQRZD\
WRUHSODFHWKHFDOOEDFNOLVWvalZLWKDQHZRQH
7RDYRLGLQILQLWHUHFXUVLRQ6FDODUHTXLUHVHDFKDX[LOLDU\FRQVWUXFWRUWRLQYRNHDQRWKHU
FRQVWUXFWRUGHILQHGEHIRUHLW VHH>6FDOD6SHF@ 7KHFRQVWUXFWRULQYRNHGPD\EH
HLWKHUDQRWKHUDX[LOLDU\FRQVWUXFWRURUWKHSULPDU\FRQVWUXFWRUDQGLWPXVWEHWKHILUVW
VWDWHPHQWLQWKHDX[LOLDU\FRQVWUXFWRU¦VERG\$GGLWLRQDOSURFHVVLQJFDQRFFXUDIWHU
WKLVFDOOVXFKDVWKHZDUQLQJPHVVDJHSULQWHGLQRXUH[DPSOH

%HFDXVHDOODX[LOLDU\FRQVWUXFWRUVHYHQWXDOO\LQYRNHWKHSULPDU\FRQ
VWUXFWRUORJLFFKHFNVDQGRWKHULQLWLDOL]DWLRQVGRQHLQWKHERG\ZLOOEH
SHUIRUPHGFRQVLVWHQWO\IRUDOOLQVWDQFHVFUHDWHG

7KHUHDUHDIHZDGYDQWDJHVRI6FDOD¦VFRQVWUDLQWVRQFRQVWUXFWRUV
(OLPLQDWLRQRIGXSOLFDWLRQ
%HFDXVHDX[LOLDU\FRQVWUXFWRUVLQYRNHWKHSULPDU\FRQVWUXFWRUSRWHQWLDOGXSOLFD
WLRQRIFRQVWUXFWLRQORJLFLVODUJHO\HOLPLQDWHG
&RGHVL]HUHGXFWLRQ
$VVKRZQLQWKHH[DPSOHVZKHQRQHRUPRUHRIWKHSULPDU\FRQVWUXFWRUSDUDP
HWHUVLVGHFODUHGDVDvalRUDvar6FDODDXWRPDWLFDOO\JHQHUDWHVDILHOGWKHDSSUR
SULDWHDFFHVVRUPHWKRGV XQOHVVWKH\DUHGHFODUHG private DQGWKHLQLWLDOL]DWLRQ
ORJLFIRUZKHQLQVWDQFHVDUHFUHDWHG
7KHUHLVDOVRDWOHDVWRQHGLVDGYDQWDJHRI6FDOD¦VFRQVWUDLQWVRQFRQVWUXFWRUV
/HVVIOH[LELOLW\
6RPHWLPHVLW¦VMXVWQRWFRQYHQLHQWWRKDYHRQHFRQVWUXFWRUERG\WKDWDOOFRQVWUXF
WRUVDUHIRUFHGWRXVH+RZHYHUZHILQGWKHVHFLUFXPVWDQFHVWREHUDUH,QVXFK
FDVHVLWPD\VLPSO\EHWKDWWKHFODVVKDVWRRPDQ\UHVSRQVLELOLWLHVDQGLWVKRXOG
EHUHIDFWRUHGLQWRVPDOOHUFODVVHV

Calling Parent Class Constructors


7KHSULPDU\FRQVWUXFWRULQDGHULYHGFODVVPXVWLQYRNHRQHRIWKHSDUHQWFODVVFRQ
VWUXFWRUVHLWKHUWKHSULPDU\FRQVWUXFWRURUDQDX[LOLDU\FRQVWUXFWRU,QWKHIROORZLQJ
H[DPSOHDFODVVGHULYHGIURPButtonWithCallbacksFDOOHGRadioButtonWithCallbacks
LQYRNHVWKHSULPDU\ ButtonWithCallbacksFRQVWUXFWRU£5DGLR¤EXWWRQVFDQEHHLWKHU
RQRURII

94 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
// code-examples/BasicOOP/ui/radio-button-callbacks.scala

package ui

/**
* Button with two states, on or off, like an old-style,
* channel-selection button on a radio.
*/
class RadioButtonWithCallbacks(
var on: Boolean, label: String, clickedCallbacks: List[() => Unit])
extends ButtonWithCallbacks(label, clickedCallbacks) {

def this(on: Boolean, label: String, clickedCallback: () => Unit) =


this(on, label, List(clickedCallback))

def this(on: Boolean, label: String) = this(on, label, Nil)


}

7KHSULPDU\FRQVWUXFWRUIRU RadioButtonWithCallbacksWDNHVWKUHHSDUDPHWHUVDQ on
VWDWH trueRUfalse DODEHODQGDOLVWRIFDOOEDFNV,WSDVVHVWKHODEHODQGOLVWRIFDOOEDFNV
WRLWVSDUHQWFODVVButtonWithCallbacks7KHonSDUDPHWHULVGHFODUHGDVDvarVRLWLV
PXWDEOHonLVDOVRWKHRQHFRQVWUXFWRUSDUDPHWHUXQLTXHWRDUDGLREXWWRQVRLWLVNHSW
DVDQDWWULEXWHRIRadioButtonWithCallbacks
)RUFRQVLVWHQF\ZLWKLWVSDUHQWFODVVRadioButtonWithCallbacksDOVRGHFODUHVWZRDX[
LOLDU\FRQVWUXFWRUV1RWHWKDWWKH\PXVWLQYRNHDSUHFHGLQJFRQVWUXFWRULQRadioButton
WithCallbacksDVEHIRUH7KH\FDQ¦WLQYRNHDButtonWithCallbacksFRQVWUXFWRUGLUHFWO\
'HFODULQJDOOWKHVHFRQVWUXFWRUVLQHDFKFODVVFRXOGJHWWHGLRXVDIWHUDZKLOHEXWZH
H[SORUHGWHFKQLTXHVLQ&KDSWHUWKDWFDQHOLPLQDWHUHSHWLWLRQ

:KLOHsuperLVXVHGWRLQYRNHRYHUULGGHQPHWKRGVDVLQ-DYDLWFDQQRW
EHXVHGWRLQYRNHDVXSHUFODVVFRQVWUXFWRU

Nested Classes
6FDODOHWV\RXQHVWFODVVGHFODUDWLRQVOLNHPDQ\REMHFWRULHQWHGODQJXDJHV6XSSRVHZH
ZDQWDOO WidgetsWRKDYHDPDSRISURSHUWLHV7KHVHSURSHUWLHVFRXOGEHVL]HFRORU
ZKHWKHU RU QRW WKH ZLGJHW LV YLVLEOH HWF :H PLJKW XVH D VLPSOH map WR KROG WKH
SURSHUWLHVEXWOHW¦VDVVXPHWKDWZHDOVRZDQWWRFRQWURODFFHVVWRWKHSURSHUWLHVDQG
WRSHUIRUPRWKHURSHUDWLRQVZKHQWKH\FKDQJH
+HUHLVRQHZD\ZHPLJKWH[SDQGRXURULJLQDO WidgetH[DPSOHIURP£7UDLWV$V0L[
LQV¤RQSDJHWRDGGWKLVIHDWXUH
// code-examples/BasicOOP/ui/widget.scala

package ui

Nested Classes | 95

Download at WoweBook.Com
abstract class Widget {
class Properties {
import scala.collection.immutable.HashMap

private var values: Map[String, Any] = new HashMap

def size = values.size

def get(key: String) = values.get(key)

def update(key: String, value: Any) = {


// Do some preprocessing, e.g., filtering.
values = values.update(key, value)
// Do some postprocessing.
}
}

val properties = new Properties


}

:HDGGHGD PropertiesFODVVWKDWKDVDSULYDWHPXWDEOHUHIHUHQFHWRDQLPPXWDEOH
HashMap:HDOVRDGGHGWKUHHSXEOLFPHWKRGVWKDWUHWULHYHWKHVL]H LHWKHQXPEHURI
SURSHUWLHVGHILQHG UHWULHYHDVLQJOHHOHPHQWLQWKHPDSDQGXSGDWHWKHPDSZLWKD
QHZHOHPHQWUHVSHFWLYHO\:HPLJKWQHHGWRGRDGGLWLRQDOZRUNLQWKHupdatePHWKRG
DQGZH¦YHLQGLFDWHGDVPXFKZLWKFRPPHQWV

<RXFDQVHHIURPWKHSUHYLRXVH[DPSOHWKDW6FDODDOORZVFODVVHVWREH
GHFODUHG LQVLGH RQH DQRWKHU RU £QHVWHG¤ $ QHVWHG FODVV PDNH VHQVH
ZKHQ\RXKDYHHQRXJKUHODWHGIXQFWLRQDOLW\WROXPSWRJHWKHULQDFODVV
EXWWKHIXQFWLRQDOLW\LVRQO\HYHUJRLQJWREHXVHGE\LWV£RXWHU¤FODVV

6RIDUZH¦YHFRYHUHGKRZWRGHFODUHFODVVHVKRZWRLQVWDQWLDWHWKHPDQGVRPHRIWKH
EDVLFVRILQKHULWDQFH,QWKHQH[WVHFWLRQZH¦OOGLVFXVVYLVLELOLW\UXOHVZLWKLQFODVVHVDQG
REMHFWV

Visibility Rules
)RUFRQYHQLHQFHZH¦OOXVHWKHZRUG£W\SH¤LQWKLVVHFWLRQWRUHIHUWR
FODVVHVDQGWUDLWVJHQHULFDOO\DVRSSRVHGWRUHIHUULQJWRPHPEHU type
GHFODUDWLRQV :H¦OO LQFOXGH WKRVH ZKHQ ZH XVH WKH WHUP £PHPEHU¤
JHQHULFDOO\XQOHVVRWKHUZLVHLQGLFDWHG

0RVWREMHFWRULHQWHGODQJXDJHVKDYHFRQVWUXFWVWRFRQVWUDLQWKHYLVLELOLW\ RUVFRSH RI


W\SHDQGW\SHPHPEHUGHFODUDWLRQV7KHVHFRQVWUXFWVVXSSRUWWKHREMHFWRULHQWHGIRUP
RIHQFDSVXODWLRQZKHUHRQO\WKHHVVHQWLDOSXEOLFDEVWUDFWLRQRIDFODVVRUWUDLWLVH[SRVHG
DQGLPSOHPHQWDWLRQLQIRUPDWLRQLVKLGGHQIURPYLHZ

96 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
<RX¦OOZDQWWRXVHSXEOLFYLVLELOLW\IRUDQ\WKLQJWKDWXVHUVRI\RXUFODVVHVDQGREMHFWV
VKRXOGVHHDQGXVH.HHSLQPLQGWKDWWKHVHWRISXEOLFO\YLVLEOHPHPEHUVIRUPWKH
DEVWUDFWLRQH[SRVHGE\WKHW\SHDORQJZLWKWKHW\SH¦VQDPHLWVHOI
7KHFRQYHQWLRQDOZLVGRPLQREMHFWRULHQWHGGHVLJQLVWKDWILHOGVVKRXOGEHSULYDWHRU
SURWHFWHG,IDFFHVVLVUHTXLUHGLWVKRXOGKDSSHQWKURXJKPHWKRGVEXWQRWHYHU\WKLQJ
VKRXOGEHDFFHVVLEOHE\GHIDXOW7KHYLUWXHRIWKH8QLIRUP$FFHVV3ULQFLSOH VHH£:KHQ
$FFHVVRU 0HWKRGV DQG )LHOGV $UH ,QGLVWLQJXLVKDEOH 7KH 8QLIRUP $FFHVV 3ULQFL
SOH¤RQSDJH LVWKDWZHFDQJLYHWKHXVHUWKHVHPDQWLFVRISXEOLFILHOGDFFHVVYLD
HLWKHUDPHWKRGRUGLUHFWDFFHVVWRDILHOGZKLFKHYHULVDSSURSULDWHIRUWKHWDVN

7KHDUWRIJRRGREMHFWRULHQWHGGHVLJQLQFOXGHVGHILQLQJPLQLPDOFOHDU
DQGFRKHVLYHSXEOLFDEVWUDFWLRQV

7KHUH DUH WZR NLQGV RI £XVHUV¤ RI D W\SH GHULYHG W\SHV DQG FRGH WKDW ZRUNV ZLWK
LQVWDQFHVRIWKHW\SH'HULYHGW\SHVXVXDOO\QHHGPRUHDFFHVVWRWKHPHPEHUVRIWKHLU
SDUHQWW\SHVWKDQXVHUVRILQVWDQFHVGR
6FDOD¦VYLVLELOLW\UXOHVDUHVLPLODUWR-DYD¦VEXWWHQGWREHERWKPRUHFRQVLVWHQWO\DSSOLHG
DQGPRUHIOH[LEOH)RUH[DPSOHLQ-DYDLIDQLQQHUFODVVKDVD privatePHPEHUWKH
HQFORVLQJFODVVFDQVHHLW,Q6FDODWKHHQFORVLQJFODVVFDQ¦WVHHDprivatePHPEHUEXW
6FDODSURYLGHVDQRWKHUZD\WRGHFODUHLWYLVLEOHWRWKHHQFORVLQJFODVV
$V LQ -DYD DQG & WKH NH\ZRUGV WKDW PRGLI\ YLVLELOLW\ VXFK DV private DQG
protectedDSSHDUDWWKHEHJLQQLQJRIGHFODUDWLRQV<RX¦OOILQGWKHPEHIRUHWKH class
RU traitNH\ZRUGVIRUW\SHVEHIRUHWKH valRU varIRUILHOGVDQGEHIRUHWKH defIRU
PHWKRGV

<RXFDQDOVRXVHDQDFFHVVPRGLILHUNH\ZRUGRQWKHSULPDU\FRQVWUXFWRU
RIDFODVV3XWLWDIWHUWKHW\SHQDPHDQGW\SHSDUDPHWHUVLIDQ\DQG
EHIRUH WKH DUJXPHQW OLVW DV LQ WKLV H[DPSOH class Restricted[+A]
private (name: String) {...}

7DEOHVXPPDUL]HVWKHYLVLELOLW\VFRSHV
7DEOH9LVLELOLW\VFRSHV
Name Keyword Description
public none Public members and types are visible everywhere, across all boundaries.
protected protected Protected members are visible to the defining type, to derived types, and to
nested types. Protected types are visible only within the same package and
subpackages.

Visibility Rules | 97

Download at WoweBook.Com
Name Keyword Description
private private Private members are visible only within the defining type and nested types.
Private types are visible only within the same package.
scoped protected protected[scope] Visibility is limited to scope, which can be a package, type, or this (meaning
the same instance, when applied to members, or the enclosing package, when
applied to types). See the text below for details.
scoped private private[scope] Synonymous with scoped protected visibility, except under inheritance (dis-
cussed below).

/HW¦VH[SORUHWKHVHYLVLELOLW\RSWLRQVLQPRUHGHWDLO7RNHHSWKLQJVVLPSOHZH¦OOXVH
ILHOGVIRUPHPEHUH[DPSOHV0HWKRGDQGW\SHGHFODUDWLRQVEHKDYHWKHVDPHZD\

8QIRUWXQDWHO\\RXFDQ¦WDSSO\DQ\RIWKHYLVLELOLW\PRGLILHUVWRSDFN
DJHV7KHUHIRUHDSDFNDJHLVDOZD\VSXEOLFHYHQZKHQLWFRQWDLQVQR
SXEOLFO\YLVLEOHW\SHV

Public Visibility
$Q\GHFODUDWLRQZLWKRXWDYLVLELOLW\NH\ZRUGLV£SXEOLF¤PHDQLQJLWLVYLVLEOHHYHU\
ZKHUH7KHUHLVQRpublicNH\ZRUGLQ6FDOD7KLVLVLQFRQWUDVWWR-DYDZKLFKGHIDXOWV
WRSXEOLFYLVLELOLW\RQO\ZLWKLQWKHHQFORVLQJSDFNDJH LH£SDFNDJHSULYDWH¤ 2WKHU
REMHFWRULHQWHGODQJXDJHVOLNH5XE\DOVRGHIDXOWWRSXEOLFYLVLELOLW\
// code-examples/BasicOOP/scoping/public.scala

package scopeA {
class PublicClass1 {
val publicField = 1

class Nested {
val nestedField = 1
}

val nested = new Nested


}

class PublicClass2 extends PublicClass1 {


val field2 = publicField + 1
val nField2 = new Nested().nestedField
}
}

package scopeB {
class PublicClass1B extends scopeA.PublicClass1

class UsingClass(val publicClass: scopeA.PublicClass1) {


def method = "UsingClass:" +
" field: " + publicClass.publicField +

98 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
" nested field: " + publicClass.nested.nestedField
}
}

<RXFDQFRPSLOHWKLVILOHZLWKscalac,WVKRXOGFRPSLOHZLWKRXWHUURU
(YHU\WKLQJLVSXEOLFLQWKHVHSDFNDJHVDQGFODVVHV1RWHWKDW scopeB.UsingClassFDQ
DFFHVVscopeA.PublicClass1DQGLWVPHPEHUVLQFOXGLQJWKHLQVWDQFHRINestedDQGLWV
SXEOLFILHOG

Protected Visibility
3URWHFWHGYLVLELOLW\LVIRUWKHEHQHILWRILPSOHPHQWHUVRIGHULYHGW\SHVZKRQHHGDOLWWOH
PRUH DFFHVV WR WKH GHWDLOV RI WKHLU SDUHQW W\SHV $Q\ PHPEHU GHFODUHG ZLWK WKH
protectedNH\ZRUGLVYLVLEOHRQO\WRWKHGHILQLQJW\SHLQFOXGLQJRWKHULQVWDQFHVRIWKH
VDPHW\SHDQGDQ\GHULYHGW\SHV:KHQDSSOLHGWRDW\SHprotectedOLPLWVYLVLELOLW\WR
WKHHQFORVLQJSDFNDJH
-DYDLQFRQWUDVWPDNHVSURWHFWHGPHPEHUVYLVLEOHWKURXJKRXWWKHHQFORVLQJSDFNDJH
6FDODKDQGOHVWKLVFDVHZLWKVFRSHGSULYDWHDQGSURWHFWHGDFFHVV
// code-examples/BasicOOP/scoping/protected-wont-compile.scala
// WON'T COMPILE

package scopeA {
class ProtectedClass1(protected val protectedField1: Int) {
protected val protectedField2 = 1

def equalFields(other: ProtectedClass1) =


(protectedField1 == other.protectedField1) &&
(protectedField1 == other.protectedField1) &&
(nested == other.nested)

class Nested {
protected val nestedField = 1
}

protected val nested = new Nested


}

class ProtectedClass2 extends ProtectedClass1(1) {


val field1 = protectedField1
val field2 = protectedField2
val nField = new Nested().nestedField // ERROR
}

class ProtectedClass3 {
val protectedClass1 = new ProtectedClass1(1)
val protectedField1 = protectedClass1.protectedField1 // ERROR
val protectedField2 = protectedClass1.protectedField2 // ERROR
val protectedNField = protectedClass1.nested.nestedField // ERROR
}

Visibility Rules | 99

Download at WoweBook.Com
protected class ProtectedClass4

class ProtectedClass5 extends ProtectedClass4


protected class ProtectedClass6 extends ProtectedClass4
}

package scopeB {
class ProtectedClass4B extends scopeA.ProtectedClass4 // ERROR
}

:KHQ\RXFRPSLOHWKLVILOHZLWKscalac\RXJHWWKHIROORZLQJRXWSXW 7KHILOHQDPHV
EHIRUHWKHN:OLQHQXPEHUVKDYHEHHQUHPRYHGIURPWKHRXWSXWWREHWWHUILWWKHVSDFH
16: error: value nestedField cannot be accessed in ProtectedClass2.this.Nested
val nField = new Nested().nestedField
^
20: error: value protectedField1 cannot be accessed in scopeA.ProtectedClass1
val protectedField1 = protectedClass1.protectedField1
^
21: error: value protectedField2 cannot be accessed in scopeA.ProtectedClass1
val protectedField2 = protectedClass1.protectedField2
^
22: error: value nested cannot be accessed in scopeA.ProtectedClass1
val protectedNField = protectedClass1.nested.nestedField
^
32: error: class ProtectedClass4 cannot be accessed in package scopeA
class ProtectedClass4B extends scopeA.ProtectedClass4
^
5 errors found

7KH// ERRORFRPPHQWVLQWKHOLVWLQJPDUNWKHOLQHVWKDWIDLOWRSDUVH
ProtectedClass2 FDQ DFFHVV SURWHFWHG PHPEHUV RI ProtectedClass1 VLQFH LW GHULYHV
IURP LW +RZHYHU LW FDQ¦W DFFHVV WKH SURWHFWHG nestedField LQ protectedClass1.nes
ted $OVR ProtectedClass3 FDQ¦W DFFHVV SURWHFWHG PHPEHUV RI WKH ProtectedClass1
LQVWDQFHLWXVHV
)LQDOO\EHFDXVH ProtectedClass4LVGHFODUHG protectedLWLVQRWYLVLEOHLQWKH scopeB
SDFNDJH

Private Visibility
3ULYDWHYLVLELOLW\FRPSOHWHO\KLGHVLPSOHPHQWDWLRQGHWDLOVHYHQIURPWKHLPSOHPHQWHUV
RIGHULYHGFODVVHV$Q\PHPEHUGHFODUHGZLWKWKH privateNH\ZRUGLVYLVLEOHRQO\WR
WKHGHILQLQJW\SHLQFOXGLQJRWKHULQVWDQFHVRIWKHVDPHW\SH:KHQDSSOLHGWRDW\SH
privateOLPLWVYLVLELOLW\WRWKHHQFORVLQJSDFNDJH
// code-examples/BasicOOP/scoping/private-wont-compile.scala
// WON'T COMPILE

package scopeA {
class PrivateClass1(private val privateField1: Int) {
private val privateField2 = 1

100 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
def equalFields(other: PrivateClass1) =
(privateField1 == other.privateField1) &&
(privateField2 == other.privateField2) &&
(nested == other.nested)

class Nested {
private val nestedField = 1
}

private val nested = new Nested


}

class PrivateClass2 extends PrivateClass1(1) {


val field1 = privateField1 // ERROR
val field2 = privateField2 // ERROR
val nField = new Nested().nestedField // ERROR
}

class PrivateClass3 {
val privateClass1 = new PrivateClass1(1)
val privateField1 = privateClass1.privateField1 // ERROR
val privateField2 = privateClass1.privateField2 // ERROR
val privateNField = privateClass1.nested.nestedField // ERROR
}

private class PrivateClass4

class PrivateClass5 extends PrivateClass4 // ERROR


protected class PrivateClass6 extends PrivateClass4 // ERROR
private class PrivateClass7 extends PrivateClass4
}

package scopeB {
class PrivateClass4B extends scopeA.PrivateClass4 // ERROR
}

&RPSLOLQJWKLVILOH\LHOGVWKHIROORZLQJRXWSXW
14: error: not found: value privateField1
val field1 = privateField1
^
15: error: not found: value privateField2
val field2 = privateField2
^
16: error: value nestedField cannot be accessed in PrivateClass2.this.Nested
val nField = new Nested().nestedField
^
20: error: value privateField1 cannot be accessed in scopeA.PrivateClass1
val privateField1 = privateClass1.privateField1
^
21: error: value privateField2 cannot be accessed in scopeA.PrivateClass1
val privateField2 = privateClass1.privateField2
^
22: error: value nested cannot be accessed in scopeA.PrivateClass1
val privateNField = privateClass1.nested.nestedField
^

Visibility Rules | 101

Download at WoweBook.Com
27: error: private class PrivateClass4 escapes its defining scope as part
of type scopeA.PrivateClass4
class PrivateClass5 extends PrivateClass4
^
28: error: private class PrivateClass4 escapes its defining scope as part
of type scopeA.PrivateClass4
protected class PrivateClass6 extends PrivateClass4
^
33: error: class PrivateClass4 cannot be accessed in package scopeA
class PrivateClass4B extends scopeA.PrivateClass4
^
9 errors found

1RZ PrivateClass2FDQ¦WDFFHVVSULYDWHPHPEHUVRILWVSDUHQWFODVV PrivateClass1


7KH\DUHFRPSOHWHO\LQYLVLEOHWRWKHVXEFODVVDVLQGLFDWHGE\WKHHUURUPHVVDJHV1RU
FDQLWDFFHVVDSULYDWHILHOGLQDNestedFODVV
-XVWDVIRUWKHFDVHRIprotectedDFFHVVPrivateClass3FDQ¦WDFFHVVSULYDWHPHPEHUVRI
WKHPrivateClass1LQVWDQFHLWLVXVLQJ1RWHKRZHYHUWKDWWKHequalFieldsPHWKRGFDQ
DFFHVVSULYDWHPHPEHUVRIWKHotherLQVWDQFH
7KH GHFODUDWLRQV RI PrivateClass5 DQG PrivateClass6 IDLO EHFDXVH LI DOORZHG WKH\
ZRXOGHQDEOHPrivateClass4WR£HVFDSHLWVGHILQLQJVFRSH¤+RZHYHUWKHGHFODUDWLRQ
RIPrivateClass7VXFFHHGVEHFDXVHLWLVDOVRGHFODUHGWREHSULYDWH&XULRXVO\RXUSUH
YLRXVH[DPSOHZDVDEOHWRGHFODUHDSXEOLFFODVVWKDWVXEFODVVHGDSURWHFWHGFODVVZLWK
RXWDVLPLODUHUURU
)LQDOO\MXVWDVIRU protectedW\SHGHFODUDWLRQVWKH privateW\SHVFDQ¦WEHVXEFODVVHG
RXWVLGHWKHVDPHSDFNDJH

Scoped Private and Protected Visibility


6FDOD DOORZV \RX WR ILQHWXQH WKH VFRSH RI YLVLELOLW\ ZLWK WKH VFRSHG private DQG
protectedYLVLELOLW\GHFODUDWLRQV1RWHWKDWXVLQJprivateRUprotectedLQDVFRSHGGHF
ODUDWLRQLVLQWHUFKDQJHDEOHDVWKH\EHKDYHLGHQWLFDOO\H[FHSWXQGHULQKHULWDQFHZKHQ
DSSOLHGWRPHPEHUV

:KLOHHLWKHUFKRLFHEHKDYHVWKHVDPHLQPRVWVFHQDULRVLWLVPRUHFRP
PRQWRVHH private[X]UDWKHUWKDQ protected[X]XVHGLQFRGH,QWKH
FRUHOLEUDULHVLQFOXGHGZLWK6FDODWKHUDWLRLVURXJKO\ILYHWRRQH

/HW¦VEHJLQE\FRQVLGHULQJWKHRQO\GLIIHUHQFHVLQEHKDYLRUEHWZHHQVFRSHGSULYDWHDQG
VFRSHG SURWHFWHG¢KRZ WKH\ EHKDYH XQGHU LQKHULWDQFH ZKHQ PHPEHUV KDYH WKHVH
VFRSHV
// code-examples/BasicOOP/scoping/scope-inheritance-wont-compile.scala
// WON'T COMPILE

package scopeA {

102 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
class Class1 {
private[scopeA] val scopeA_privateField = 1
protected[scopeA] val scopeA_protectedField = 2
private[Class1] val class1_privateField = 3
protected[Class1] val class1_protectedField = 4
private[this] val this_privateField = 5
protected[this] val this_protectedField = 6
}

class Class2 extends Class1 {


val field1 = scopeA_privateField
val field2 = scopeA_protectedField
val field3 = class1_privateField // ERROR
val field4 = class1_protectedField
val field5 = this_privateField // ERROR
val field6 = this_protectedField
}
}

package scopeB {
class Class2B extends scopeA.Class1 {
val field1 = scopeA_privateField // ERROR
val field2 = scopeA_protectedField
val field3 = class1_privateField // ERROR
val field4 = class1_protectedField
val field5 = this_privateField // ERROR
val field6 = this_protectedField
}
}

&RPSLOLQJWKLVILOH\LHOGVWKHIROORZLQJRXWSXW
17: error: not found: value class1_privateField
val field3 = class1_privateField // ERROR
^
19: error: not found: value this_privateField
val field5 = this_privateField // ERROR
^
26: error: not found: value scopeA_privateField
val field1 = scopeA_privateField // ERROR
^
28: error: not found: value class1_privateField
val field3 = class1_privateField // ERROR
^
30: error: not found: value this_privateField
val field5 = this_privateField // ERROR
^
5 errors found

7KHILUVWWZRHUURUVLQVLGHClass2VKRZXVWKDWDGHULYHGFODVVLQVLGHWKHVDPHSDFNDJH
FDQ¦WUHIHUHQFHDPHPEHUWKDWLVVFRSHGSULYDWHWRWKHSDUHQWFODVVRU thisEXWLWFDQ
UHIHUHQFHDSULYDWHPHPEHUVFRSHGWRWKHSDFNDJH RUW\SH WKDWHQFORVHVERWKClass1
DQGClass2

Visibility Rules | 103

Download at WoweBook.Com
,QFRQWUDVWIRUDGHULYHGFODVVRXWVLGHWKHVDPHSDFNDJHLWKDVQRDFFHVVWRDQ\RIWKH
VFRSHGSULYDWHPHPEHUVRIClass1
+RZHYHUDOOWKHVFRSHGSURWHFWHGPHPEHUVDUHYLVLEOHLQERWKGHULYHGFODVVHV
:H¦OOXVHVFRSHGSULYDWHGHFODUDWLRQVIRUWKHUHVWRIRXUH[DPSOHVDQGGLVFXVVLRQVLQFH
XVHRIVFRSHGSULYDWHLVDOLWWOHPRUHFRPPRQLQWKH6FDODOLEUDU\WKDQVFRSHGSURWHFWHG
ZKHQWKHSUHYLRXVLQKHULWDQFHVFHQDULRVDUHQ¦WDIDFWRU
)LUVW OHW¦V VWDUW ZLWK WKH PRVW UHVWULFWLYH YLVLELOLW\ private[this] DV LW DIIHFWV W\SH
PHPEHUV
// code-examples/BasicOOP/scoping/private-this-wont-compile.scala
// WON'T COMPILE

package scopeA {
class PrivateClass1(private[this] val privateField1: Int) {
private[this] val privateField2 = 1

def equalFields(other: PrivateClass1) =


(privateField1 == other.privateField1) && // ERROR
(privateField2 == other.privateField2) &&
(nested == other.nested)

class Nested {
private[this] val nestedField = 1
}

private[this] val nested = new Nested


}

class PrivateClass2 extends PrivateClass1(1) {


val field1 = privateField1 // ERROR
val field2 = privateField2 // ERROR
val nField = new Nested().nestedField // ERROR
}

class PrivateClass3 {
val privateClass1 = new PrivateClass1(1)
val privateField1 = privateClass1.privateField1 // ERROR
val privateField2 = privateClass1.privateField2 // ERROR
val privateNField = privateClass1.nested.nestedField // ERROR
}
}

&RPSLOLQJWKLVILOH\LHOGVWKHIROORZLQJRXWSXW
5: error: value privateField1 is not a member of scopeA.PrivateClass1
(privateField1 == other.privateField1) &&
^
14: error: not found: value privateField1
val field1 = privateField1
^
15: error: not found: value privateField2
val field2 = privateField2
^

104 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
16: error: value nestedField is not a member of PrivateClass2.this.Nested
val nField = new Nested().nestedField
^
20: error: value privateField1 is not a member of scopeA.PrivateClass1
val privateField1 = privateClass1.privateField1
^
21: error: value privateField2 is not a member of scopeA.PrivateClass1
val privateField2 = privateClass1.privateField2
^
22: error: value nested is not a member of scopeA.PrivateClass1
val privateNField = privateClass1.nested.nestedField
^
7 errors found

/LQHV¡DOVRZRQ¦WSDUVH6LQFHWKH\DUHSDUWRIWKHH[SUHVVLRQWKDW
VWDUWHGRQOLQHWKHFRPSLOHUVWRSSHGDIWHUWKHILUVWHUURU

7KHprivate[this]PHPEHUVDUHRQO\YLVLEOHWRWKHVDPHLQVWDQFH$QLQVWDQFHRIWKH
VDPHFODVVFDQ¦WVHH private[this]PHPEHUVRIDQRWKHULQVWDQFHVRWKH equalFields
PHWKRGZRQ¦WSDUVH
2WKHUZLVH WKH YLVLELOLW\ RI FODVV PHPEHUV LV WKH VDPH DV private ZLWKRXW D VFRSH
VSHFLILHU
:KHQGHFODULQJDW\SHZLWKprivate[this]XVHRIthisHIIHFWLYHO\ELQGVWRWKHHQFORVLQJ
SDFNDJHDVVKRZQKHUH
// code-examples/BasicOOP/scoping/private-this-pkg-wont-compile.scala
// WON'T COMPILE

package scopeA {
private[this] class PrivateClass1

package scopeA2 {
private[this] class PrivateClass2
}

class PrivateClass3 extends PrivateClass1 // ERROR


protected class PrivateClass4 extends PrivateClass1 // ERROR
private class PrivateClass5 extends PrivateClass1
private[this] class PrivateClass6 extends PrivateClass1

private[this] class PrivateClass7 extends scopeA2.PrivateClass2 // ERROR


}

package scopeB {
class PrivateClass1B extends scopeA.PrivateClass1 // ERROR
}

&RPSLOLQJWKLVILOH\LHOGVWKHIROORZLQJRXWSXW

Visibility Rules | 105

Download at WoweBook.Com
8: error: private class PrivateClass1 escapes its defining scope as part
of type scopeA.PrivateClass1
class PrivateClass3 extends PrivateClass1
^
9: error: private class PrivateClass1 escapes its defining scope as part
of type scopeA.PrivateClass1
protected class PrivateClass4 extends PrivateClass1
^
13: error: type PrivateClass2 is not a member of package scopeA.scopeA2
private[this] class PrivateClass7 extends scopeA2.PrivateClass2
^
17: error: type PrivateClass1 is not a member of package scopeA
class PrivateClass1B extends scopeA.PrivateClass1
^
four errors found

,QWKHVDPHSDFNDJHDWWHPSWLQJWRGHFODUHDpublicRUprotectedVXEFODVVIDLOV2QO\
privateDQG private[this]VXEFODVVHVDUHDOORZHG$OVR PrivateClass2LVVFRSHGWR
scopeA2VR\RXFDQ¦WGHFODUHLWRXWVLGHscopeA26LPLODUO\DQDWWHPSWWRGHFODUHDFODVV
LQXQUHODWHGscopeBXVLQJPrivateClass1DOVRIDLOV
+HQFHZKHQDSSOLHGWRW\SHV private[this]LVHTXLYDOHQWWR-DYD¦V package private
YLVLELOLW\
1H[WOHW¦VH[DPLQHW\SHOHYHOYLVLELOLW\private[T]ZKHUHTLVDW\SH
// code-examples/BasicOOP/scoping/private-type-wont-compile.scala
// WON'T COMPILE

package scopeA {
class PrivateClass1(private[PrivateClass1] val privateField1: Int) {
private[PrivateClass1] val privateField2 = 1

def equalFields(other: PrivateClass1) =


(privateField1 == other.privateField1) &&
(privateField2 == other.privateField2) &&
(nested == other.nested)

class Nested {
private[Nested] val nestedField = 1
}

private[PrivateClass1] val nested = new Nested


val nestedNested = nested.nestedField // ERROR
}

class PrivateClass2 extends PrivateClass1(1) {


val field1 = privateField1 // ERROR
val field2 = privateField2 // ERROR
val nField = new Nested().nestedField // ERROR
}

class PrivateClass3 {
val privateClass1 = new PrivateClass1(1)
val privateField1 = privateClass1.privateField1 // ERROR

106 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
val privateField2 = privateClass1.privateField2 // ERROR
val privateNField = privateClass1.nested.nestedField // ERROR
}
}

&RPSLOLQJWKLVILOH\LHOGVWKHIROORZLQJRXWSXW
12: error: value nestedField cannot be accessed in PrivateClass1.this.Nested
val nestedNested = nested.nestedField
^
15: error: not found: value privateField1
val field1 = privateField1
^
16: error: not found: value privateField2
val field2 = privateField2
^
17: error: value nestedField cannot be accessed in PrivateClass2.this.Nested
val nField = new Nested().nestedField
^
21: error: value privateField1 cannot be accessed in scopeA.PrivateClass1
val privateField1 = privateClass1.privateField1
^
22: error: value privateField2 cannot be accessed in scopeA.PrivateClass1
val privateField2 = privateClass1.privateField2
^
23: error: value nested cannot be accessed in scopeA.PrivateClass1
val privateNField = privateClass1.nested.nestedField
^
7 errors found

$ private[PrivateClass1] PHPEHU LV YLVLEOH WR RWKHU LQVWDQFHV VR WKH equalFields
PHWKRG QRZ SDUVHV +HQFH private[T] LV QRW DV UHVWULFWLYH DV private[this] 1RWH
WKDW PrivateClass1 FDQ¦W VHH Nested.nestedField EHFDXVH WKDW ILHOG LV GHFODUHG
private[Nested]

:KHQPHPEHUVRITDUHGHFODUHGprivate[T]WKHEHKDYLRULVHTXLYDOHQW
WR private ,W LV QRW HTXLYDOHQW WR private[this] ZKLFK LV PRUH
UHVWULFWLYH

:KDWLIZHFKDQJHWKHVFRSHRINested.nestedFieldWREHprivate[PrivateClass1]"/HW¦V
VHHKRZprivate[T]DIIHFWVQHVWHGW\SHV
// code-examples/BasicOOP/scoping/private-type-nested-wont-compile.scala
// WON'T COMPILE

package scopeA {
class PrivateClass1 {
class Nested {
private[PrivateClass1] val nestedField = 1
}

private[PrivateClass1] val nested = new Nested


val nestedNested = nested.nestedField

Visibility Rules | 107

Download at WoweBook.Com
}

class PrivateClass2 extends PrivateClass1 {


val nField = new Nested().nestedField // ERROR
}

class PrivateClass3 {
val privateClass1 = new PrivateClass1
val privateNField = privateClass1.nested.nestedField // ERROR
}
}

&RPSLOLQJWKLVILOH\LHOGVWKHIROORZLQJRXWSXW
10: error: value nestedField cannot be accessed in PrivateClass2.this.Nested
def nField = new Nested().nestedField
^
14: error: value nested cannot be accessed in scopeA.PrivateClass1
val privateNField = privateClass1.nested.nestedField
^
two errors found

1RZnestedFieldLVYLVLEOHWRPrivateClass1EXWLWLVVWLOOLQYLVLEOHRXWVLGHRIPrivate
Class17KLVLVKRZprivateZRUNVLQ-DYD
/HW¦VH[DPLQHVFRSLQJXVLQJDSDFNDJHQDPH
// code-examples/BasicOOP/scoping/private-pkg-type-wont-compile.scala
// WON'T COMPILE

package scopeA {
private[scopeA] class PrivateClass1

package scopeA2 {
private [scopeA2] class PrivateClass2
private [scopeA] class PrivateClass3
}

class PrivateClass4 extends PrivateClass1


protected class PrivateClass5 extends PrivateClass1
private class PrivateClass6 extends PrivateClass1
private[this] class PrivateClass7 extends PrivateClass1

private[this] class PrivateClass8 extends scopeA2.PrivateClass2 // ERROR


private[this] class PrivateClass9 extends scopeA2.PrivateClass3
}

package scopeB {
class PrivateClass1B extends scopeA.PrivateClass1 // ERROR
}

&RPSLOLQJWKLVILOH\LHOGVWKHIROORZLQJRXWSXW
14: error: class PrivateClass2 cannot be accessed in package scopeA.scopeA2
private[this] class PrivateClass8 extends scopeA2.PrivateClass2
^
19: error: class PrivateClass1 cannot be accessed in package scopeA

108 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
class PrivateClass1B extends scopeA.PrivateClass1
^
two errors found

1RWHWKDWPrivateClass2FDQ¦WEHVXEFODVVHGRXWVLGHRIscopeA2EXWPrivateClass3FDQ
EHVXEFODVVHGLQscopeAEHFDXVHLWLVGHFODUHGprivate[scopeA]
)LQDOO\OHW¦VORRNDWWKHHIIHFWRISDFNDJHOHYHOVFRSLQJRIW\SHPHPEHUV
// code-examples/BasicOOP/scoping/private-pkg-wont-compile.scala
// WON'T COMPILE

package scopeA {
class PrivateClass1 {
private[scopeA] val privateField = 1

class Nested {
private[scopeA] val nestedField = 1
}

private[scopeA] val nested = new Nested


}

class PrivateClass2 extends PrivateClass1 {


val field = privateField
val nField = new Nested().nestedField
}

class PrivateClass3 {
val privateClass1 = new PrivateClass1
val privateField = privateClass1.privateField
val privateNField = privateClass1.nested.nestedField
}

package scopeA2 {
class PrivateClass4 {
private[scopeA2] val field1 = 1
private[scopeA] val field2 = 2
}
}

class PrivateClass5 {
val privateClass4 = new scopeA2.PrivateClass4
val field1 = privateClass4.field1 // ERROR
val field2 = privateClass4.field2
}
}

package scopeB {
class PrivateClass1B extends scopeA.PrivateClass1 {
val field1 = privateField // ERROR
val privateClass1 = new scopeA.PrivateClass1
val field2 = privateClass1.privateField // ERROR
}
}

Visibility Rules | 109

Download at WoweBook.Com
&RPSLOLQJWKLVILOH\LHOGVWKHIROORZLQJRXWSXW
28: error: value field1 cannot be accessed in scopeA.scopeA2.PrivateClass4
val field1 = privateClass4.field1
^
35: error: not found: value privateField
val field1 = privateField
^
37: error: value privateField cannot be accessed in scopeA.PrivateClass1
val field2 = privateClass1.privateField
^
three errors found

7KHRQO\HUURUVDUHZKHQZHDWWHPSWWRDFFHVVPHPEHUVVFRSHGWR scopeAIURPWKH
XQUHODWHG SDFNDJH scopeB DQG ZKHQ ZH DWWHPSW WR DFFHVV D PHPEHU IURP D QHVWHG
SDFNDJHscopeA2WKDWLVVFRSHGWRWKDWSDFNDJH

:KHQDW\SHRUPHPEHULVGHFODUHGprivate[P]ZKHUHPLVWKHHQFORVLQJ
SDFNDJHWKHQLWLVHTXLYDOHQWWR-DYD¦Vpackage privateYLVLELOLW\

Final Thoughts on Visibility


6FDODYLVLELOLW\GHFODUDWLRQVDUHYHU\IOH[LEOHDQGWKH\EHKDYHFRQVLVWHQWO\7KH\SURYLGH
ILQHJUDLQHG FRQWURO RYHU YLVLELOLW\ DW DOO SRVVLEOH VFRSHV IURP WKH LQVWDQFH OHYHO
private[this] XSWRSDFNDJHOHYHOYLVLELOLW\ private[P]IRUDSDFNDJHP )RUH[DP
SOH WKH\ PDNH LW HDVLHU WR FUHDWH £FRPSRQHQWV¤ ZLWK W\SHV H[SRVHG RXWVLGH RI WKH
FRPSRQHQW¦VWRSOHYHOSDFNDJHZKLOHKLGLQJLPSOHPHQWDWLRQW\SHVDQGW\SHPHPEHUV
ZLWKLQWKH£FRPSRQHQW¦V¤SDFNDJHV
)LQDOO\ZHKDYHREVHUYHGDSRWHQWLDO£JRWFKD¤ZLWKKLGGHQPHPEHUVRIWUDLWV

%HFDUHIXOZKHQFKRRVLQJWKHQDPHVRIPHPEHUVRIWUDLWV,IWZRWUDLWV
KDYHDPHPEHURIWKHVDPHQDPHDQGWKHWUDLWVDUHXVHGLQWKHVDPH
LQVWDQFHDQDPHFROOLVLRQZLOORFFXUHYHQLIERWKPHPEHUVDUHSULYDWH

)RUWXQDWHO\WKHFRPSLOHUFDWFKHVWKLVSUREOHP

Recap and What’s Next


:HLQWURGXFHGWKHEDVLFVRI6FDOD¦VREMHFWPRGHOLQFOXGLQJFRQVWUXFWRUVLQKHULWDQFH
QHVWLQJRIFODVVHVDQGUXOHVIRUYLVLELOLW\
,QWKHQH[WFKDSWHUZH¦OOH[SORUH6FDOD¦VPRUHDGYDQFHG223IHDWXUHVLQFOXGLQJRYHU
ULGLQJFRPSDQLRQREMHFWVFDVHFODVVHVDQGUXOHVIRUHTXDOLW\EHWZHHQREMHFWV

110 | Chapter 5:—Basic Object-Oriented Programming in Scala

Download at WoweBook.Com
CHAPTER 6
Advanced Object-Oriented
Programming In Scala

:H¦YHJRWWKHEDVLFVRI223LQ6FDODXQGHURXUEHOWEXWWKHUH¦VSOHQW\PRUHWROHDUQ

Overriding Members of Classes and Traits


&ODVVHV DQG WUDLWV FDQ GHFODUH DEVWUDFW PHPEHUV ILHOGV PHWKRGV DQG W\SHV 7KHVH
PHPEHUVPXVWEHGHILQHGE\DGHULYHGFODVVRUWUDLWEHIRUHDQLQVWDQFHFDQEHFUHDWHG
0RVWREMHFWRULHQWHGODQJXDJHVVXSSRUWDEVWUDFWPHWKRGVDQGVRPHDOVRVXSSRUWDE
VWUDFWILHOGVDQGW\SHV

:KHQRYHUULGLQJDFRQFUHWHPHPEHU6FDODUHTXLUHVWKH overrideNH\
ZRUG,WLVRSWLRQDOZKHQDVXEW\SHGHILQHV £RYHUULGHV¤ DQDEVWUDFW
PHPEHU&RQYHUVHO\GRQ¦WXVH overrideXQOHVV\RXDUHDFWXDOO\RYHU
ULGLQJDPHPEHU

5HTXLULQJWKHoverrideNH\ZRUGKDVVHYHUDOEHQHILWV
‡ ,WFDWFKHVPLVVSHOOHGPHPEHUVWKDWZHUHLQWHQGHGWREHRYHUULGHV7KHFRPSLOHU
ZLOOWKURZDQHUURUWKDWWKHPHPEHUGRHVQ¦WRYHUULGHDQ\WKLQJ
‡ ,WFDWFKHVDSRWHQWLDOO\VXEWOHEXJWKDWFDQRFFXULIDQHZPHPEHULVDGGHGWRD
EDVHFODVVZKHUHWKHPHPEHU¦VQDPHFROOLGHVZLWKDQROGHUGHULYHGFODVVPHPEHU
WKDWLVXQNQRZQWRWKHEDVHFODVVGHYHORSHU7KDWLVWKHGHULYHGFODVVPHPEHUZDV
QHYHULQWHQGHGWRRYHUULGHDEDVHFODVVPHPEHU%HFDXVHWKHGHULYHGFODVVPHPEHU
ZRQ¦WKDYHWKHoverrideNH\ZRUGWKHFRPSLOHUZLOOWKURZDQHUURUZKHQWKHQHZ
EDVHFODVVPHPEHULVLQWURGXFHG
‡ +DYLQJ WR DGG WKH NH\ZRUG UHPLQGV \RX WR FRQVLGHU ZKDW PHPEHUV VKRXOG RU
VKRXOGQRWEHRYHUULGGHQ

111

Download at WoweBook.Com
-DYDKDVDQRSWLRQDO@OverrideDQQRWDWLRQIRUPHWKRGV,WKHOSVFDWFKHUURUVRIWKHILUVW
W\SH PLVVSHOOLQJV EXWLWFDQ¦WKHOSZLWKHUURUVRIWKHVHFRQGW\SHVLQFHXVLQJWKH
DQQRWDWLRQLVRSWLRQDO

Attempting to Override final Declarations


+RZHYHULIDGHFODUDWLRQLQFOXGHVWKHfinalNH\ZRUGWKHQRYHUULGLQJWKHGHFODUDWLRQ
LVSURKLELWHG,QWKHIROORZLQJH[DPSOHWKHfixedMethodLVGHFODUHGfinalLQWKHSDUHQW
FODVV$WWHPSWLQJWRFRPSLOHWKHH[DPSOHZLOOUHVXOWLQDFRPSLODWLRQHUURU
// code-examples/AdvOOP/overrides/final-member-wont-compile.scala
// WON'T COMPILE.

class NotFixed {
final def fixedMethod = "fixed"
}

class Changeable2 extends NotFixed {


override def fixedMethod = "not fixed" // ERROR
}

7KLVFRQVWUDLQWDSSOLHVWRFODVVHVDQGWUDLWVDVZHOODVPHPEHUV,QWKLVH[DPSOHWKH
FODVVFixedLVGHFODUHGfinalVRDQDWWHPSWWRGHULYHDQHZW\SHIURPLWZLOODOVRIDLOWR
FRPSLOH
// code-examples/AdvOOP/overrides/final-class-wont-compile.scala
// WON'T COMPILE.

final class Fixed {


def doSomething = "Fixed did something!"
}

class Changeable1 extends Fixed // ERROR

6RPHRIWKHW\SHVLQWKH6FDODOLEUDU\DUHILQDOLQFOXGLQJ-'.FODVVHV
OLNHStringDQGDOOWKH£YDOXH¤W\SHVGHULYHGIURPAnyVal VHH£7KH6FDOD
7\SH+LHUDUFK\¤RQSDJH 

)RUGHFODUDWLRQVWKDWDUHQ¦WILQDOOHW¦VH[DPLQHWKHUXOHVDQGEHKDYLRUVIRURYHUULGLQJ
VWDUWLQJZLWKPHWKRGV

Overriding Abstract and Concrete Methods


/HW¦VH[WHQGRXUIDPLOLDU WidgetEDVHFODVVZLWKDQDEVWUDFWPHWKRG drawWRVXSSRUW
£UHQGHULQJ¤ WKH ZLGJHW WR D GLVSOD\ ZHE SDJH HWF :H¦OO DOVR RYHUULGH D FRQFUHWH
PHWKRGIDPLOLDUWRDQ\-DYDSURJUDPPHUtoString()XVLQJDQDGKRFIRUPDW$VEH
IRUHZHZLOOXVHDQHZSDFNDJHui3

112 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
'UDZLQJLVDFWXDOO\DFURVVFXWWLQJFRQFHUQ7KHVWDWHRIDWidgetLVRQH
WKLQJKRZLWLVUHQGHUHGRQGLIIHUHQWSODWIRUPVWKLFNFOLHQWVZHESDJHV
PRELOHGHYLFHVHWFLVDVHSDUDWHLVVXH6RGUDZLQJLVDYHU\JRRGFDQ
GLGDWH IRU D WUDLW HVSHFLDOO\ LI \RX ZDQW \RXU *8, DEVWUDFWLRQV WR EH
SRUWDEOH+RZHYHUWRNHHSWKLQJVVLPSOHZHZLOOKDQGOHGUDZLQJLQWKH
WidgetKLHUDUFK\LWVHOI

+HUHLVWKHUHYLVHGWidgetFODVVZLWKdrawDQGtoStringPHWKRGV
// code-examples/AdvOOP/ui3/widget.scala

package ui3

abstract class Widget {


def draw(): Unit
override def toString() = "(widget)"
}

7KHdrawPHWKRGLVDEVWUDFWEHFDXVHLWKDVQRERG\WKDWLVWKHPHWKRGLVQ¦WIROORZHG
E\ DQ HTXDOV VLJQ =  QRU DQ\ WH[W DIWHU LW 7KHUHIRUH Widget KDV WR EH GHFODUHG
abstract LWZDVRSWLRQDOEHIRUH (DFKFRQFUHWHVXEFODVVRIWidgetZLOOKDYHWRLPSOH
PHQWdrawRUUHO\RQDSDUHQWFODVVWKDWLPSOHPHQWVLW:HGRQ¦WQHHGWRUHWXUQDQ\WKLQJ
IURPdrawVRLWVUHWXUQYDOXHLVUnit
7KH toString() PHWKRG LV VWUDLJKWIRUZDUG 6LQFH AnyRef GHILQHV toString WKH
overrideNH\ZRUGLVUHTXLUHGIRUWidget.toString
+HUHLVWKHUHYLVHGButtonFODVVZLWKdrawDQGtoStringPHWKRGV
// code-examples/AdvOOP/ui3/button.scala

package ui3

class Button(val label: String) extends Widget with Clickable {

def click() = {
// Logic to give the appearance of clicking a button...
}

def draw() = {
// Logic to draw the button on the display, web page, etc.
}

override def toString() =


"(button: label=" + label + ", " + super.toString() + ")"
}

Button LPSOHPHQWV WKH DEVWUDFW PHWKRG draw 1R override NH\ZRUG LV UHTXLUHG
Button DOVR RYHUULGHV toString VR WKH override NH\ZRUG LV UHTXLUHG 1RWH WKDW
super.toStringLVFDOOHG

Overriding Members of Classes and Traits | 113

Download at WoweBook.Com
7KHsuperNH\ZRUGLVDQDORJRXVWRthisEXWLWELQGVWRWKHSDUHQWW\SHZKLFKLVWKH
DJJUHJDWLRQ RI WKH SDUHQW FODVV DQG DQ\ PL[HGLQ WUDLWV 7KH VHDUFK IRU
super.toString ZLOO ILQG WKH £FORVHVW¤ SDUHQW W\SH toString DV GHWHUPLQHG E\ WKH
OLQHDUL]DWLRQSURFHVV VHH£/LQHDUL]DWLRQRIDQ2EMHFW¦V+LHUDUFK\¤RQSDJH ,Q
WKLVFDVHVLQFHClickableGRHVQ¦WGHILQHtoStringWidget.toStringZLOOEHFDOOHG

2YHUULGLQJDFRQFUHWHPHWKRGVKRXOGEHGRQHUDUHO\EHFDXVHLWLVHUURU
SURQH6KRXOG\RXLQYRNHWKHSDUHQWPHWKRG",IVRZKHQ"'R\RXFDOO
LWEHIRUHGRLQJDQ\WKLQJHOVHRUDIWHUZDUG":KLOHWKHZULWHURIWKHSD
UHQWPHWKRGPLJKWGRFXPHQWWKHRYHUULGLQJFRQVWUDLQWVIRUWKHPHWKRG
LW¦VGLIILFXOWWRHQVXUHWKDWWKHZULWHURIDGHULYHGFODVVZLOOKRQRUWKRVH
FRQVWUDLQWV$PXFKPRUHUREXVWDSSURDFKLVWKH7HPSODWH0HWKRG3DW
WHUQ VHH>*2)@ 

Overriding Abstract and Concrete Fields


0RVWREMHFWRULHQWHGODQJXDJHVDOORZ\RXWRRYHUULGHPXWDEOHILHOGV var )HZHU22
ODQJXDJHV DOORZ \RX WR GHILQH DEVWUDFW ILHOGV RU RYHUULGH FRQFUHWH LPPXWDEOH ILHOGV
val )RUH[DPSOHLW¦VFRPPRQIRUDEDVHFODVVFRQVWUXFWRUWRLQLWLDOL]HDPXWDEOHILHOG
DQGIRUDGHULYHGFODVVFRQVWUXFWRUWRFKDQJHLWVYDOXH
:H¦OOGLVFXVVRYHUULGLQJILHOGVLQWUDLWVDQGFODVVHVVHSDUDWHO\DVWUDLWVKDYHVRPHSDU
WLFXODULVVXHV

Overriding Abstract and Concrete Fields in Traits


5HFDOORXUVetoableClicksWUDLWLQ£6WDFNDEOH7UDLWV¤RQSDJH,WGHILQHVDvalQDPHG
maxAllowedDQGLQLWLDOL]HVLWWR 1:HZRXOGOLNHWKHDELOLW\WRRYHUULGHWKHYDOXHLQD
FODVVWKDWPL[HVLQWKLVWUDLW
8QIRUWXQDWHO\LQ6FDODYHUVLRQ;LWLVQRWSRVVLEOHWRRYHUULGHD valGHILQHGLQD
WUDLW+RZHYHULWLVSRVVLEOHWRRYHUULGHDvalGHILQHGLQDSDUHQWFODVV9HUVLRQRI
6FDODGRHVVXSSRUWRYHUULGLQJDvalLQDWUDLW

%HFDXVHWKHRYHUULGHEHKDYLRUIRUDvalLQDWUDLWLVFKDQJLQJ\RXVKRXOG
DYRLGUHO\LQJRQWKHDELOLW\WRRYHUULGHLWLI\RXDUHFXUUHQWO\XVLQJ6FDOD
YHUVLRQ;8VHDQRWKHUDSSURDFKLQVWHDG

8QIRUWXQDWHO\WKHYHUVLRQFRPSLOHUDFFHSWVFRGHWKDWDWWHPSWVWRRYHUULGHDWUDLW
GHILQHGvalEXWWKHRYHUULGHGRHVQRWDFWXDOO\KDSSHQDVLOOXVWUDWHGE\WKLVH[DPSOH
// code-examples/AdvOOP/overrides/trait-val-script.scala
// DANGER! Silent failure to override a trait's "name" (V2.7.5 only).
// Works as expected in V2.8.0.

114 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
trait T1 {
val name = "T1"
}

class Base

class ClassWithT1 extends Base with T1 {


override val name = "ClassWithT1"
}

val c = new ClassWithT1()


println(c.name)

class ClassExtendsT1 extends T1 {


override val name = "ClassExtendsT1"
}

val c2 = new ClassExtendsT1()


println(c2.name)

,I\RXUXQWKLVVFULSWZLWKscalaYHUVLRQWKHRXWSXWLVWKHIROORZLQJ
T1
T1

5HDGLQJWKHVFULSWZHZRXOGKDYHH[SHFWHGWKHWZRT1VWULQJVWREHClassWithT1DQG
ClassExtendsT1UHVSHFWLYHO\
+RZHYHULI\RXUXQWKLVVFULSWZLWKscalaYHUVLRQ\RXJHWWKLVRXWSXW
ClassWithT1
ClassExtendsT1

$WWHPSWVWRRYHUULGHDWUDLWGHILQHGvalZLOOEHDFFHSWHGE\WKHFRPSLOHU
EXWKDYHQRHIIHFWLQ6FDODYHUVLRQ;

7KHUHDUHWKUHHZRUNDURXQGV\RXFDQXVHZLWK6FDODYHUVLRQ7KHILUVWLVWRXVHVRPH
DGYDQFHGRSWLRQVIRU scalaDQG scalac7KH -XfutureRSWLRQZLOOHQDEOHWKHRYHUULGH
EHKDYLRUVXSSRUWHGLQYHUVLRQ7KH-XcheckinitRSWLRQZLOODQDO\]H\RXUFRGHDQG
UHSRUWZKHWKHUWKHEHKDYLRUFKDQJHZLOOEUHDNLW7KHRSWLRQ -XexperimentalZKLFK
HQDEOHV PDQ\ H[SHULPHQWDO FKDQJHV ZLOO DOVR ZDUQ \RX WKDW WKH val RYHUULGH
EHKDYLRULVGLIIHUHQW
7KHVHFRQGZRUNDURXQGLVWRPDNHWKHvalDEVWUDFWLQWKHWUDLW7KLVIRUFHVDQLQVWDQFH
XVLQJWKHWUDLWWRDVVLJQDYDOXH'HFODULQJDvalLQDWUDLWDEVWUDFWLVDSHUIHFWO\XVHIXO
GHVLJQDSSURDFKIRUERWKYHUVLRQVRI6FDOD,QIDFWWKLVZLOOEHWKHEHVWGHVLJQFKRLFH
ZKHQWKHUHLVQRDSSURSULDWHGHIDXOWYDOXHWRDVVLJQWRWKHvalLQWKHWUDLW
// code-examples/AdvOOP/overrides/trait-abs-val-script.scala

trait AbstractT1 {
val name: String

Overriding Members of Classes and Traits | 115

Download at WoweBook.Com
}

class Base

class ClassWithAbstractT1 extends Base with AbstractT1 {


val name = "ClassWithAbstractT1"
}

val c = new ClassWithAbstractT1()


println(c.name)

class ClassExtendsAbstractT1 extends AbstractT1 {


val name = "ClassExtendsAbstractT1"
}

val c2 = new ClassExtendsAbstractT1()


println(c2.name)

7KLVVFULSWSURGXFHVWKHRXWSXWWKDWZHZRXOGH[SHFW
ClassWithAbstractT1
ClassExtendsAbstractT1

6RDQDEVWUDFWvalZRUNVILQHXQOHVVWKHILHOGLVXVHGLQWKHWUDLWERG\LQDZD\WKDWZLOO
IDLOXQWLOWKHILHOGLVSURSHUO\LQLWLDOL]HG8QIRUWXQDWHO\WKHSURSHULQLWLDOL]DWLRQZRQ¦W
RFFXUXQWLODIWHUWKHWUDLW¦VERG\KDVH[HFXWHG&RQVLGHUWKHIROORZLQJH[DPSOH
// code-examples/AdvOOP/overrides/trait-invalid-init-val-script.scala
// ERROR: "value" read before initialized.

trait AbstractT2 {
println("In AbstractT2:")
val value: Int
val inverse = 1.0/value // ???
println("AbstractT2: value = "+value+", inverse = "+inverse)
}

val c2b = new AbstractT2 {


println("In c2b:")
val value = 10
}
println("c2b.value = "+c2b.value+", inverse = "+c2b.inverse)

:KLOH LW DSSHDUV WKDW ZH DUH FUHDWLQJ DQ LQVWDQFH RI WKH WUDLW ZLWK new
AbstractT2 ...ZHDUHDFWXDOO\XVLQJDQDQRQ\PRXVFODVVWKDWLPSOLFLWO\H[WHQGVWKH
WUDLW7KLVVFULSWVKRZVZKDWKDSSHQVZKHQinverseLVFDOFXODWHG
In AbstractT2:
AbstractT2: value = 0, inverse = Infinity
In c2b:
c2b.value = 10, inverse = Infinity

$V\RXPLJKWH[SHFWWKH inverseLVFDOFXODWHGWRRHDUO\1RWHWKDWDGLYLGHE\]HUR
H[FHSWLRQLVQ¦WWKURZQWKHFRPSLOHUUHFRJQL]HVWKHYDOXHLVLQILQLWHEXWLWKDVQ¦WDF
WXDOO\£WULHG¤WKHGLYLVLRQ\HW

116 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
7KHEHKDYLRURIWKLVVFULSWLVDFWXDOO\TXLWHVXEWOH$VDQH[HUFLVHWU\VHOHFWLYHO\UH
PRYLQJ RUFRPPHQWLQJRXW WKHGLIIHUHQWprintlnVWDWHPHQWVRQHDWDWLPH2EVHUYH
ZKDWKDSSHQVWRWKHUHVXOWV6RPHWLPHVinverseLVLQLWLDOL]HGSURSHUO\ +LQWUHPRYH
WKHprintln("In c2b:")VWDWHPHQW7KHQWU\SXWWLQJLWEDFNEXWDIWHUWKHval value =
10OLQH
:KDWWKLVH[SHULPHQWUHDOO\VKRZVLVWKDWVLGHHIIHFWV LHIURPWKHprintlnVWDWHPHQWV
FDQEHXQH[SHFWHGDQGVXEWOHHVSHFLDOO\GXULQJLQLWLDOL]DWLRQ,W¦VEHVWWRDYRLGWKHP
6FDODSURYLGHVWZRVROXWLRQVWRWKLVSUREOHPOD]\YDOXHVZKLFKZHGLVFXVVLQ£/D]\
9DOV¤RQSDJHDQGSUHLQLWLDOL]HGILHOGVZKLFKLVGHPRQVWUDWHGLQWKHIROORZLQJ
UHILQHPHQWWRWKHSUHYLRXVH[DPSOH
// code-examples/AdvOOP/overrides/trait-pre-init-val-script.scala

trait AbstractT2 {
println("In AbstractT2:")
val value: Int
val inverse = 1.0/value
println("AbstractT2: value = "+value+", inverse = "+inverse)
}

val c2c = new {


// Only initializations are allowed in pre-init. blocks.
// println("In c2c:")
val value = 10
} with AbstractT2

println("c2c.value = "+c2c.value+", inverse = "+c2c.inverse)

:HLQVWDQWLDWHDQDQRQ\PRXVLQQHUFODVVLQLWLDOL]LQJWKHvalueILHOGLQWKHEORFNEHIRUH
WKHwith AbstractT2FODXVH7KLVJXDUDQWHHVWKDWvalueLVLQLWLDOL]HGEHIRUHWKHERG\RI
AbstractT2LVH[HFXWHGDVVKRZQZKHQ\RXUXQWKHVFULSW
In AbstractT2:
AbstractT2: value = 10, inverse = 0.1
c2c.value = 10, inverse = 0.1

$OVRLI\RXVHOHFWLYHO\UHPRYHDQ\RIWKHprintlnVWDWHPHQWV\RXJHWWKHVDPHH[SHFWHG
DQGQRZSUHGLFWDEOHUHVXOWV
1RZOHW¦VFRQVLGHUWKHVHFRQGZRUNDURXQGZHGHVFULEHGHDUOLHUFKDQJLQJWKHGHFOD
UDWLRQWRvar7KLVVROXWLRQLVPRUHVXLWDEOHLIDJRRGGHIDXOWYDOXHH[LVWVDQG\RXGRQ¦W
ZDQWWRUHTXLUHLQVWDQFHVWKDWXVHWKHWUDLWWRDOZD\VVHWWKHYDOXH,QWKLVFDVHFKDQJH
WKH valWRD varHLWKHUDSXEOLF varRUDSULYDWH varKLGGHQEHKLQGUHDGHUDQGZULWHU
PHWKRGV(LWKHUZD\ZHFDQVLPSO\UHDVVLJQWKHYDOXHLQDGHULYHGWUDLWRUFODVV
5HWXUQLQJWRRXU VetoableClicksH[DPSOHKHUHLVWKHPRGLILHG VetoableClicksWUDLW
WKDWXVHVDSXEOLFvarIRUmaxAllowed

Overriding Members of Classes and Traits | 117

Download at WoweBook.Com
// code-examples/AdvOOP/ui3/vetoable-clicks.scala

package ui3
import observer._

trait VetoableClicks extends Clickable {


var maxAllowed = 1 // default
private var count = 0
abstract override def click() = {
count += 1
if (count <= maxAllowed)
super.click()
}
}

+HUHLVDQHZspecsREMHFWButtonClickableObserverVetoableSpec2WKDWGHPRQVWUDWHV
FKDQJLQJWKHYDOXHRImaxAllowed
// code-examples/AdvOOP/ui3/button-clickable-observer-vetoable2-spec.scala
package ui3

import org.specs._
import observer._
import ui.ButtonCountObserver

object ButtonClickableObserverVetoableSpec2 extends Specification {


"A Button Observer with Vetoable Clicks" should {
"observe only the first 'maxAllowed' clicks" in {
val observableButton =
new Button("Okay") with ObservableClicks with VetoableClicks {
maxAllowed = 2
}
observableButton.maxAllowed mustEqual 2
val buttonClickCountObserver = new ButtonCountObserver
observableButton.addObserver(buttonClickCountObserver)
for (i <- 1 to 3) observableButton.click()
buttonClickCountObserver.count mustEqual 2
}
}
}

1Roverride varLVUHTXLUHG:HMXVWDVVLJQDQHZYDOXH6LQFHWKHERG\RIWKHWUDLWLV
H[HFXWHG EHIRUH WKH ERG\ RI WKH FODVV XVLQJ LW UHDVVLJQLQJ WKH ILHOG YDOXH KDSSHQV
DIWHUWKHLQLWLDODVVLJQPHQWLQWKHWUDLW¦VERG\+RZHYHUDVZHVDZEHIRUHWKDWUHDV
VLJQPHQWFRXOGKDSSHQWRRODWHLIWKHILHOGLVXVHGLQWKHWUDLW¦VERG\LQVRPHFDOFXODWLRQ
WKDWZLOOEHFRPHLQYDOLGE\DUHDVVLJQPHQWODWHU<RXFDQDYRLGWKLVSUREOHPLI\RX
PDNHWKHILHOGSULYDWHDQGGHILQHDSXEOLFZULWHUPHWKRGWKDWUHGRHVDQ\GHSHQGHQW
FDOFXODWLRQV
$QRWKHUGLVDGYDQWDJHRIXVLQJDvarGHFODUDWLRQLVWKDWmaxAllowedZDVQRWLQWHQGHGWR
EHZULWDEOH$VZHZLOOVHHLQ&KDSWHUUHDGRQO\YDOXHVKDYHLPSRUWDQWEHQHILWV:H
ZRXOG SUHIHU IRU maxAllowed WR EH UHDGRQO\ DW OHDVW DIWHU WKH FRQVWUXFWLRQ SURFHVV
FRPSOHWHV

118 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
:HFDQVHHWKDWWKHVLPSOHDFWRIFKDQJLQJWKHvalWRDvarFDXVHVSRWHQWLDOSUREOHPV
IRUWKHPDLQWDLQHURIVetoableClicks&RQWURORYHUWKDWILHOGLVQRZORVW7KHPDLQWDLQHU
PXVWFDUHIXOO\FRQVLGHUZKHWKHURUQRWWKHYDOXHZLOOFKDQJHDQGLIDFKDQJHZLOOLQYD
OLGDWH WKH VWDWH RI WKH LQVWDQFH 7KLV LVVXH LV HVSHFLDOO\ SHUQLFLRXV LQ PXOWLWKUHDGHG
V\VWHPV VHH£7KH3UREOHPVRI6KDUHG6\QFKURQL]HG6WDWH¤RQSDJH 

$YRLG varILHOGVZKHQSRVVLEOH LQFODVVHVDVZHOODVWUDLWV &RQVLGHU


SXEOLFvarILHOGVHVSHFLDOO\ULVN\

Overriding Abstract and Concrete Fields in Classes


,QFRQWUDVWWRWUDLWVRYHUULGLQJD valGHFODUHGLQDFODVVZRUNVDVH[SHFWHG+HUHLVDQ
H[DPSOHZLWKERWKDvalRYHUULGHDQGDvarUHDVVLJQPHQWLQDGHULYHGFODVV
// code-examples/AdvOOP/overrides/class-field-script.scala

class C1 {
val name = "C1"
var count = 0
}

class ClassWithC1 extends C1 {


override val name = "ClassWithC1"
count = 1
}

val c = new ClassWithC1()


println(c.name)
println(c.count)

7KH overrideNH\ZRUGLVUHTXLUHGIRUWKHFRQFUHWH valILHOG nameEXWQRWIRUWKH var


ILHOGcount7KLVLVEHFDXVHZHDUHFKDQJLQJWKHLQLWLDOL]DWLRQRIDFRQVWDQW val ZKLFK
LVD£VSHFLDO¤RSHUDWLRQ
,I\RXUXQWKLVVFULSWWKHRXWSXWLVWKHIROORZLQJ
ClassWithC1
1

%RWKILHOGVDUHRYHUULGGHQLQWKHGHULYHGFODVVDVH[SHFWHG+HUHLVWKHVDPHH[DPSOH
PRGLILHGVRWKDWERWKWKHvalDQGWKHvarDUHDEVWUDFWLQWKHEDVHFODVV
// code-examples/AdvOOP/overrides/class-abs-field-script.scala

abstract class AbstractC1 {


val name: String
var count: Int
}

class ClassWithAbstractC1 extends AbstractC1 {


val name = "ClassWithAbstractC1"

Overriding Members of Classes and Traits | 119

Download at WoweBook.Com
var count = 1
}

val c = new ClassWithAbstractC1()


println(c.name)
println(c.count)

7KHoverrideNH\ZRUGLVQRWUHTXLUHGIRUnameLQClassWithAbstractC1VLQFHWKHRULJ
LQDOGHFODUDWLRQLVDEVWUDFW7KHRXWSXWRIWKLVVFULSWLVWKHIROORZLQJ
ClassWithAbstractC1
1

,W¦VLPSRUWDQWWRHPSKDVL]HWKDWnameDQGcountDUHDEVWUDFWILHOGVQRWFRQFUHWHILHOGV
ZLWK GHIDXOW YDOXHV $ VLPLODUORRNLQJ GHFODUDWLRQ RI name LQ D -DYD FODVV
String name;ZRXOGGHFODUHDFRQFUHWHILHOGZLWKWKHGHIDXOWYDOXH nullLQWKLVFDVH 
-DYDGRHVQ¦WVXSSRUWDEVWUDFWILHOGVRUW\SHV DVZH¦OOGLVFXVVQH[W RQO\PHWKRGV

Overriding Abstract Types


:H LQWURGXFHG DEVWUDFW W\SH GHFODUDWLRQV LQ £$EVWUDFW 7\SHV $QG 3DUDPHWHUL]HG
7\SHV¤RQSDJH5HFDOOWKHBulkReaderH[DPSOHIURPWKDWVHFWLRQ
// code-examples/TypeLessDoMore/abstract-types-script.scala

import java.io._

abstract class BulkReader {


type In
val source: In
def read: String
}

class StringBulkReader(val source: String) extends BulkReader {


type In = String
def read = source
}

class FileBulkReader(val source: File) extends BulkReader {


type In = File
def read = {
val in = new BufferedInputStream(new FileInputStream(source))
val numBytes = in.available()
val bytes = new Array[Byte](numBytes)
in.read(bytes, 0, numBytes)
new String(bytes)
}
}

println( new StringBulkReader("Hello Scala!").read )


println( new FileBulkReader(new File("abstract-types-script.scala")).read )

120 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
$EVWUDFWW\SHVDUHDQDOWHUQDWLYHWRSDUDPHWHUL]HGW\SHVZKLFKZH¦OOH[SORUHLQ£8Q
GHUVWDQGLQJ3DUDPHWHUL]HG7\SHV¤RQSDJH/LNHSDUDPHWHUL]HGW\SHVWKH\SUR
YLGHDQDEVWUDFWLRQPHFKDQLVPDWWKHW\SHOHYHO
7KHH[DPSOHVKRZVKRZWRGHFODUHDQDEVWUDFWW\SHDQGKRZWRGHILQHDFRQFUHWHYDOXH
LQ GHULYHG FODVVHV BulkReader GHFODUHV type In ZLWKRXW LQLWLDOL]LQJ LW 7KH FRQFUHWH
GHULYHGFODVVStringBulkReaderSURYLGHVDFRQFUHWHYDOXHXVLQJtype In = String
8QOLNH ILHOGV DQG PHWKRGV LW LV QRW SRVVLEOH WR RYHUULGH D FRQFUHWH type GHILQLWLRQ
+RZHYHUWKHDEVWUDFWGHFODUDWLRQFDQFRQVWUDLQWKHDOORZHGFRQFUHWHW\SHYDOXHV:H¦OO
OHDUQKRZLQ&KDSWHU
)LQDOO\\RXSUREDEO\QRWLFHGWKDWWKLVH[DPSOHDOVRGHPRQVWUDWHVGHILQLQJDQDEVWUDFW
ILHOGXVLQJDFRQVWUXFWRUSDUDPHWHUDQGDQDEVWUDFWPHWKRG
)RU DQRWKHU H[DPSOH OHW¦V UHYLVLW RXU Subject WUDLW IURP £7UDLWV $V 0L[
LQV¤RQSDJH7KHGHILQLWLRQRIWKHObserverW\SHLVDVWUXFWXUDOW\SHZLWKDPHWKRG
QDPHG receiveUpdate2EVHUYHUVPXVWKDYHWKLV£VWUXFWXUH¤/HW¦VJHQHUDOL]HWKHLP
SOHPHQWDWLRQQRZXVLQJDQDEVWUDFWW\SH
// code-examples/AdvOOP/observer/observer2.scala

package observer

trait AbstractSubject {
type Observer

private var observers = List[Observer]()


def addObserver(observer:Observer) = observers ::= observer
def notifyObservers = observers foreach (notify(_))

def notify(observer: Observer): Unit


}

trait SubjectForReceiveUpdateObservers extends AbstractSubject {


type Observer = { def receiveUpdate(subject: Any) }

def notify(observer: Observer): Unit = observer.receiveUpdate(this)


}

trait SubjectForFunctionalObservers extends AbstractSubject {


type Observer = (AbstractSubject) => Unit

def notify(observer: Observer): Unit = observer(this)


}

1RZAbstractSubjectGHFODUHVtype ObserverDVDEVWUDFW LPSOLFLWO\EHFDXVHWKHUHLV


QRGHILQLWLRQ 6LQFHWKHRULJLQDOVWUXFWXUDOW\SHLVJRQHZHGRQ¦WNQRZH[DFWO\KRZWR
QRWLI\DQREVHUYHU6RZHDOVRDGGHGDQDEVWUDFWPHWKRGnotifyZKLFKDFRQFUHWHFODVV
RUWUDLWZLOOGHILQHDVDSSURSULDWH

Overriding Members of Classes and Traits | 121

Download at WoweBook.Com
7KH SubjectForReceiveUpdateObserversGHULYHGWUDLWGHILQHV ObserverZLWKWKHVDPH
VWUXFWXUDO W\SH ZH XVHG LQ WKH RULJLQDO H[DPSOH DQG notify VLPSO\ FDOOV
receiveUpdateDVEHIRUH
7KH SubjectForFunctionalObservers GHULYHG WUDLW GHILQHV Observer WR EH D IXQFWLRQ
WDNLQJDQLQVWDQFHRI AbstractSubjectDQGUHWXUQLQJ Unit$OO notifyKDVWRGRLVFDOO
WKHREVHUYHUIXQFWLRQSDVVLQJWKHVXEMHFWDVWKHVROHDUJXPHQW1RWHWKDWWKLVLPSOH
PHQWDWLRQLVVLPLODUWRWKHDSSURDFKZHXVHGLQRXURULJLQDOEXWWRQLPSOHPHQWDWLRQ
ButtonWithCallbacksZKHUHWKH£FDOOEDFNV¤ZHUHXVHUVXSSOLHGIXQFWLRQV 6HH£,QWUR
GXFLQJ 7UDLWV¤ RQ SDJH  DQG D UHYLVLWHG YHUVLRQ LQ £&RQVWUXFWRUV LQ 6FDOD¤
RQSDJH
+HUHLVDVSHFLILFDWLRQWKDWH[HUFLVHVWKHVHWZRYDULDWLRQVREVHUYLQJEXWWRQFOLFNVDV
EHIRUH
// code-examples/AdvOOP/observer/button-observer2-spec.scala

package ui
import org.specs._
import observer._

object ButtonObserver2Spec extends Specification {


"An Observer watching a SubjectForReceiveUpdateObservers button" should {
"observe button clicks" in {
val observableButton =
new Button(name) with SubjectForReceiveUpdateObservers {
override def click() = {
super.click()
notifyObservers
}
}
val buttonObserver = new ButtonCountObserver
observableButton.addObserver(buttonObserver)
for (i <- 1 to 3) observableButton.click()
buttonObserver.count mustEqual 3
}
}
"An Observer watching a SubjectForFunctionalObservers button" should {
"observe button clicks" in {
val observableButton =
new Button(name) with SubjectForFunctionalObservers {
override def click() = {
super.click()
notifyObservers
}
}
var count = 0
observableButton.addObserver((button) => count += 1)
for (i <- 1 to 3) observableButton.click()
count mustEqual 3
}
}
}

122 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
)LUVWZHH[HUFLVH SubjectForReceiveUpdateObserversZKLFKORRNVYHU\VLPLODUWRRXU
HDUOLHU H[DPSOHV 1H[W ZH H[HUFLVH SubjectForFunctionalObservers ,Q WKLV FDVH ZH
GRQ¦WQHHGDQRWKHU£REVHUYHU¤LQVWDQFHDWDOO:HMXVWPDLQWDLQD countYDULDEOHDQG
SDVVDIXQFWLRQOLWHUDOWRaddObserverWRLQFUHPHQWWKHFRXQW DQGLJQRUHWKHEXWWRQ 
7KHPDLQYLUWXHRI SubjectForFunctionalObserversLVLWVPLQLPDOLVP,WUHTXLUHVQR
VSHFLDO LQVWDQFHV QR WUDLWV GHILQLQJ DEVWUDFWLRQV HWF )RU PDQ\ FDVHV LW LV DQ LGHDO
DSSURDFK
AbstractSubject LV PRUH UHXVDEOH WKDQ WKH RULJLQDO GHILQLWLRQ RI Subject EHFDXVH LW
LPSRVHVIHZHUFRQVWUDLQWVRQSRWHQWLDOREVHUYHUV

AbstractSubjectLOOXVWUDWHVWKDWDQDEVWUDFWLRQZLWKIHZHUFRQFUHWHGH
WDLOVLVXVXDOO\PRUHUHXVDEOH

%XWZDLWWKHUH¦VPRUH:H¦OOUHYLVLWWKHXVHRIDEVWUDFWW\SHVDQGWKH2EVHUYHU3DWWHUQ
LQ£6FDODEOH$EVWUDFWLRQV¤RQSDJH

When Accessor Methods and Fields Are Indistinguishable: The Uniform


Access Principle
6XSSRVHDXVHURI ButtonCountObserverIURP£7UDLWV$V0L[LQV¤RQSDJHDFFHVVHV
WKHcountPHPEHU
// code-examples/Traits/ui/button-count-observer-script.scala

val bco = new ui.ButtonCountObserver


val oldCount = bco.count
bco.count = 5
val newCount = bco.count
println(newCount + " == 5 and " + oldCount + " == 0?")

:KHQWKHcountILHOGLVUHDGRUZULWWHQDVLQWKLVH[DPSOHDUHPHWKRGVFDOOHGRULVWKH
ILHOGDFFHVVHGGLUHFWO\"$VRULJLQDOO\GHFODUHGLQ ButtonCountObserverWKHILHOGLVDF
FHVVHGGLUHFWO\+RZHYHUWKHXVHUGRHVQ¦WUHDOO\FDUH,QIDFWWKHIROORZLQJWZRGHIL
QLWLRQVDUHIXQFWLRQDOO\HTXLYDOHQWIURPWKHSHUVSHFWLYHRIWKHXVHU
class ButtonCountObserver {
var count = 0 // public field access (original definition)
// ...
}
class ButtonCountObserver {
private var cnt = 0 // private field
def count = cnt // reader method
def count_=(newCount: Int) = cnt = newCount // writer method
// ...
}

Overriding Members of Classes and Traits | 123

Download at WoweBook.Com
7KLVHTXLYDOHQFHLVDQH[DPSOHRIWKH8QLIRUP$FFHVV3ULQFLSOH&OLHQWVUHDGDQGZULWH
ILHOGYDOXHVDVLIWKH\DUHSXEOLFO\DFFHVVLEOHHYHQWKRXJKLQVRPHFDVHVWKH\DUHDFWXDOO\
FDOOLQJPHWKRGV7KHPDLQWDLQHURIButtonCountObserverKDVWKHIUHHGRPWRFKDQJHWKH
LPSOHPHQWDWLRQZLWKRXWIRUFLQJXVHUVWRPDNHFRGHFKDQJHV
7KHUHDGHUPHWKRGLQWKHVHFRQGYHUVLRQGRHVQRWKDYHSDUHQWKHVHV5HFDOOWKDWFRQ
VLVWHQF\LQWKHXVHRISDUHQWKHVHVLVUHTXLUHGLIDPHWKRGGHILQLWLRQRPLWVSDUHQWKHVHV
7KLVLVRQO\SRVVLEOHLIWKHPHWKRGWDNHVQRDUJXPHQWV)RUWKH8QLIRUP$FFHVV3ULQ
FLSOHWRZRUNZHZDQWWRGHILQHILHOGUHDGHUPHWKRGVZLWKRXWSDUHQWKHVHV &RQWUDVW
WKDWZLWK5XE\ZKHUHPHWKRGSDUHQWKHVHVDUHDOZD\VRSWLRQDODVORQJDVWKHSDUVHLV
XQDPELJXRXV
7KHZULWHUPHWKRGKDVWKHIRUPDWcount_=(...)$VDELWRIV\QWDFWLFVXJDUWKHFRPSLOHU
DOORZVLQYRFDWLRQVRIPHWKRGVZLWKWKLVIRUPDWWREHZULWWHQLQHLWKHURIWKHIROORZLQJ
ZD\V
obj.field_=(newValue)
// or
obj.field = newValue

:HQDPHGWKHSULYDWHYDULDEOH cntLQWKHDOWHUQDWLYHGHILQLWLRQ6FDODNHHSVILHOGDQG
PHWKRGQDPHVLQWKHVDPHQDPHVSDFHZKLFKPHDQVZHFDQ¦WQDPHWKHILHOGcountLID
PHWKRGLVQDPHGcount0DQ\ODQJXDJHVOLNH-DYDGRQ¦WKDYHWKLVUHVWULFWLRQEHFDXVH
WKH\NHHSILHOGDQGPHWKRGQDPHVLQVHSDUDWHQDPHVSDFHV+RZHYHUWKHVHODQJXDJHV
FDQ¦W VXSSRUW WKH 8QLIRUP $FFHVV 3ULQFLSOH DV D UHVXOW XQOHVV WKH\ EXLOG LQ DG KRF
VXSSRUWLQWKHLUJUDPPDUVRUFRPSLOHUV
6LQFHPHPEHUobjectGHILQLWLRQVEHKDYHVLPLODUWRILHOGVIURPWKHFDOOHU¦VSHUVSHFWLYH
WKH\DUHDOVRLQWKHVDPHQDPHVSDFHDVPHWKRGVDQGILHOGV+HQFHWKHIROORZLQJFODVV
ZRXOGQRWFRPSLOH
// code-examples/AdvOOP/overrides/member-namespace-wont-compile.scala
// WON'T COMPILE

class IllegalMemberNameUse {
def member(i: Int) = 2 * i
val member = 2 // ERROR
object member { // ERROR
def apply() = 2
}
}

7KHUHLVRQHRWKHUEHQHILWRIWKLVQDPHVSDFH£XQLILFDWLRQ¤,IDSDUHQWFODVVGHFODUHVD
SDUDPHWHUOHVV PHWKRG WKHQ D VXEFODVV FDQ RYHUULGH WKDW PHWKRG ZLWK D val ,I WKH
SDUHQW¦VPHWKRGLVFRQFUHWHWKHQWKHoverrideNH\ZRUGLVUHTXLUHG
// code-examples/AdvOOP/overrides/method-field-class-script.scala

class Parent {
def name = "Parent"
}

124 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
class Child extends Parent {
override val name = "Child"
}

println(new Child().name) // => "Child"

,IWKHSDUHQW¦VPHWKRGLVDEVWUDFWWKHQWKHoverrideNH\ZRUGLVRSWLRQDO
// code-examples/AdvOOP/overrides/abs-method-field-class-script.scala

abstract class AbstractParent {


def name: String
}

class ConcreteChild extends AbstractParent {


val name = "Child"
}

println(new ConcreteChild().name) // => "Child"

7KLVDOVRZRUNVIRUWUDLWV,IWKHWUDLW¦VPHWKRGLVFRQFUHWHZHKDYHWKHIROORZLQJ
// code-examples/AdvOOP/overrides/method-field-trait-script.scala

trait NameTrait {
def name = "NameTrait"
}

class ConcreteNameClass extends NameTrait {


override val name = "ConcreteNameClass"
}

println(new ConcreteNameClass().name) // => "ConcreteNameClass"

,IWKHWUDLW¦VPHWKRGLVDEVWUDFWZHKDYHWKHIROORZLQJ
// code-examples/AdvOOP/overrides/abs-method-field-trait-script.scala

trait AbstractNameTrait {
def name: String
}

class ConcreteNameClass extends AbstractNameTrait {


val name = "ConcreteNameClass"
}

println(new ConcreteNameClass().name) // => "ConcreteNameClass"

:K\LVWKLVIHDWXUHXVHIXO",WDOORZVGHULYHGFODVVHVDQGWUDLWVWRXVHDVLPSOHILHOGDFFHVV
ZKHQWKDWLVVXIILFLHQWRUDPHWKRGFDOOZKHQPRUHSURFHVVLQJLVUHTXLUHGVXFKDVOD]\
LQLWLDOL]DWLRQ7KHVDPHDUJXPHQWKROGVIRUWKH8QLIRUP$FFHVV3ULQFLSOHLQJHQHUDO
2YHUULGLQJD defZLWKDvalLQDVXEFODVVFDQDOVREHKDQG\ZKHQLQWHURSHUDWLQJZLWK
-DYDFRGH7XUQDJHWWHULQWRD valE\SODFLQJLWLQWKHFRQVWUXFWRU<RX¦OOVHHWKLVLQ
DFWLRQLQWKHIROORZLQJH[DPSOHLQZKLFKRXU6FDODFODVV PersonLPSOHPHQWVDK\SR
WKHWLFDOPersonInterfaceIURPVRPHOHJDF\-DYDFRGH

Overriding Members of Classes and Traits | 125

Download at WoweBook.Com
class Person(val getName: String) extends PersonInterface

,I\RXRQO\KDYHDIHZDFFHVVRUVLQWKH-DYDFRGH\RX¦UHLQWHJUDWLQJZLWKWKLVWHFKQLTXH
PDNHVTXLFNZRUNRIWKHP
:KDWDERXWRYHUULGLQJDSDUDPHWHUOHVVPHWKRGZLWKDvarRURYHUULGLQJDvalRUvar
ZLWKDPHWKRG"7KHVHDUHQRWSHUPLWWHGEHFDXVHWKH\FDQ¦WPDWFKWKHEHKDYLRUVRIWKH
WKLQJVWKH\DUHRYHUULGLQJ
,I\RXDWWHPSWWRXVHD varWRRYHUULGHDSDUDPHWHUOHVVPHWKRG\RXJHWDQHUURUWKDW
WKHZULWHUPHWKRG override name_=LVQRWRYHUULGLQJDQ\WKLQJ7KLVZRXOGDOVREH
LQFRQVLVWHQWZLWKDSKLORVRSKLFDOJRDORIIXQFWLRQDOSURJUDPPLQJWKDWDPHWKRGWKDW
WDNHV QR SDUDPHWHUV VKRXOG DOZD\V UHWXUQ WKH VDPH UHVXOW 7R GR RWKHUZLVH ZRXOG
UHTXLUH VLGH HIIHFWV LQ WKH LPSOHPHQWDWLRQ ZKLFK IXQFWLRQDO SURJUDPPLQJ WULHV WR
DYRLGIRUUHDVRQVZHZLOOH[DPLQHLQ&KDSWHU%HFDXVHDvarLVFKDQJHDEOHWKHQR
SDUDPHWHU£PHWKRG¤GHILQHGLQWKHSDUHQWW\SHZRXOGQRORQJHUUHWXUQWKHVDPHUHVXOW
FRQVLVWHQWO\
,I\RXFRXOGRYHUULGHDvalZLWKDPHWKRGWKHUHZRXOGEHQRZD\IRU6FDODWRJXDUDQWHH
WKDWWKHPHWKRGZRXOGDOZD\VUHWXUQWKHVDPHYDOXHFRQVLVWHQWZLWK valVHPDQWLFV
7KDWLVVXHGRHVQ¦WH[LVWZLWKDvarRIFRXUVHEXW\RXZRXOGKDYHWRRYHUULGHWKHvar
ZLWK WZR PHWKRGV D UHDGHU DQG D ZULWHU 7KH 6FDOD FRPSLOHU GRHVQ¦W VXSSRUW WKDW
VXEVWLWXWLRQ

Companion Objects
5HFDOOWKDWILHOGVDQGPHWKRGVGHILQHGLQobjectsVHUYHWKHUROHWKDWFODVV£VWDWLF¤ILHOGV
DQGPHWKRGVVHUYHLQODQJXDJHVOLNH-DYD:KHQobjectEDVHGILHOGVDQGPHWKRGVDUH
FORVHO\DVVRFLDWHGZLWKDSDUWLFXODU classWKH\DUHQRUPDOO\GHILQHGLQDFRPSDQLRQ
REMHFW
:H PHQWLRQHG FRPSDQLRQ REMHFWV EULHIO\ LQ &KDSWHU  DQG ZH GLVFXVVHG WKH Pair
H[DPSOHIURPWKH6FDODOLEUDU\LQ&KDSWHU/HW¦VILOOLQWKHUHPDLQLQJGHWDLOVQRZ
)LUVWUHFDOOWKDWLIDclass RUDtypeUHIHUULQJWRDFODVV DQGDQobjectDUHGHFODUHGLQ
WKHVDPHILOHLQWKHVDPHSDFNDJHDQGZLWKWKHVDPHQDPHWKH\DUHFDOOHGDFRPSDQLRQ
FODVV RUFRPSDQLRQW\SH DQGDFRPSDQLRQREMHFWUHVSHFWLYHO\
7KHUHLVQRQDPHVSDFHFROOLVLRQZKHQWKHQDPHLVUHXVHGLQWKLVZD\EHFDXVH6FDOD
VWRUHVWKHFODVVQDPHLQWKHW\SHQDPHVSDFHZKLOHLWVWRUHVWKHREMHFWQDPHLQWKHWHUP
QDPHVSDFH VHH>6FDOD6SHF@ 
7KH WZR PRVW LQWHUHVWLQJ PHWKRGV IUHTXHQWO\ GHILQHG LQ D FRPSDQLRQ REMHFW DUH
applyDQGunapply

126 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
Apply
6FDODSURYLGHVVRPHV\QWDFWLFVXJDULQWKHIRUPRIWKHapplyPHWKRG:KHQDQLQVWDQFH
RIDFODVVLVIROORZHGE\SDUHQWKHVHVZLWKDOLVWRI]HURRUPRUHSDUDPHWHUVWKHFRPSLOHU
LQYRNHVWKH applyPHWKRGIRUWKDWLQVWDQFH7KLVLVWUXHIRUDQ objectZLWKDGHILQHG
applyPHWKRG VXFKDVDFRPSDQLRQREMHFW DVZHOODVDQLQVWDQFHRIDclassWKDWGHILQHV
DQapplyPHWKRG
,QWKHFDVHRIDQobjectapplyLVFRQYHQWLRQDOO\XVHGDVDIDFWRU\PHWKRGUHWXUQLQJD
QHZLQVWDQFH7KLVLVZKDWPair.applyGRHVLQWKH6FDODOLEUDU\+HUHLVPairIURPWKH
VWDQGDUGOLEUDU\
type Pair[+A, +B] = Tuple2[A, B]
object Pair {
def apply[A, B](x: A, y: B) = Tuple2(x, y)
def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x)
}

6R\RXFDQFUHDWHDQHZPairDVIROORZV
val p = Pair(1, "one")

,WORRNVOLNHZHDUHVRPHKRZFUHDWLQJDPairLQVWDQFHZLWKRXWDnew5DWKHUWKDQFDOOLQJ
DPairFRQVWUXFWRUGLUHFWO\ZHDUHDFWXDOO\FDOOLQJPair.apply LHWKHFRPSDQLRQRE
MHFWPair ZKLFKWKHQFDOOVTuple2.applyRQWKHTuple2FRPSDQLRQREMHFW

,IWKHUHDUHVHYHUDODOWHUQDWLYHFRQVWUXFWRUVIRUDFODVVDQGLWDOVRKDVD
FRPSDQLRQREMHFWFRQVLGHUGHILQLQJIHZHUFRQVWUXFWRUVRQWKHFODVVDQG
GHILQLQJVHYHUDORYHUORDGHGapplyPHWKRGVRQWKHFRPSDQLRQREMHFWWR
KDQGOHWKHYDULDWLRQV

+RZHYHU applyLVQRWOLPLWHGWRLQVWDQWLDWLQJWKHFRPSDQLRQFODVV,WFRXOGLQVWHDG
UHWXUQDQLQVWDQFHRIDVXEFODVVRIWKHFRPSDQLRQFODVV+HUHLVDQH[DPSOHZKHUHZH
GHILQHDFRPSDQLRQREMHFW WidgetWKDWXVHVUHJXODUH[SUHVVLRQVWRSDUVHDVWULQJUHS
UHVHQWLQJDWidgetVXEFODVV:KHQDPDWFKRFFXUVWKHVXEFODVVLVLQVWDQWLDWHGDQGWKH
QHZLQVWDQFHLVUHWXUQHG
// code-examples/AdvOOP/objects/widget.scala

package objects

abstract class Widget {


def draw(): Unit
override def toString() = "(widget)"
}

object Widget {
val ButtonExtractorRE = """\(button: label=([^,]+),\s+\(Widget\)\)""".r
val TextFieldExtractorRE = """\(textfield: text=([^,]+),\s+\(Widget\)\)""".r

def apply(specification: String): Option[Widget] = specification match {

Companion Objects | 127

Download at WoweBook.Com
case ButtonExtractorRE(label) => new Some(new Button(label))
case TextFieldExtractorRE(text) => new Some(new TextField(text))
case _ => None
}
}

Widget.applyUHFHLYHVDVWULQJ£VSHFLILFDWLRQ¤WKDWGHILQHVZKLFKFODVVWRLQVWDQWLDWH
7KHVWULQJPLJKWFRPHIURPDFRQILJXUDWLRQILOHZLWKZLGJHWVWRFUHDWHDWVWDUWXSIRU
H[DPSOH7KHVWULQJIRUPDWLVWKHVDPHIRUPDWXVHGE\toString()5HJXODUH[SUHVVLRQV
DUHGHILQHGIRUHDFKW\SH 3DUVHUFRPELQDWRUVDUHDQDOWHUQDWLYH7KH\DUHGLVFXVVHGLQ
£([WHUQDO'6/VZLWK3DUVHU&RPELQDWRUV¤RQSDJH
7KHmatchH[SUHVVLRQDSSOLHVHDFKUHJXODUH[SUHVVLRQWRWKHVWULQJ$FDVHH[SUHVVLRQ
OLNH
case ButtonExtractorRE(label) => new Some(new Button(label))

PHDQVWKDWWKHVWULQJLVPDWFKHGDJDLQVWWKHButtonExtractorREUHJXODUH[SUHVVLRQ,I
VXFFHVVIXOLWH[WUDFWVWKHVXEVWULQJLQWKHILUVWFDSWXUHJURXSLQWKHUHJXODUH[SUHVVLRQ
DQGDVVLJQVLWWRWKHYDULDEOH label)LQDOO\DQHZ ButtonZLWKWKLVODEHOLVFUHDWHG
ZUDSSHGLQDSome:H¦OOOHDUQKRZWKLVH[WUDFWLRQSURFHVVZRUNVLQWKHQH[WVHFWLRQ
£8QDSSO\¤RQSDJH
$VLPLODUFDVHKDQGOHVTextFieldFUHDWLRQ TextFieldLVQRWVKRZQ6HHWKHRQOLQHFRGH
H[DPSOHV )LQDOO\LIapplyFDQ¦WPDWFKWKHVWULQJLWUHWXUQVNone
+HUHLVDspecsobjectWKDWH[HUFLVHVWidget.apply
// code-examples/AdvOOP/objects/widget-apply-spec.scala

package objects
import org.specs._

object WidgetApplySpec extends Specification {


"Widget.apply with a valid widget specification string" should {
"return a widget instance with the correct fields set" in {
Widget("(button: label=click me, (Widget))") match {
case Some(w) => w match {
case b:Button => b.label mustEqual "click me"
case x => fail(x.toString())
}
case None => fail("None returned.")
}
Widget("(textfield: text=This is text, (Widget))") match {
case Some(w) => w match {
case tf:TextField => tf.text mustEqual "This is text"
case x => fail(x.toString())
}
case None => fail("None returned.")
}
}
}
"Widget.apply with an invalid specification string" should {
"return None" in {

128 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
Widget("(button: , (Widget)") mustEqual None
}
}
}

7KHILUVWPDWFKVWDWHPHQWLPSOLFLWO\LQYRNHV Widget.applyZLWKWKHVWULQJ "(button:


label=click me, (Widget))",IDEXWWRQZUDSSHGLQD SomeLVQRWUHWXUQHGZLWKWKH
ODEHO"click me"WKLVWHVWZLOOIDLO1H[WDVLPLODUWHVWIRUDTextFieldZLGJHWLVGRQH
7KHILQDOWHVWXVHVDQLQYDOLGVWULQJDQGFRQILUPVWKDWNoneLVUHWXUQHG
$GUDZEDFNRIWKLVSDUWLFXODULPSOHPHQWDWLRQLVWKDWZHKDYHKDUGFRGHGDGHSHQGHQF\
RQHDFKGHULYHGFODVVRIWidgetLQWidgetLWVHOIZKLFKEUHDNVWKH2SHQ&ORVHG3ULQFL
SOH VHH>0H\HU@DQG>0DUWLQ@ $EHWWHULPSOHPHQWDWLRQZRXOGXVHDIDFWRU\
GHVLJQSDWWHUQIURP>*2)@1HYHUWKHOHVVWKHH[DPSOHLOOXVWUDWHVKRZDQ apply
PHWKRGFDQEHXVHGDVDUHDOIDFWRU\
7KHUHLVQRUHTXLUHPHQWIRUapplyLQDQobjectWREHXVHGDVDIDFWRU\1HLWKHULVWKHUH
DQ\UHVWULFWLRQRQWKHDUJXPHQWOLVWRUZKDW applyUHWXUQV+RZHYHUEHFDXVHLWLVVR
FRPPRQWRXVHapplyLQDQobjectDVDIDFWRU\XVHFDXWLRQZKHQXVLQJapplyIRURWKHU
SXUSRVHVDVLWFRXOGFRQIXVHXVHUV+RZHYHUWKHUHDUHJRRGFRXQWHUH[DPSOHVVXFK
DVWKHXVHRIapplyLQ'RPDLQ6SHFLILF/DQJXDJHV VHH&KDSWHU 
7KHIDFWRU\FRQYHQWLRQLVOHVVFRPPRQO\XVHGIRUapplyGHILQHGLQFODVVHV)RUH[DPSOH
LQWKH6FDODVWDQGDUGOLEUDU\Array.apply(i: int)UHWXUQVWKHHOHPHQWDWLQGH[iLQWKH
DUUD\0DQ\RIWKHRWKHUFROOHFWLRQVXVHapplyLQDVLPLODUZD\6RXVHUVFDQZULWHFRGH
OLNHWKHIROORZLQJ
val a = Array(1,2,3,4)
println(a(2)) // => 3

)LQDOO\DVDUHPLQGHUDOWKRXJKapplyLVKDQGOHGVSHFLDOO\E\WKHFRPSLOHULWLVRWKHU
ZLVHQRGLIIHUHQWIURPDQ\RWKHUPHWKRG<RXFDQRYHUORDGLW\RXFDQLQYRNHLWGLUHFWO\
HWF

Unapply
7KHQDPHunapplyVXJJHVWVWKDWLWGRHVWKH£RSSRVLWH¤RSHUDWLRQRIapply,QGHHGLWLV
XVHGWRH[WUDFWWKHFRQVWLWXHQWSDUWVRIDQLQVWDQFH3DWWHUQPDWFKLQJXVHVWKLVIHDWXUH
H[WHQVLYHO\+HQFHunapplyLVRIWHQGHILQHGLQFRPSDQLRQREMHFWVDQGLVXVHGWRH[WUDFW
WKHILHOGYDOXHVIURPLQVWDQFHVRIWKHFRUUHVSRQGLQJFRPSDQLRQW\SHV)RUWKLVUHDVRQ
unapplyPHWKRGVDUHFDOOHGH[WUDFWRUV
+HUHLVDQH[SDQGHGbutton.scalaZLWKDButtonobjectWKDWGHILQHVDQunapplyH[WUDFWRU
PHWKRG
// code-examples/AdvOOP/objects/button.scala

package objects
import ui3.Clickable

class Button(val label: String) extends Widget with Clickable {

Companion Objects | 129

Download at WoweBook.Com
def click() = {
// Logic to give the appearance of clicking a button...
}

def draw() = {
// Logic to draw the button on the display, web page, etc.
}

override def toString() = "(button: label="+label+", "+super.toString()+")"


}

object Button {
def unapply(button: Button) = Some(button.label)
}

Button.unapplyWDNHVDVLQJOHButtonDUJXPHQWDQGUHWXUQVDSomeZUDSSLQJWKH label
YDOXH7KLVGHPRQVWUDWHVWKHSURWRFROIRUunapplyPHWKRGV7KH\UHWXUQDSomeZUDS
SLQJWKHH[WUDFWHGILHOGV :H¦OOVHHKRZWRKDQGOHPRUHWKDQRQHILHOGLQDPRPHQW
+HUHLVDspecsobjectWKDWH[HUFLVHVButton.unapply
// code-examples/AdvOOP/objects/button-unapply-spec.scala

package objects
import org.specs._

object ButtonUnapplySpec extends Specification {


"Button.unapply" should {
"match a Button object" in {
val b = new Button("click me")
b match {
case Button(label) =>
case _ => fail()
}
}
"match a RadioButton object" in {
val b = new RadioButton(false, "click me")
b match {
case Button(label) =>
case _ => fail()
}
}
"not match a non-Button object" in {
val tf = new TextField("hello world!")
tf match {
case Button(label) => fail()
case _ =>
}
}
"extract the Button's label" in {
val b = new Button("click me")
b match {
case Button(label) => label mustEqual "click me"
case _ => fail()
}

130 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
}
"extract the RadioButton's label" in {
val rb = new RadioButton(false, "click me, too")
rb match {
case Button(label) => label mustEqual "click me, too"
case _ => fail()
}
}
}
}

7KH ILUVW WKUHH H[DPSOHV in FODXVHV  FRQILUP WKDW Button.unapply LV RQO\ FDOOHG IRU
DFWXDOButtonLQVWDQFHVRULQVWDQFHVRIGHULYHGFODVVHVOLNHRadioButton
6LQFHunapplyWDNHVDButtonDUJXPHQW LQWKLVFDVH WKH6FDODUXQWLPHW\SHFKHFNVWKH
LQVWDQFHEHLQJPDWFKHG,WWKHQORRNVIRUDFRPSDQLRQREMHFWZLWKDQunapplyPHWKRG
DQGLQYRNHVWKDWPHWKRGSDVVLQJWKHLQVWDQFH7KHGHIDXOWFDVHFODXVHcase _LVLQYRNHG
IRUWKHLQVWDQFHVWKDWGRQ¦WW\SHFKHFNDVFRPSDWLEOH7KHSDWWHUQPDWFKLQJSURFHVVLV
IXOO\W\SHVDIH
7KHUHPDLQLQJH[DPSOHV inFODXVHV FRQILUPWKDWWKHFRUUHFWYDOXHVIRUWKHlabelDUH
H[WUDFWHG7KH6FDODUXQWLPHDXWRPDWLFDOO\H[WUDFWVWKHLWHPLQWKHSome
:KDWDERXWH[WUDFWLQJPXOWLSOHILHOGV")RUDIL[HGVHWRINQRZQILHOGVDSomeZUDSSLQJ
DTupleLVUHWXUQHGDVVKRZQLQWKLVXSGDWHGYHUVLRQRIRadioButton
// code-examples/AdvOOP/objects/radio-button.scala

package objects

/**
* Button with two states, on or off, like an old-style,
* channel-selection botton on a radio.
*/
class RadioButton(val on: Boolean, label: String) extends Button(label)

object RadioButton {
def unapply(button: RadioButton) = Some((button.on, button.label))
// equivalent to: = Some(Pair(button.on, button.label))
}

$SomeZUDSSLQJDPair(button.on, button.label)LVUHWXUQHG$VZHGLVFXVVLQ£7KH
3UHGHI2EMHFW¤RQSDJH PairLVDW\SHGHILQHGWREHHTXDOWR Tuple2+HUHLVWKH
FRUUHVSRQGLQJspecsobjectWKDWWHVWVLW
// code-examples/AdvOOP/objects/radio-button-unapply-spec.scala

package objects
import org.specs._

object RadioButtonUnapplySpec extends Specification {


"RadioButton.unapply" should {
"should match a RadioButton object" in {
val b = new RadioButton(true, "click me")
b match {

Companion Objects | 131

Download at WoweBook.Com
case RadioButton(on, label) =>
case _ => fail()
}
}
"not match a Button (parent class) object" in {
val b = new Button("click me")
b match {
case RadioButton(on, label) => fail()
case _ =>
}
}
"not match a non-RadioButton object" in {
val tf = new TextField("hello world!")
tf match {
case RadioButton(on, label) => fail()
case _ =>
}
}
"extract the RadioButton's on/off state and label" in {
val b = new RadioButton(true, "click me")
b match {
case RadioButton(on, label) => {
label mustEqual "click me"
on mustEqual true
}
case _ => fail()
}
}
}
}

Apply and UnapplySeq for Collections


:KDWLI\RXZDQWWREXLOGDFROOHFWLRQIURPDYDULDEOHDUJXPHQWOLVWSDVVHGWRapply"
:KDWLI\RXZDQWWRH[WUDFWWKHILUVWIHZHOHPHQWVIURPDFROOHFWLRQDQG\RXGRQ¦WFDUH
DERXWWKHUHVWRILW"
,QWKLVFDVH\RXGHILQHapplyDQGunapplySeq £XQDSSO\VHTXHQFH¤ PHWKRGV+HUHDUH
WKRVHPHWKRGVIURP6FDOD¦VRZQListFODVV
def apply[A](xs: A*): List[A] = xs.toList

def unapplySeq[A](x: List[A]): Some[List[A]] = Some(x)

7KH[A]W\SHSDUDPHWHUL]DWLRQRQWKHVHPHWKRGVDOORZVWKHListobjectZKLFKLVQRW
SDUDPHWHUL]HG WR FRQVWUXFW D QHZ List[A] 6HH £8QGHUVWDQGLQJ 3DUDPHWHUL]HG
7\SHV¤RQSDJHIRUPRUHGHWDLOV 0RVWRIWKHWLPHWKHW\SHSDUDPHWHUZLOOEH
LQIHUUHGEDVHGRQWKHFRQWH[W
7KHSDUDPHWHUOLVWxs: A*LVDYDULDEOHDUJXPHQWOLVW&DOOHUVRIapplyFDQSDVVDVPDQ\
ALQVWDQFHVDVWKH\ZDQWLQFOXGLQJQRQH,QWHUQDOO\YDULDEOHDUJXPHQWOLVWVDUHVWRUHG
LQDQArray[A]ZKLFKLQKHULWVWKHtoListPHWKRGIURPIterableWKDWZHXVHGKHUH

132 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
7KLVLVDKDQG\LGLRPIRU$3,ZULWHUV$FFHSWLQJYDULDEOHDUJXPHQWVWR
DIXQFWLRQFDQEHFRQYHQLHQWIRUXVHUVDQGFRQYHUWLQJWKHDUJXPHQWV
WRDListLVRIWHQLGHDOIRULQWHUQDOPDQDJHPHQW

+HUHLVDQH[DPSOHVFULSWWKDWXVHVList.applyLPSOLFLWO\
// code-examples/AdvOOP/objects/list-apply-example-script.scala

val list1 = List()


val list2 = List(1, 2.2, "three", 'four)
val list3 = List("1", "2.2", "three", "four")
println("1: "+list1)
println("2: "+list2)
println("3: "+list3)

7KH'fourLVDV\PEROHVVHQWLDOO\DQLQWHUQHGVWULQJ6\PEROVDUHPRUHFRPPRQO\XVHG
LQ5XE\IRUH[DPSOHZKHUHWKHVDPHV\PEROZRXOGEHZULWWHQDV:four6\PEROVDUH
XVHIXOIRUUHSUHVHQWLQJLGHQWLWLHVFRQVLVWHQWO\
7KLVVFULSW\LHOGVWKHIROORZLQJRXWSXW
1: List()
2: List(1, 2.2, three, 'four)
3: List(1, 2.2, three, four)

7KHunapplySeqPHWKRGLVWULYLDOLWUHWXUQVWKHLQSXWOLVWZUDSSHGLQDSome+RZHYHU
WKLVLVVXIILFLHQWIRUSDWWHUQPDWFKLQJDVVKRZQLQWKLVH[DPSOH
// code-examples/AdvOOP/objects/list-unapply-example-script.scala

val list = List(1, 2.2, "three", 'four)


list match {
case List(x, y, _*) => println("x = "+x+", y = "+y)
case _ => throw new Exception("No match! "+list)
}

7KHList(x, y, _*)V\QWD[PHDQVZHZLOORQO\PDWFKRQDOLVWZLWKDWOHDVWWZRHOHPHQWV
DQGWKHILUVWWZRHOHPHQWVZLOOEHDVVLJQHGWRxDQGy:HGRQ¦WFDUHDERXWWKHUHVWRI
WKHOLVW7KH_*PDWFKHV]HURRUPRUHUHPDLQLQJHOHPHQWV
7KHRXWSXWLVWKHIROORZLQJ
x = 1, y = 2.2

:H¦OOKDYHPXFKPRUHWRVD\DERXWListDQGSDWWHUQPDWFKLQJLQ£/LVWVLQ)XQFWLRQDO
3URJUDPPLQJ¤RQSDJH

Companion Objects and Java Static Methods


7KHUHLVRQHPRUHWKLQJWRNQRZDERXWFRPSDQLRQREMHFWV:KHQHYHU\RXGHILQHD
mainPHWKRGWRXVHDVWKHHQWU\SRLQWIRUDQDSSOLFDWLRQ6FDODUHTXLUHV\RXWRSXWLWLQ
DQREMHFW+RZHYHUDWWKHWLPHRIWKLVZULWLQJ mainPHWKRGVFDQQRWEHGHILQHGLQD

Companion Objects | 133

Download at WoweBook.Com
FRPSDQLRQREMHFW%HFDXVHRILPSOHPHQWDWLRQGHWDLOVLQWKHJHQHUDWHGFRGHWKH-90
ZRQ¦WILQGWKH mainPHWKRG7KLVLVVXHPD\EHUHVROYHGLQDIXWXUHUHOHDVH)RUQRZ
\RXPXVWGHILQHDQ\mainPHWKRGLQDVLQJOHWRQREMHFW LHD£QRQFRPSDQLRQ¤REMHFW
VHH>6FDOD7LSV@ &RQVLGHUWKHIROORZLQJH[DPSOHRIDVLPSOH PersonFODVVDQGFRP
SDQLRQREMHFWWKDWDWWHPSWVWRGHILQHmain
// code-examples/AdvOOP/objects/person.scala

package objects

class Person(val name: String, val age: Int) {


override def toString = "name: " + name + ", age: " + age
}

object Person {
def apply(name: String, age: Int) = new Person(name, age)
def unapply(person: Person) = Some((person.name, person.age))

def main(args: Array[String]) = {


// Test the constructor...
val person = new Person("Buck Trends", 18)
assert(person.name == "Buck Trends")
assert(person.age == 21)
}
}

object PersonTest {
def main(args: Array[String]) = Person.main(args)
}

7KLVFRGHFRPSLOHVILQHEXWLI\RXDWWHPSWWRLQYRNHPerson.mainXVLQJscala -cp ...


objects.Person\RXJHWWKHIROORZLQJHUURU
java.lang.NoSuchMethodException: objects.Person.main([Ljava.lang.String;)

7KH objects/Person.classILOHH[LVWV,I\RXGHFRPSLOHLWZLWK javap -classpath ...


objects.Person UHIHU WR £7KH VFDODS MDYDS DQG MDG &RPPDQG/LQH
7RROV¤RQSDJH \RXFDQVHHWKDWLWGRHVQ¦WFRQWDLQD mainPHWKRG,I\RXGH
FRPSLOHobjects/Person$.classWKHILOHIRUWKHFRPSDQLRQREMHFW¦VE\WHFRGHLWKDVD
mainPHWKRGEXWQRWLFHWKDWLWLVQ¦WGHFODUHG static6RDWWHPSWLQJWRLQYRNH scala
-cp ... objects.Person$DOVRIDLOVWRILQGWKH£VWDWLF¤main
java.lang.NoSuchMethodException: objects.Person$.main is not static

7KHVHSDUDWHVLQJOHWRQREMHFW PersonTestGHILQHGLQWKLVH[DPSOHKDVWREHXVHG'H
FRPSLOLQJLWZLWKjavap -classpath ... objects.PersonTestVKRZVWKDWLWKDVDstatic
mainPHWKRG,I\RXLQYRNHLWXVLQJ scala -cp ... objects.PersonTestWKH PersonT
est.mainPHWKRGLVLQYRNHGZKLFKLQWXUQLQYRNHVPerson.main<RXJHWDQDVVHUWLRQ
HUURUIURPWKHVHFRQGFDOOWRassertZKLFKLVLQWHQWLRQDO
java.lang.AssertionError: assertion failed
at scala.Predef$.assert(Predef.scala:87)
at objects.Person$.test(person.scala:15)

134 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
at objects.PersonTest$.main(person.scala:20)
at objects.PersonTest.main(person.scala)
...

,QIDFWWKLVLVDJHQHUDOLVVXHZLWKPHWKRGVGHILQHGLQFRPSDQLRQREMHFWVWKDWQHHGWR
EHYLVLEOHWR-DYDFRGHDVVWDWLFPHWKRGV7KH\DUHQ¦WVWDWLFLQWKHE\WHFRGH<RXKDYH
WRSXWWKHVHPHWKRGVLQVLQJOHWRQREMHFWVLQVWHDG&RQVLGHUWKHIROORZLQJ-DYDFODVV
WKDWDWWHPSWVWRFUHDWHDXVHUZLWKPerson.apply
// code-examples/AdvOOP/objects/PersonUserWontCompile.java
// WON'T COMPILE

package objects;

public class PersonUserWontCompile {


public static void main(String[] args) {
Person buck = Person.apply("Buck Trends", 100); // ERROR
System.out.println(buck);
}
}

,IZHFRPSLOHLW DIWHUFRPSLOLQJPerson.scala ZHJHWWKHIROORZLQJHUURU


$ javac -classpath ... objects/PersonUserWontCompile.java
objects/PersonUserWontCompile.java:5: cannot find symbol
symbol : method apply(java.lang.String,int)
location: class objects.Person
Person buck = Person.apply("Buck Trends", 100);
^
1 error

+RZHYHUZHFDQXVHWKHIROORZLQJVLQJOHWRQREMHFW
// code-examples/AdvOOP/objects/person-factory.scala

package objects

object PersonFactory {
def make(name: String, age: Int) = new Person(name, age)
}

1RZWKHIROORZLQJ-DYDFODVVZLOOFRPSLOH
// code-examples/AdvOOP/objects/PersonUser.java

package objects;

public class PersonUser {


public static void main(String[] args) {
// The following line won't compile.
// Person buck = Person.apply("Buck Trends", 100);
Person buck = PersonFactory.make("Buck Trends", 100);
System.out.println(buck);
}
}

Companion Objects | 135

Download at WoweBook.Com
'RQRWGHILQHmainRUDQ\RWKHUPHWKRGLQDFRPSDQLRQREMHFWWKDWQHHGV
WREHYLVLEOHWR-DYDFRGHDVD staticPHWKRG'HILQHLWLQDVLQJOHWRQ
REMHFWLQVWHDG

,I\RXKDYHQRRWKHUFKRLFHEXWWRFDOODPHWKRGLQDFRPSDQLRQREMHFWIURP-DYD\RX
FDQH[SOLFLWO\FUHDWHDQLQVWDQFHRIWKHREMHFWZLWK newVLQFHWKHREMHFWLVD£UHJXODU¤
-DYDFODVVLQWKHE\WHFRGHDQGFDOOWKHPHWKRGRQWKHLQVWDQFH

Case Classes
,Q£0DWFKLQJRQ&DVH&ODVVHV¤RQSDJHZHEULHIO\LQWURGXFHG\RXWRFDVHFODVVHV
&DVHFODVVHVKDYHVHYHUDOXVHIXOIHDWXUHVEXWDOVRVRPHGUDZEDFNV
/HW¦VUHZULWHWKH ShapeH[DPSOHZHXVHGLQ£$7DVWHRI&RQFXUUHQF\¤RQSDJHWR
XVHFDVHFODVVHV+HUHLVWKHRULJLQDOLPSOHPHQWDWLRQ
// code-examples/IntroducingScala/shapes.scala

package shapes {
class Point(val x: Double, val y: Double) {
override def toString() = "Point(" + x + "," + y + ")"
}

abstract class Shape() {


def draw(): Unit
}

class Circle(val center: Point, val radius: Double) extends Shape {


def draw() = println("Circle.draw: " + this)
override def toString() = "Circle(" + center + "," + radius + ")"
}

class Rectangle(val lowerLeft: Point, val height: Double, val width: Double)
extends Shape {
def draw() = println("Rectangle.draw: " + this)
override def toString() =
"Rectangle(" + lowerLeft + "," + height + "," + width + ")"
}

class Triangle(val point1: Point, val point2: Point, val point3: Point)
extends Shape() {
def draw() = println("Triangle.draw: " + this)
override def toString() =
"Triangle(" + point1 + "," + point2 + "," + point3 + ")"
}
}

+HUHLVWKHH[DPSOHUHZULWWHQXVLQJWKHcaseNH\ZRUG
// code-examples/AdvOOP/shapes/shapes-case.scala

package shapes {

136 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
case class Point(x: Double, y: Double)

abstract class Shape() {


def draw(): Unit
}

case class Circle(center: Point, radius: Double) extends Shape() {


def draw() = println("Circle.draw: " + this)
}

case class Rectangle(lowerLeft: Point, height: Double, width: Double)


extends Shape() {
def draw() = println("Rectangle.draw: " + this)
}

case class Triangle(point1: Point, point2: Point, point3: Point)


extends Shape() {
def draw() = println("Triangle.draw: " + this)
}
}

$GGLQJWKH caseNH\ZRUGFDXVHVWKHFRPSLOHUWRDGGDQXPEHURIXVHIXOIHDWXUHVDX
WRPDWLFDOO\ 7KH NH\ZRUG VXJJHVWV DQ DVVRFLDWLRQ ZLWK case H[SUHVVLRQV LQ SDWWHUQ
PDWFKLQJ,QGHHGWKH\DUHSDUWLFXODUO\ZHOOVXLWHGIRUWKDWDSSOLFDWLRQDVZHZLOOVHH
)LUVWWKHFRPSLOHUDXWRPDWLFDOO\FRQYHUWVWKHFRQVWUXFWRUDUJXPHQWVLQWRLPPXWDEOH
ILHOGV valV 7KHvalNH\ZRUGLVRSWLRQDO,I\RXZDQWPXWDEOHILHOGVXVHWKHvarNH\
ZRUG6RRXUFRQVWUXFWRUDUJXPHQWOLVWVDUHQRZVKRUWHU
6HFRQGWKHFRPSLOHUDXWRPDWLFDOO\LPSOHPHQWVequalshashCodeDQGtoStringPHWK
RGVWRWKHFODVVZKLFKXVHWKHILHOGVVSHFLILHGDVFRQVWUXFWRUDUJXPHQWV6RZHQR
ORQJHUQHHGRXURZQtoStringPHWKRGV,QIDFWWKHJHQHUDWHGtoStringPHWKRGVSUR
GXFH WKH VDPH RXWSXWV DV WKH RQHV ZH LPSOHPHQWHG RXUVHOYHV $OVR WKH ERG\ RI
PointLVJRQHEHFDXVHWKHUHDUHQRPHWKRGVWKDWZHQHHGWRGHILQH
7KHIROORZLQJVFULSWXVHVWKHVHPHWKRGVWKDWDUHQRZLQWKHVKDSHV
// code-examples/AdvOOP/shapes/shapes-usage-example1-script.scala

import shapes._

val shapesList = List(


Circle(Point(0.0, 0.0), 1.0),
Circle(Point(5.0, 2.0), 3.0),
Rectangle(Point(0.0, 0.0), 2, 5),
Rectangle(Point(-2.0, -1.0), 4, 3),
Triangle(Point(0.0, 0.0), Point(1.0, 0.0), Point(0.0, 1.0)))

val shape1 = shapesList.head // grab the first one.


println("shape1: "+shape1+". hash = "+shape1.hashCode)
for (shape2 <- shapesList) {
println("shape2: "+shape2+". 1 == 2 ? "+(shape1 == shape2))
}

Case Classes | 137

Download at WoweBook.Com
7KLVVFULSWRXWSXWVWKHIROORZLQJ
shape1: Circle(Point(0.0,0.0),1.0). hash = 2061963534
shape2: Circle(Point(0.0,0.0),1.0). 1 == 2 ? true
shape2: Circle(Point(5.0,2.0),3.0). 1 == 2 ? false
shape2: Rectangle(Point(0.0,0.0),2.0,5.0). 1 == 2 ? false
shape2: Rectangle(Point(-2.0,-1.0),4.0,3.0). 1 == 2 ? false
shape2: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0)). 1 == 2 ? false

$VZH¦OOVHHLQ£(TXDOLW\RI2EMHFWV¤RQSDJHWKH==PHWKRGDFWXDOO\LQYRNHVWKH
equalsPHWKRG
(YHQRXWVLGHRIcaseH[SUHVVLRQVDXWRPDWLFJHQHUDWLRQRIWKHVHWKUHHPHWKRGVLVYHU\
FRQYHQLHQWIRUVLPSOH£VWUXFWXUDO¤FODVVHVLHFODVVHVWKDWFRQWDLQUHODWLYHO\VLPSOH
ILHOGVDQGEHKDYLRUV
7KLUGZKHQWKHcaseNH\ZRUGLVXVHGWKHFRPSLOHUDXWRPDWLFDOO\FUHDWHVDFRPSDQLRQ
REMHFW ZLWK DQ apply IDFWRU\ PHWKRG WKDW WDNHV WKH VDPH DUJXPHQWV DV WKH SULPDU\
FRQVWUXFWRU7KHSUHYLRXVH[DPSOHXVHGWKHDSSURSULDWH applyPHWKRGVWRFUHDWHWKH
PointsWKHGLIIHUHQW ShapesDQGDOVRWKH ListLWVHOI7KDW¦VZK\ZHGRQ¦WQHHG new
ZH¦UHDFWXDOO\FDOOLQJapply(x,y)LQWKHPointFRPSDQLRQREMHFWIRUH[DPSOH

<RXFDQKDYHVHFRQGDU\FRQVWUXFWRUVLQFDVHFODVVHVEXWWKHUHZLOOEH
QRRYHUORDGHGapplyPHWKRGJHQHUDWHGWKDWKDVWKHVDPHDUJXPHQWOLVW
<RX¦OOKDYHWRXVHnewWRFUHDWHLQVWDQFHVZLWKWKRVHFRQVWUXFWRUV

7KHFRPSDQLRQREMHFWDOVRJHWVDQ unapplyH[WUDFWRUPHWKRGZKLFKH[WUDFWVDOOWKH
ILHOGVRIDQLQVWDQFHLQDQHOHJDQWIDVKLRQ7KHIROORZLQJVFULSWGHPRQVWUDWHVWKHH[
WUDFWRUVLQSDWWHUQPDWFKLQJcaseVWDWHPHQWV
// code-examples/AdvOOP/shapes/shapes-usage-example2-script.scala

import shapes._

val shapesList = List(


Circle(Point(0.0, 0.0), 1.0),
Circle(Point(5.0, 2.0), 3.0),
Rectangle(Point(0.0, 0.0), 2, 5),
Rectangle(Point(-2.0, -1.0), 4, 3),
Triangle(Point(0.0, 0.0), Point(1.0, 0.0), Point(0.0, 1.0)))

def matchOn(shape: Shape) = shape match {


case Circle(center, radius) =>
println("Circle: center = "+center+", radius = "+radius)
case Rectangle(ll, h, w) =>
println("Rectangle: lower-left = "+ll+", height = "+h+", width = "+w)
case Triangle(p1, p2, p3) =>
println("Triangle: point1 = "+p1+", point2 = "+p2+", point3 = "+p3)
case _ =>
println("Unknown shape!"+shape)
}

138 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
shapesList.foreach { shape => matchOn(shape) }

7KLVVFULSWRXWSXWVWKHIROORZLQJ
Circle: center = Point(0.0,0.0), radius = 1.0
Circle: center = Point(5.0,2.0), radius = 3.0
Rectangle: lower-left = Point(0.0,0.0), height = 2.0, width = 5.0
Rectangle: lower-left = Point(-2.0,-1.0), height = 4.0, width = 3.0
Triangle: point1 = Point(0.0,0.0), point2 = Point(1.0,0.0), point3 = Point(0.0,1.0)

Syntactic Sugar for Binary Operations


%\WKHZD\UHPHPEHULQ£0DWFKLQJRQ6HTXHQFHV¤RQSDJHZKHQZHGLVFXVVHG
PDWFKLQJRQOLVWV":HZURWHWKLVcaseH[SUHVVLRQ
def processList(l: List[Any]): Unit = l match {
case head :: tail => ...
...
}

,WWXUQVRXWWKDWWKHIROORZLQJH[SUHVVLRQVDUHLGHQWLFDO
case head :: tail => ...
case ::(head, tail) => ...

:HDUHXVLQJWKHFRPSDQLRQREMHFWIRUWKHFDVHFODVVQDPHG::ZKLFKLVXVHGIRUQRQ
HPSW\OLVWV:KHQXVHGLQ caseH[SUHVVLRQVWKHFRPSLOHUVXSSRUWVWKLVVSHFLDOLQIL[
RSHUDWRUQRWDWLRQIRULQYRFDWLRQVRIunapply
,WZRUNVQRWRQO\IRUunapplyPHWKRGVZLWKWZRDUJXPHQWVEXWDOVRZLWKRQHRUPRUH
DUJXPHQWV:HFRXOGUHZULWHRXUmatchOnPHWKRGWKLVZD\
def matchOn(shape: Shape) = shape match {
case center Circle radius => ...
case ll Rectangle (h, w) => ...
case p1 Triangle (p2, p3) => ...
case _ => ...
}

)RU DQ unapply WKDW WDNHV RQH DUJXPHQW \RX ZRXOG KDYH WR LQVHUW DQ HPSW\ VHW RI
SDUHQWKHVHVWRDYRLGDSDUVLQJDPELJXLW\
case arg Foo () => ...

)URPWKHSRLQWRIYLHZRIFODULW\WKLVV\QWD[LVHOHJDQWIRUVRPHFDVHVZKHQWKHUHDUH
WZRDUJXPHQWV)RUOLVWV head :: tailPDWFKHVWKHH[SUHVVLRQVIRUEXLOGLQJXSOLVWV
VRWKHUHLVDEHDXWLIXOV\PPHWU\ZKHQWKHH[WUDFWLRQSURFHVVXVHVWKHVDPHV\QWD[
+RZHYHUWKHPHULWVRIWKLVV\QWD[DUHOHVVFOHDUIRURWKHUH[DPSOHVHVSHFLDOO\ZKHQ
WKHUHDUH1 DUJXPHQWV

Case Classes | 139

Download at WoweBook.Com
The copy Method in Scala Version 2.8
,Q6FDODYHUVLRQDQRWKHULQVWDQFHPHWKRGLVDXWRPDWLFDOO\JHQHUDWHGFDOOHGcopy
7KLVPHWKRGLVXVHIXOZKHQ\RXZDQWWRPDNHDQHZLQVWDQFHRIDFDVHFODVVWKDWLV
LGHQWLFDOWRDQRWKHULQVWDQFHZLWKDIHZILHOGVFKDQJHG&RQVLGHUWKHIROORZLQJH[DPSOH
VFULSW
// code-examples/AdvOOP/shapes/shapes-usage-example3-v28-script.scala
// Scala version 2.8 only.

import shapes._

val circle1 = Circle(Point(0.0, 0.0), 2.0)


val circle2 = circle1 copy (radius = 4.0)

println(circle1)
println(circle2)

7KH VHFRQG FLUFOH LV FUHDWHG E\ FRS\LQJ WKH ILUVW DQG VSHFLI\LQJ D QHZ UDGLXV 7KH
copyPHWKRGLPSOHPHQWDWLRQWKDWLVJHQHUDWHGE\WKHFRPSLOHUH[SORLWVWKHQHZQDPHG
DQGGHIDXOWSDUDPHWHUVLQ6FDODYHUVLRQZKLFKZHGLVFXVVHGLQ£0HWKRG'HIDXOW
DQG1DPHG$UJXPHQWV 6FDOD9HUVLRQ ¤RQSDJH7KHJHQHUDWHGLPSOHPHQWDWLRQ
RICircle.copyORRNVURXJKO\OLNHWKHIROORZLQJ
case class Circle(center: Point, radius: Double) extends Shape() {
...
def copy(center: Point = this.center, radius: Double = this.radius) =
new Circle(center, radius)
}

6RGHIDXOWYDOXHVDUHSURYLGHGIRUDOOWKHDUJXPHQWVWRWKHPHWKRG RQO\WZRLQWKLV
FDVH :KHQXVLQJWKHcopyPHWKRGWKHXVHUVSHFLILHVE\QDPHRQO\WKHILHOGVWKDWDUH
FKDQJLQJ7KHYDOXHVIRUWKHUHVWRIWKHILHOGVDUHXVHGZLWKRXWKDYLQJWRUHIHUHQFHWKHP
H[SOLFLWO\

Case Class Inheritance


'LG\RXQRWLFHWKDWWKHQHZShapesFRGHLQ£&DVH&ODVVHV¤RQSDJHGLGQRWSXWWKH
caseNH\ZRUGRQWKHDEVWUDFW ShapeFODVV"7KLVLVDOORZHGE\WKHFRPSLOHUEXWWKHUH
DUHUHDVRQVIRUQRWKDYLQJRQHFDVHFODVVLQKHULWDQRWKHU)LUVWLWFDQFRPSOLFDWHILHOG
LQLWLDOL]DWLRQ6XSSRVHZHPDNH ShapeDFDVHFODVV6XSSRVHZHZDQWWRDGGDVWULQJ
ILHOGWRDOOVKDSHVUHSUHVHQWLQJDQidWKDWWKHXVHUZDQWVWRVHW,WPDNHVVHQVHWRGHILQH
WKLVILHOGLQShape/HW¦VPDNHWKHVHWZRFKDQJHVWRShape
abstract case class Shape(id: String) {
def draw(): Unit
}

1RZWKHGHULYHGVKDSHVQHHGWRSDVVWKH idWRWKH ShapeFRQVWUXFWRU)RUH[DPSOH


CircleZRXOGEHFRPHWKHIROORZLQJ

140 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
case class Circle(id: String, center: Point, radius: Double) extends Shape(id){
def draw(): Unit
}

+RZHYHULI\RXFRPSLOHWKLVFRGH\RX¦OOJHWHUURUVOLNHWKHIROORZLQJ
... error: error overriding value id in class Shape of type String;
value id needs `override' modifier
case class Circle(id: String, center: Point, radius: Double) extends Shape(id){
^

5HPHPEHU WKDW ERWK GHILQLWLRQV RI id WKH RQH LQ Shape DQG WKH RQH LQ Circle DUH
FRQVLGHUHG val ILHOG GHILQLWLRQV 7KH HUURU PHVVDJH WHOOV XV WKH DQVZHU XVH WKH
override NH\ZRUG DV ZH GLVFXVVHG LQ £2YHUULGLQJ 0HPEHUV RI &ODVVHV DQG
7UDLWV¤RQSDJH6RWKHFRPSOHWHVHWRIUHTXLUHGPRGLILFDWLRQVDUHDVIROORZV
// code-examples/AdvOOP/shapes/shapes-case-id.scala

package shapesid {
case class Point(x: Double, y: Double)

abstract case class Shape(id: String) {


def draw(): Unit
}

case class Circle(override val id: String, center: Point, radius: Double)
extends Shape(id) {
def draw() = println("Circle.draw: " + this)
}

case class Rectangle(override val id: String, lowerLeft: Point,


height: Double, width: Double) extends Shape(id) {
def draw() = println("Rectangle.draw: " + this)
}

case class Triangle(override val id: String, point1: Point,


point2: Point, point3: Point) extends Shape(id) {
def draw() = println("Triangle.draw: " + this)
}
}

1RWHWKDWZHDOVRKDYHWRDGGWKHvalNH\ZRUGV7KLVZRUNVEXWLWLVVRPHZKDWXJO\
$PRUHRPLQRXVSUREOHPLQYROYHVWKHJHQHUDWHGequalsPHWKRGV8QGHULQKHULWDQFH
WKHequalsPHWKRGVGRQ¦WREH\DOOWKHVWDQGDUGUXOHVIRUUREXVWREMHFWHTXDOLW\:H¦OO
GLVFXVVWKRVHUXOHVLQ£(TXDOLW\RI2EMHFWV¤RQSDJH)RUQRZFRQVLGHUWKHIRO
ORZLQJH[DPSOH
// code-examples/AdvOOP/shapes/shapes-case-equals-ambiguity-script.scala

import shapesid._

case class FancyCircle(name: String, override val id: String,


override val center: Point, override val radius: Double)
extends Circle(id, center, radius) {
override def draw() = println("FancyCircle.draw: " + this)

Case Classes | 141

Download at WoweBook.Com
}

val fc = FancyCircle("me", "circle", Point(0.0,0.0), 10.0)


val c = Circle("circle", Point(0.0,0.0), 10.0)
format("FancyCircle == Circle? %b\n", (fc == c))
format("Circle == FancyCircle? %b\n", (c == fc))

,I\RXUXQWKLVVFULSW\RXJHWWKHIROORZLQJRXWSXW
FancyCircle == Circle? false
Circle == FancyCircle? true

6RCircle.equalsHYDOXDWHVWRtrueZKHQJLYHQDFancyCircleZLWKWKHVDPHYDOXHVIRU
WKH Circle ILHOGV 7KH UHYHUVH FDVH LVQ¦W WUXH :KLOH \RX PLJKW DUJXH WKDW DV IDU DV
CircleLVFRQFHUQHGWKH\UHDOO\DUHHTXDOPRVWSHRSOHZRXOGDUJXHWKDWWKLVLVDULVN\
£UHOD[HG¤LQWHUSUHWDWLRQRIHTXDOLW\,W¦VWUXHWKDWDIXWXUHYHUVLRQRI6FDODFRXOGJHQ
HUDWHequalsPHWKRGVIRUcaseFODVVHVWKDWGRH[DFWW\SHHTXDOLW\FKHFNLQJ
6RWKHFRQYHQLHQFHVSURYLGHGE\FDVHFODVVHVVRPHWLPHVOHDGWRSUREOHPV,WLVEHVWWR
DYRLGLQKHULWDQFHRIRQHFDVHFODVVE\DQRWKHU1RWHWKDWLW¦VILQHIRUDFDVHFODVVWR
LQKHULWIURPDQRQFDVHFODVVRUWUDLW,W¦VDOVRILQHIRUDQRQFDVHFODVVRUWUDLWWRLQKHULW
IURPDFDVHFODVV
%HFDXVHRIWKHVHLVVXHVLWLVSRVVLEOHWKDWFDVHFODVVLQKHULWDQFHZLOOEHGHSUHFDWHGDQG
UHPRYHGLQIXWXUHYHUVLRQVRI6FDOD

$YRLGLQKHULWLQJDFDVHFODVVIURPDQRWKHUFDVHFODVV

Equality of Objects
,PSOHPHQWLQJDUHOLDEOHHTXDOLW\WHVWIRULQVWDQFHVLVGLIILFXOWWRGRFRUUHFWO\(IIHFWLYH
-DYD >%ORFK@ DQGWKH6FDODGRFSDJHIRUAnyRef.equalsGHVFULEHWKHUHTXLUHPHQWV
IRUDJRRGHTXDOLW\WHVW$YHU\JRRGGHVFULSWLRQRIWKHWHFKQLTXHVIRUZULWLQJFRUUHFW
equalsDQGhashCodePHWKRGVFDQEHIRXQGLQ>2GHUVN\@ZKLFKXVHV-DYDV\QWD[
EXWLVDGDSWHGIURP&KDSWHURI3URJUDPPLQJLQ6FDOD >2GHUVN\@ &RQVXOW
WKHVHUHIHUHQFHVZKHQ\RXQHHGWRLPSOHPHQW\RXURZQequalsDQGhashCodePHWKRGV
5HFDOOWKDWWKHVHPHWKRGVDUHFUHDWHGDXWRPDWLFDOO\IRUcaseFODVVHV
+HUHZHIRFXVRQWKHGLIIHUHQWHTXDOLW\PHWKRGVDYDLODEOHLQ6FDODDQGWKHLUPHDQLQJV
7KHUH DUH VRPH VOLJKW LQFRQVLVWHQFLHV EHWZHHQ WKH 6FDOD VSHFLILFDWLRQ VHH >6FDOD6
SHF@  DQG WKH 6FDODGRF SDJHV IRU WKH HTXDOLW\UHODWHG PHWKRGV IRU Any DQG
AnyRefEXWWKHJHQHUDOEHKDYLRULVFOHDU

6RPHRIWKHHTXDOLW\PHWKRGVKDYHWKHVDPHQDPHVDVHTXDOLW\PHWKRGV
LQRWKHUODQJXDJHVEXWWKHVHPDQWLFVDUHVRPHWLPHVGLIIHUHQW

142 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
The equals Method
7KH equalsPHWKRGWHVWVIRUYDOXHHTXDOLW\7KDWLV obj1 equals obj2LVWUXHLIERWK
obj1DQGobj2KDYHWKHVDPHYDOXH7KH\GRQRWQHHGWRUHIHUWRWKHVDPHLQVWDQFH
+HQFHequalsEHKDYHVOLNHWKHequalsPHWKRGLQ-DYDDQGWKHeql?PHWKRGLQ5XE\

The == and != Methods


:KLOH==LVDQRSHUDWRULQPDQ\ODQJXDJHVLWLVDPHWKRGLQ6FDODGHILQHGDVfinalLQ
Any,WWHVWVIRUYDOXHHTXDOLW\OLNHequals7KDWLVobj1 == obj2LVWUXHLIERWKobj1DQG
obj2KDYHWKHVDPHYDOXH,QIDFW ==GHOHJDWHVWR equals+HUHLVSDUWRIWKH6FDODGRF
HQWU\IRUAny.==
o == arg0 is the same as o.equals(arg0).

+HUHLVWKHFRUUHVSRQGLQJSDUWRIWKH6FDODGRFHQWU\IRUAnyRef.==
o == arg0 is the same as if (o eq null) arg0 eq null else o.equals(arg0).

$V\RXZRXOGH[SHFW!=LVWKHQHJDWLRQLHLWLVHTXLYDOHQWWR!(obj1 == obj2)
6LQFH==DQG!=DUHGHFODUHGfinalLQAny\RXFDQ¦WRYHUULGHWKHPEXW\RXGRQ¦WQHHG
WRVLQFHWKH\GHOHJDWHWRequals

,Q -DYD & DQG & WKH == RSHUDWRU WHVWV IRU UHIHUHQFH QRW YDOXH
HTXDOLW\,QFRQWUDVW5XE\¦V==RSHUDWRUWHVWVIRUYDOXHHTXDOLW\:KDW
HYHUODQJXDJH\RX¦UHXVHGWRPDNHVXUHWRUHPHPEHUWKDWLQ6FDOD==
LVWHVWLQJIRUYDOXHHTXDOLW\

The ne and eq Methods


7KHeqPHWKRGWHVWVIRUUHIHUHQFHHTXDOLW\7KDWLVobj1 eq obj2LVWUXHLIERWKobj1DQG
obj2SRLQWWRWKHVDPHORFDWLRQLQPHPRU\7KHVHPHWKRGVDUHRQO\GHILQHGIRUAnyRef
+HQFHeqEHKDYHVOLNHWKH==RSHUDWRULQ-DYD&DQG&EXWQRW==LQ5XE\
7KHnePHWKRGLVWKHQHJDWLRQRIeqLHLWLVHTXLYDOHQWWR!(obj1 eq obj2)

Array Equality and the sameElements Method


&RPSDULQJWKHFRQWHQWVRIWZRArrayVGRHVQ¦WKDYHDQREYLRXVUHVXOWLQ6FDOD
scala> Array(1, 2) == Array(1, 2)
res0: Boolean = false

7KDW¦V D VXUSULVH 7KDQNIXOO\ WKHUH¦V D VLPSOH VROXWLRQ LQ WKH IRUP RI WKH
sameElementsPHWKRG
scala> Array(1, 2).sameElements(Array(1, 2))
res1: Boolean = true

Equality of Objects | 143

Download at WoweBook.Com
0XFKEHWWHU5HPHPEHUWRXVHsameElementsZKHQ\RXZDQWWRWHVWLIWZRArrayVFRQ
WDLQWKHVDPHHOHPHQWV
:KLOHWKLVPD\VHHPOLNHDQLQFRQVLVWHQF\HQFRXUDJLQJDQH[SOLFLWWHVWRIWKHHTXDOLW\
RIWZRPXWDEOHGDWDVWUXFWXUHVLVDFRQVHUYDWLYHDSSURDFKRQWKHSDUWRIWKHODQJXDJH
GHVLJQHUV ,Q WKH ORQJ UXQ LW VKRXOG VDYH \RX IURP XQH[SHFWHG UHVXOWV LQ \RXU
FRQGLWLRQDOV

Recap and What’s Next


:HH[SORUHGWKHILQHSRLQWVRIRYHUULGLQJPHPEHUVLQGHULYHGFODVVHV:HOHDUQHGDERXW
REMHFWHTXDOLW\FDVHFODVVHVDQGFRPSDQLRQFODVVHVDQGREMHFWV
,Q WKH QH[W FKDSWHU ZH¦OO OHDUQ DERXW WKH 6FDOD W\SH KLHUDUFK\¢LQ SDUWLFXODU WKH
PredefREMHFWWKDWLQFOXGHVPDQ\XVHIXOGHILQLWLRQV:H¦OODOVROHDUQDERXW6FDOD¦VDO
WHUQDWLYHWR-DYD¦VstaticFODVVPHPEHUVDQGWKHOLQHDUL]DWLRQUXOHVIRUPHWKRGORRNXS

144 | Chapter 6:—Advanced Object-Oriented Programming In Scala

Download at WoweBook.Com
CHAPTER 7
The Scala Object System

The Predef Object


)RU\RXUFRQYHQLHQFHZKHQHYHU\RXFRPSLOHFRGHWKH6FDODFRPSLOHUDXWRPDWLFDOO\
LPSRUWVWKHGHILQLWLRQVLQWKH java.langSDFNDJH javacGRHVWKLVWRR 2QWKH1(7
SODWIRUPLWLPSRUWVWKHsystemSDFNDJH7KHFRPSLOHUDOVRLPSRUWVWKHGHILQLWLRQVLQ
WKHDQDORJRXV6FDODSDFNDJHscala+HQFHFRPPRQ-DYDRU1(7W\SHVFDQEHXVHG
ZLWKRXWH[SOLFLWO\LPSRUWLQJWKHPRUIXOO\TXDOLI\LQJWKHPZLWKWKHjava.lang.SUHIL[
LQWKH-DYDFDVH6LPLODUO\DQXPEHURIFRPPRQ6FDODVSHFLILFW\SHVDUHPDGHDYDLODEOH
ZLWKRXWTXDOLILFDWLRQVXFKDV List:KHUHWKHUHDUH-DYDDQG6FDODW\SHQDPHVWKDW
RYHUODSOLNHStringWKH6FDODYHUVLRQLVLPSRUWHGODVWVRLW£ZLQV¤
7KHFRPSLOHUDOVRDXWRPDWLFDOO\LPSRUWVWKH PredefREMHFWZKLFKGHILQHVRULPSRUWV
VHYHUDOXVHIXOW\SHVREMHFWVDQGIXQFWLRQV

<RXFDQOHDUQDORWRI6FDODE\YLHZLQJWKHVRXUFHIRUPredef,WLVDYDLO
DEOHE\FOLFNLQJWKH£VRXUFH¤OLQNLQWKH Predef6FDODGRFSDJHRU\RX
FDQ GRZQORDG WKH IXOO VRXUFH FRGH IRU 6FDOD DW KWWSZZZVFDODODQJ
RUJ

7DEOHVKRZVDSDUWLDOOLVWRIWKHLWHPVLPSRUWHGRUGHILQHGE\ PredefRQWKH-DYD
SODWIRUP
7DEOH,WHPVLPSRUWHGRUGHILQHGE\3UHGHI
Types Character, Class, Error, Function, Integer, Map, Pair, Runnable, Set, String, Throwa
ble, Triple.
Exceptions Exception, ArrayIndexOutOfBoundsException, ClassCastException, IllegalArgumen
tException, IndexOutOfBoundsException, NoSuchElementException, NullPointerEx
ception, NumberFormatException, RuntimeException, StringIndexOutOfBoundsExcep
tion, UnsupportedOperationException.
Values Map, Set.

145

Download at WoweBook.Com
Objects Pair, Triple.
Classes Ensuring, ArrowAssoc.
Methods Factory methods to create tuples; overloaded versions of exit, error, assert, assume, and require;
implicit type conversion methods; I/O methods like readLine, println, and format; and a method
currentThread, which calls java.lang.Thread.currentThread.

PredefGHFODUHVWKHW\SHVDQGH[FHSWLRQVOLVWHGLQWKHWDEOHXVLQJWKH typeNH\ZRUG
7KH\DUHGHILQLWLRQVWKDWHTXDOWKHFRUUHVSRQGLQJ scala.<Type>RU java.lang.<Type>
FODVVHVVRWKH\EHKDYHOLNH£DOLDVHV¤RULPSRUWVIRUWKHFRUUHVSRQGLQJFODVVHV)RUH[
DPSOHStringLVGHFODUHGDVIROORZV
type String = java.lang.String

,Q WKLV FDVH WKH GHFODUDWLRQ KDV WKH VDPH QHW HIIHFW DV DQ import java.lang.String
VWDWHPHQWZRXOGKDYH
%XWGLGQ¦WZHMXVWVD\WKDWGHILQLWLRQVLQ java.langDUHLPSRUWHGDXWRPDWLFDOO\OLNH
String"7KHUHDVRQWKHUHLVDW\SHGHILQLWLRQLVWRHQDEOHVXSSRUWIRUDXQLIRUPVWULQJ
W\SHDFURVVDOOUXQWLPHHQYLURQPHQWV7KHGHILQLWLRQLVRQO\UHGXQGDQWRQWKH-90
7KHW\SHPairLVDQ£DOLDV¤IRUTuple2
type Pair[+A, +B] = Tuple2[A, B]

7KHUH DUH WZR W\SH SDUDPHWHUV A DQG B RQH IRU HDFK LWHP LQ WKH SDLU 5HFDOO IURP
£$EVWUDFW7\SHV$QG3DUDPHWHUL]HG7\SHV¤RQSDJHWKDWZHH[SODLQHGWKHPHDQLQJ
RIWKH+LQIURQWRIHDFKW\SHSDUDPHWHU
%ULHIO\DPair[A2,B2]IRUVRPHA2DQGB2LVDVXEFODVVRIPair[A1,B1]IRUVRPHA1DQG
B1LIA2LVDVXEW\SHRIA1DQGB2LVDVXEW\SHRIB1,Q£8QGHUVWDQGLQJ3DUDPHWHUL]HG
7\SHV¤RQSDJHZH¦OOGLVFXVV+DQGRWKHUW\SHTXDOLILHUVLQPRUHGHWDLO
7KHPairFODVVDOVRKDVDFRPSDQLRQREMHFWPairZLWKDQapplyIDFWRU\PHWKRGDVGLV
FXVVHGLQ£&RPSDQLRQ2EMHFWV¤RQSDJH+HQFHZHFDQFUHDWHPairLQVWDQFHVDV
LQWKLVH[DPSOH
val p = Pair(1, "one")

Pair.applyLVFDOOHGZLWKWKHWZRDUJXPHQWV7KHW\SHVADQGBVKRZQLQWKHGHILQLWLRQ
RIPairDUHLQIHUUHG$QHZTuple2LQVWDQFHLVUHWXUQHG
Map DQG Set DSSHDU LQ ERWK WKH W\SHV DQG YDOXHV OLVWV ,Q WKH YDOXHV OLVW WKH\ DUH
DVVLJQHG WKH FRPSDQLRQ REMHFWV scala.collection.immutable.Map DQG scala.collec
tion.immutable.SetUHVSHFWLYHO\+HQFH MapDQG SetLQ PredefDUHYDOXHVQRWREMHFW
GHILQLWLRQVEHFDXVHWKH\UHIHUWRREMHFWVGHILQHGHOVHZKHUHZKHUHDV PairDQG Triple
DUH GHILQHG LQ Predef LWVHOI 7KH W\SHV Map DQG Set DUH DVVLJQHG WKH FRUUHVSRQGLQJ
LPPXWDEOHFODVVHV

146 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
7KHArrowAssocFODVVGHILQHVWZRPHWKRGV->DQGWKH8QLFRGHHTXLYDOHQW→7KHXWLOLW\
RIWKHVHPHWKRGVZDVGHPRQVWUDWHGSUHYLRXVO\LQ£2SWLRQ6RPHDQG1RQH$YRLGLQJ
QXOOV¤RQSDJHZKHUHZHFUHDWHGDPDSRI86VWDWHFDSLWDOV
val stateCapitals = Map(
"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
// ...
"Wyoming" -> "Cheyenne")
// ...

7KHGHILQLWLRQRIWKH ArrowAssocFODVVDQGWKH MapDQG SetYDOXHVLQ PredefPDNHWKH


FRQYHQLHQWMapLQLWLDOL]DWLRQV\QWD[SRVVLEOH)LUVWZKHQ6FDODVHHVMap(...)LWFDOOVWKH
applyPHWKRGRQWKHMapFRPSDQLRQREMHFWMXVWDVZHGLVFXVVHGIRUPair
Map.applyH[SHFWV]HURRUPRUHPairs HJ(a1, b2), (a2, b2), ... ZKHUHHDFKWXSOH
KROGVDQDPHDQGYDOXH,QWKHH[DPSOHWKHWXSOHW\SHVDUHDOOLQIHUUHGWREHRIW\SH
Pair[String,String]7KHGHFODUDWLRQRIMap.applyLVDVIROORZV
object Map {
...
def apply[A, B](elems : (A, B)*) : Map[A, B] = ...
}

5HFDOOWKDWWKHUHFDQEHQRW\SHSDUDPHWHUVRQWKHMapFRPSDQLRQREMHFWEHFDXVHWKHUH
FDQEHRQO\RQHLQVWDQFH+RZHYHUapplyFDQKDYHW\SHSDUDPHWHUV
7KHDSSO\PHWKRGWDNHVDYDULDEOHOHQJWKDUJXPHQWOLVW,QWHUQDOO\xZLOOEHDVXEW\SH
RIArray[X]6RIRU Map.applyelemsLVRIW\SHArray[(A,B)]RUArray[Tuple2[A,B]]LI
\RXSUHIHU
6RQRZWKDWZHNQRZZKDWMap.applyH[SHFWVKRZGRZHJHWIURPa -> bWR(a, b)"
Predef DOVR GHILQHV DQ LPSOLFLW W\SH FRQYHUVLRQ PHWKRG FDOOHG any2ArrowAssoc 7KH
FRPSLOHUNQRZVWKDW StringGRHVQRWGHILQHD ->PHWKRGVRLWORRNVIRUDQLPSOLFLW
FRQYHUVLRQ LQ VFRSH WR D W\SH WKDW GHILQHV VXFK D PHWKRG VXFK DV ArrowAssoc 7KH
any2ArrowAssocPHWKRGSHUIRUPVWKDWFRQYHUVLRQ,WKDVWKHIROORZLQJLPSOHPHQWDWLRQ
implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)

,WLVDSSOLHGWRHDFKLWHPWRWKHOHIWRIDQDUURZ ->HJWKH "Alabama"VWULQJ7KHVH


VWULQJVDUHZUDSSHGLQArrowAssocLQVWDQFHVXSRQZKLFKWKH->PHWKRGLVWKHQLQYRNHG
7KLVPHWKRGKDVWKHIROORZLQJLPSOHPHQWDWLRQ
class ArrowAssoc[A](x: A) {
...
def -> [B](y: B): Tuple2[A, B] = Tuple2(x, y)
}

:KHQLWLVLQYRNHGLWLVSDVVHGWKHVWULQJRQWKHULJKWKDQGVLGHRIWKH->7KHPHWKRG
UHWXUQVDWXSOHZLWKWKHYDOXH ("Alabama", "Montgomery")IRUH[DPSOH,QWKLVZD\
HDFKkey -> valueLVFRQYHUWHGLQWRDWXSOHDQGWKHUHVXOWLQJFRPPDVHSDUDWHGOLVWRI
WXSOHVLVSDVVHGWRWKHMap.applyIDFWRU\PHWKRG

The Predef Object | 147

Download at WoweBook.Com
7KHGHVFULSWLRQPD\VRXQGFRPSOLFDWHGDWILUVWEXWWKHEHDXW\RI6FDODLVWKDWWKLVPDS
LQLWLDOL]DWLRQV\QWD[LVQRWDQDGKRFODQJXDJHIHDWXUHVXFKDVDVSHFLDOSXUSRVHRSHU
DWRU ->GHILQHGLQWKHODQJXDJHJUDPPDU,QVWHDGWKLVV\QWD[LVGHILQHGZLWKQRUPDO
GHILQLWLRQVRIW\SHVDQGPHWKRGVFRPELQHGZLWKDIHZJHQHUDOSXUSRVHSDUVLQJFRQ
YHQWLRQVVXFKDVVXSSRUWIRULPSOLFLWV)XUWKHUPRUHLWLVDOOW\SHVDIH<RXFDQXVHWKH
VDPHWHFKQLTXHVWRZULWH\RXURZQFRQYHQLHQW£RSHUDWRUV¤IRUPLQL'RPDLQ6SHFLILF
/DQJXDJHV VHH&KDSWHU 
,PSOLFLW W\SH FRQYHUVLRQV DUH GLVFXVVHG LQ PRUH GHWDLO LQ £,PSOLFLW &RQYHU
VLRQV¤RQSDJH
1H[W UHFDOO IURP &KDSWHU  WKDW ZH ZHUH DEOH WR UHSODFH FDOOV WR
Console.println(...) ZLWK println(...) 7KLV £EDUH¤ println PHWKRG LV GHILQHG LQ
PredefWKHQLPSRUWHGDXWRPDWLFDOO\E\WKHFRPSLOHU7KHGHILQLWLRQFDOOVWKHFRUUH
VSRQGLQJPHWKRGLQ Console6LPLODUO\DOOWKHRWKHU,2PHWKRGVGHILQHGE\ Predef
HJreadLineDQGformatFDOOWKHFRUUHVSRQGLQJConsolePHWKRGV
)LQDOO\ WKH assert assume DQG require PHWKRGV DUH HDFK RYHUORDGHG ZLWK YDULRXV
DUJXPHQWOLVWRSWLRQV7KH\DUHXVHGIRUUXQWLPHWHVWLQJRIERROHDQFRQGLWLRQV,ID
FRQGLWLRQLVIDOVHDQH[FHSWLRQLVWKURZQ7KHEnsuringFODVVVHUYHVDVLPLODUSXUSRVH
<RXFDQXVHWKHVHIHDWXUHVIRU'HVLJQE\&RQWUDFWSURJUDPPLQJDVGLVFXVVHGLQ£%HWWHU
'HVLJQZLWK'HVLJQ%\&RQWUDFW¤RQSDJH
)RUWKHIXOOOLVWRIIHDWXUHVGHILQHGE\PredefVHHWKHFRUUHVSRQGLQJ6FDODGRFHQWU\LQ
>6FDOD$3,@

Four Ways to Create a Two-Item Tuple


:HQRZNQRZIRXUZD\VWRFUHDWHDWZRLWHPWXSOH WZRSOH" 
 £+HOOR¤
 3DLU £+HOOR¤
 7XSOH £+HOOR¤
 £+HOOR¤z

Classes and Objects: Where Are the Statics?


0DQ\REMHFWRULHQWHGODQJXDJHVDOORZFODVVHVWRKDYHFODVVOHYHOFRQVWDQWVILHOGVDQG
PHWKRGVFDOOHG£VWDWLF¤PHPEHUVLQ-DYD&DQG&7KHVHFRQVWDQWVILHOGVDQG
PHWKRGVDUHQRWDVVRFLDWHGZLWKDQ\LQVWDQFHVRIWKHFODVV
$QH[DPSOHRIDFODVVOHYHOILHOGLVDVKDUHGORJJLQJLQVWDQFHXVHGE\DOOLQVWDQFHVRID
FODVVIRUORJJLQJPHVVDJHV$QH[DPSOHRIDFODVVOHYHOFRQVWDQWLVWKHGHIDXOWORJJLQJ
£WKUHVKROG¤OHYHO

148 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
$QH[DPSOHRIDFODVVOHYHOPHWKRGLVD£ILQGHU¤PHWKRGWKDWORFDWHVDOOLQVWDQFHVRI
WKHFODVVLQVRPHUHSRVLWRU\WKDWPDWFKVRPHXVHUVSHFLILHGFULWHULD$QRWKHUH[DPSOH
LV D IDFWRU\ PHWKRG DV XVHG LQ RQH RI WKH IDFWRU\UHODWHG GHVLJQ SDWWHUQV VHH
>*2)@ 
7RUHPDLQFRQVLVWHQWZLWKWKHJRDOWKDW£HYHU\WKLQJLVDQREMHFW¤LQ6FDODFODVVOHYHO
ILHOGVDQGPHWKRGVDUHQRWVXSSRUWHG,QVWHDG6FDODVXSSRUWVGHFODUDWLRQVRIFODVVHV
WKDW DUH VLQJOHWRQV XVLQJ WKH object NH\ZRUG LQVWHDG RI WKH class NH\ZRUG 7KH
objects SURYLGH DQ REMHFWRULHQWHG DSSURDFK WR £VWDWLF¤ GDWD DQG PHWKRGV +HQFH
6FDODGRHVQRWHYHQKDYHDstaticNH\ZRUG
ObjectsDUHLQVWDQWLDWHGDXWRPDWLFDOO\DQGOD]LO\E\WKHUXQWLPHV\VWHP VHH6HFWLRQ
RI>6FDOD6SHF@ -XVWDVIRUFODVVHVDQGWUDLWVWKHERG\RIWKH objectLVWKHFRQ
VWUXFWRUEXWVLQFHWKHV\VWHPLQVWDQWLDWHVWKHREMHFWWKHUHLVQRZD\IRUWKHXVHUWR
VSHFLI\DSDUDPHWHUOLVWIRUWKHFRQVWUXFWRUVRWKH\DUHQ¦WVXSSRUWHG$Q\GDWDGHILQHG
LQWKHREMHFWKDVWREHLQLWLDOL]HGZLWKGHIDXOWYDOXHV)RUWKHVDPHUHDVRQVDX[LOLDU\
FRQVWUXFWRUVFDQ¦WEHXVHGDQGDUHQRWVXSSRUWHG
:H¦YHDOUHDG\VHHQVRPHH[DPSOHVRIREMHFWVVXFKDVWKHspecsREMHFWVXVHGSUHYLRXVO\
IRUWHVWVDQGWKHPairW\SHDQGLWVFRPSDQLRQREMHFWZKLFKZHH[SORUHGLQ£7KH3UHGHI
2EMHFW¤RQSDJH
type Pair[+A, +B] = Tuple2[A, B]
object Pair {
def apply[A, B](x: A, y: B) = Tuple2(x, y)
def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x)
}

7R UHIHUHQFH DQ REMHFW ILHOG RU PHWKRG \RX XVH WKH V\QWD[ object_name.field RU
object_name.method(...)UHVSHFWLYHO\)RUH[DPSOH Pair.apply(...)1RWHWKDWWKLV
LVWKHVDPHV\QWD[WKDWLVFRPPRQO\XVHGLQODQJXDJHVZLWKVWDWLFILHOGVDQGPHWKRGV

:KHQDQREMHFWQDPHGMyObjectLVFRPSLOHGWRDFODVVILOHWKHFODVVILOH
QDPHZLOOEHMyObject$.class

,Q-DYDDQG&WKHFRQYHQWLRQIRUGHILQLQJFRQVWDQWVLVWRXVH final staticILHOGV


&DOVRKDVDconstantNH\ZRUGIRUVLPSOHILHOGVOLNHintsDQGstrings ,Q6FDODWKH
FRQYHQWLRQLVWRXVHvalILHOGVLQREMHFWV
)LQDOO\UHFDOOIURP£1HVWHG&ODVVHV¤RQSDJHWKDWFODVVGHILQLWLRQVFDQEHQHVWHG
ZLWKLQRWKHUFODVVGHILQLWLRQV7KLVSURSHUW\JHQHUDOL]HVIRUREMHFWV<RXFDQGHILQH
QHVWHGREMHFWVWUDLWVDQGFODVVHVLQVLGHRWKHUREMHFWVWUDLWVDQGFODVVHV

Classes and Objects: Where Are the Statics? | 149

Download at WoweBook.Com
Package Objects
6FDODYHUVLRQLQWURGXFHVDQHZVFRSLQJFRQVWUXFWFDOOHGSDFNDJHREMHFWV7KH\DUH
XVHGWRGHILQHW\SHVYDULDEOHVDQGPHWKRGVWKDWDUHYLVLEOHDWWKHOHYHORIWKHFRUUH
VSRQGLQJ SDFNDJH 7R XQGHUVWDQG WKHLU XVHIXOQHVV OHW¦V VHH DQ H[DPSOH IURP 6FDOD
YHUVLRQ  LWVHOI 7KH FROOHFWLRQ OLEUDU\ LV EHLQJ UHRUJDQL]HG WR UHILQH WKH SDFNDJH
VWUXFWXUHDQGWRXVHLWPRUHFRQVLVWHQWO\ DPRQJRWKHUFKDQJHV 7KH6FDODWHDPIDFHG
DGLOHPPD7KH\ZDQWHGWRPRYHW\SHVWRQHZSDFNDJHVEXWDYRLGEUHDNLQJEDFNZDUG
FRPSDWLELOLW\ 7KH package object FRQVWUXFW SURYLGHG D VROXWLRQ DORQJ ZLWK RWKHU
EHQHILWV
)RUH[DPSOHWKHLPPXWDEOHListLVGHILQHGLQWKHscalaSDFNDJHLQYHUVLRQEXWLW
LV PRYHG WR WKH scala.collection.immutable SDFNDJH LQ YHUVLRQ  'HVSLWH WKH
FKDQJHListLVPDGHYLVLEOHLQWKH scalaSDFNDJHXVLQJpackage object scalaIRXQG
LQWKHVUFOLEUDU\VFDODSDFNDJHVFDODILOHLQWKHYHUVLRQVRXUFHFRGHGLVWULEXWLRQ
1RWHWKHILOHQDPH,W¦VQRWUHTXLUHGEXWLW¦VDXVHIXOFRQYHQWLRQIRUSDFNDJHREMHFWV
+HUHLVWKHIXOOSDFNDJHREMHFWGHILQLWLRQ DWWKHWLPHRIWKLVZULWLQJLWFRXOGFKDQJH
EHIRUHWKHILQDOYHUVLRQLVUHOHDVHG 
package object scala {
type Iterable[+A] = scala.collection.Iterable[A]
val Iterable = scala.collection.Iterable

@deprecated("use Iterable instead") type Collection[+A] = Iterable[A]


@deprecated("use Iterable instead") val Collection = Iterable

type Seq[+A] = scala.collection.Sequence[A]


val Seq = scala.collection.Sequence

type RandomAccessSeq[+A] = scala.collection.Vector[A]


val RandomAccessSeq = scala.collection.Vector

type Iterator[+A] = scala.collection.Iterator[A]


val Iterator = scala.collection.Iterator

type BufferedIterator[+A] = scala.collection.BufferedIterator[A]

type List[+A] = scala.collection.immutable.List[A]


val List = scala.collection.immutable.List

val Nil = scala.collection.immutable.Nil

type ::[A] = scala.collection.immutable.::[A]


val :: = scala.collection.immutable.::

type Stream[+A] = scala.collection.immutable.Stream[A]


val Stream = scala.collection.immutable.Stream

type StringBuilder = scala.collection.mutable.StringBuilder


val StringBuilder = scala.collection.mutable.StringBuilder
}

150 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
1RWHWKDWSDLUVRIGHFODUDWLRQVOLNHtype List[+] = ...DQGval List = ...DUHHIIHF
WLYHO\£DOLDVHV¤IRUWKHFRPSDQLRQFODVVDQGREMHFWUHVSHFWLYHO\%HFDXVHWKHFRQWHQWV
RIWKHscalaSDFNDJHDUHDXWRPDWLFDOO\LPSRUWHGE\WKHFRPSLOHU\RXFDQVWLOOUHIHUHQFH
DOOWKHGHILQLWLRQVLQWKLVREMHFWLQDQ\VFRSHZLWKRXWDQH[SOLFLWLPSRUWVWDWHPHQWIRU
IXOO\TXDOLILHGQDPHV
2WKHUWKDQWKHZD\WKHPHPEHUVLQSDFNDJHREMHFWVDUHVFRSHGWKH\EHKDYHMXVWOLNH
RWKHUREMHFWGHFODUDWLRQV:KLOHWKLVH[DPSOHFRQWDLQVRQO\ valVDQG typeV\RXFDQ
DOVRGHILQHPHWKRGVDQG\RXFDQVXEFODVVDQRWKHUFODVVRUWUDLWDQGPL[LQRWKHUWUDLWV
$QRWKHUEHQHILWRISDFNDJHREMHFWVLVWKDWLWSURYLGHVDPRUHVXFFLQFWLPSOHPHQWDWLRQ
RIZKDWZDVDQDZNZDUGLGLRPEHIRUH:LWKRXWSDFNDJHREMHFWV\RXZRXOGKDYHWR
SXWGHILQLWLRQVLQDQDGKRFREMHFWLQVLGHWKHGHVLUHGSDFNDJHWKHQLPSRUWIURPWKH
REMHFW)RUH[DPSOHKHUHLVKRZ ListZRXOGKDYHWREHKDQGOHGZLWKRXWDSDFNDJH
REMHFW
package scala {
object toplevel {
...
type List[+A] = scala.collection.immutable.List[A]
val List = scala.collection.immutable.List
...
}
}

...
import scala.toplevel._
...

)LQDOO\DQRWKHUEHQHILWRISDFNDJHREMHFWVLVWKHZD\WKH\SURYLGHDFOHDUVHSDUDWLRQ
EHWZHHQWKHDEVWUDFWLRQVH[SRVHGE\DSDFNDJHDQGWKHLPSOHPHQWDWLRQVWKDWVKRXOG
EHKLGGHQLQVLGHLW,QDODUJHUDSSOLFDWLRQDSDFNDJHREMHFWFRXOGEHXVHGWRH[SRVH
DOOWKHSXEOLFW\SHVYDOXHVDQGRSHUDWLRQV PHWKRGV IRUD£FRPSRQHQW¤ZKLOHHY
HU\WKLQJHOVHLQWKHSDFNDJHDQGQHVWHGSDFNDJHVFRXOGEHWUHDWHGDVLQWHUQDOLPSOH
PHQWDWLRQGHWDLOV

Sealed Class Hierarchies


5HFDOOIURP£&DVH&ODVVHV¤RQSDJHWKDWZHGHPRQVWUDWHGSDWWHUQPDWFKLQJZLWK
RXUShapesKLHUDUFK\ZKLFKXVHFDVHFODVVHV:HKDGDGHIDXOWcase _ => ...H[SUHV
VLRQ,W¦VXVXDOO\ZLVHWRKDYHRQH2WKHUZLVHLIVRPHRQHGHILQHVDQHZVXEW\SHRI
ShapeDQGSDVVHVLWWRWKLVmatchVWDWHPHQWDUXQWLPHscala.MatchErrorZLOOEHWKURZQ
EHFDXVHWKHQHZVKDSHZRQ¦WPDWFKWKHVKDSHVFRYHUHGLQWKHPDWFKVWDWHPHQW+RZ
HYHULW¦VQRWDOZD\VSRVVLEOHWRGHILQHUHDVRQDEOHEHKDYLRUIRUWKHGHIDXOWFDVH
7KHUHLVDQDOWHUQDWLYHVROXWLRQLI\RXNQRZWKDWWKHFDVHFODVVKLHUDUFK\LVXQOLNHO\WR
FKDQJHDQG\RXFDQGHILQHWKHZKROHKLHUDUFK\LQRQHILOH,QWKLVVLWXDWLRQ\RXFDQ
DGGWKHsealedNH\ZRUGWRWKHGHFODUDWLRQRIWKHFRPPRQEDVHFODVV:KHQVHDOHGWKH

Sealed Class Hierarchies | 151

Download at WoweBook.Com
FRPSLOHUNQRZVDOOWKHSRVVLEOHFODVVHVWKDWFRXOGDSSHDULQWKHmatchH[SUHVVLRQEH
FDXVHDOORIWKHPPXVWEHGHILQHGLQWKHVDPHVRXUFHILOH6RLI\RXFRYHUDOOWKRVH
FODVVHVLQWKHcaseH[SUHVVLRQV HLWKHUH[SOLFLWO\RUWKURXJKVKDUHGSDUHQWFODVVHV WKHQ
\RXFDQVDIHO\HOLPLQDWHWKHGHIDXOWcaseH[SUHVVLRQ
+HUHLVDQH[DPSOHXVLQJWKH+773PHWKRGV VHH>+773@ ZKLFKDUHQRWOLNHO\
WRFKDQJHYHU\RIWHQVRZHGHFODUHD£VHDOHG¤VHWRIFDVHFODVVHVIRUWKHP
// code-examples/ObjectSystem/sealed/http-script.scala

sealed abstract class HttpMethod()


case class Connect(body: String) extends HttpMethod
case class Delete (body: String) extends HttpMethod
case class Get (body: String) extends HttpMethod
case class Head (body: String) extends HttpMethod
case class Options(body: String) extends HttpMethod
case class Post (body: String) extends HttpMethod
case class Put (body: String) extends HttpMethod
case class Trace (body: String) extends HttpMethod

def handle (method: HttpMethod) = method match {


case Connect (body) => println("connect: " + body)
case Delete (body) => println("delete: " + body)
case Get (body) => println("get: " + body)
case Head (body) => println("head: " + body)
case Options (body) => println("options: " + body)
case Post (body) => println("post: " + body)
case Put (body) => println("put: " + body)
case Trace (body) => println("trace: " + body)
}

val methods = List(


Connect("connect body..."),
Delete ("delete body..."),
Get ("get body..."),
Head ("head body..."),
Options("options body..."),
Post ("post body..."),
Put ("put body..."),
Trace ("trace body..."))

methods.foreach { method => handle(method) }

7KLVVFULSWRXWSXWVWKHIROORZLQJ
connect: connect body...
delete: delete body...
get: get body...
head: head body...
options: options body...
post: post body...
put: put body...
trace: trace body...

152 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
1RGHIDXOWFDVHLVQHFHVVDU\VLQFHZHFRYHUDOOWKHSRVVLELOLWLHV&RQYHUVHO\LI\RXRPLW
RQHRIWKHFODVVHVDQG\RXGRQ¦WSURYLGHDGHIDXOWFDVHRUDFDVHIRUDVKDUHGSDUHQW
FODVVWKHFRPSLOHUZDUQV\RXWKDWWKH£PDWFKLVQRWH[KDXVWLYH¤)RUH[DPSOHLI\RX
FRPPHQWRXWWKHFDVHIRUPut\RXJHWWKLVZDUQLQJ
warning: match is not exhaustive!
missing combination Put

def handle (method: HttpMethod) = method match {


...

<RXDOVRJHWDMatchErrorH[FHSWLRQLIDPutLQVWDQFHLVSDVVHGWRWKHPDWFK
8VLQJsealedKDVRQHGUDZEDFN(YHU\WLPH\RXDGGRUUHPRYHDFODVVIURPWKHKLHU
DUFK\\RXKDYHWRPRGLI\WKHILOHVLQFHWKHHQWLUHKLHUDUFK\KDVWREHGHFODUHGLQWKH
VDPHILOH7KLVEUHDNVWKH2SHQ&ORVHG3ULQFLSOH VHH>0H\HU@DQG>0DUWLQ@ 
ZKLFKLVDVROXWLRQWRWKHSUDFWLFDOSUREOHPWKDWLWFDQEHFRVWO\WRPRGLI\H[LVWLQJFRGH
UHWHVWLW DQGRWKHUFRGHWKDWXVHVLW DQGUHGHSOR\LW,W¦VPXFKOHVV£FRVWO\¤LI\RXFDQ
H[WHQGWKHV\VWHPE\DGGLQJQHZGHULYHGW\SHVLQVHSDUDWHVRXUFHILOHV7KLVLVZK\ZH
SLFNHGWKH+773PHWKRGKLHUDUFK\IRUWKHH[DPSOH7KHOLVWRIPHWKRGVLVYHU\VWDEOH

$YRLGsealedFDVHFODVVKLHUDUFKLHVLIWKHKLHUDUFK\FKDQJHVIUHTXHQWO\
IRUDQDSSURSULDWHGHILQLWLRQRI£IUHTXHQWO\¤ 

)LQDOO\\RXPD\KDYHQRWLFHGVRPHGXSOLFDWLRQLQWKHH[DPSOH$OOWKHFRQFUHWHFODVVHV
KDYHDbodyILHOG:K\GLGQ¦WZHSXWWKDWILHOGLQWKHSDUHQWHttpMethodFODVV"%HFDXVH
ZHGHFLGHGWRXVHFDVHFODVVHVIRUWKHFRQFUHWHFODVVHVZH¦OOUXQLQWRWKHVDPHSUREOHP
ZLWK FDVH FODVV LQKHULWDQFH WKDW ZH GLVFXVVHG LQ £&DVH &ODVV ,QKHUL
WDQFH¤RQSDJHZKHUHZHDGGHGDVKDUHGidILHOGLQWKHShapeKLHUDUFK\:HQHHG
WKHbodyDUJXPHQWIRUHDFK+773PHWKRG¦VFRQVWUXFWRU\HWLWZLOOEHPDGHDILHOGRI
HDFKPHWKRGW\SHDXWRPDWLFDOO\6RZHZRXOGKDYHWRXVHWKHoverride valWHFKQLTXH
ZHGHPRQVWUDWHGSUHYLRXVO\
:HFRXOGUHPRYHWKHFDVHNH\ZRUGVDQGLPSOHPHQWWKHPHWKRGVDQGFRPSDQLRQRE
MHFWVWKDWZHQHHG+RZHYHULQWKLVFDVHWKHGXSOLFDWLRQLVPLQLPDODQGWROHUDEOH
:KDWLIZHZDQWWRXVHFDVHFODVVHV\HWDOVRUHIHUHQFHWKH bodyILHOGLQ HttpMethod"
)RUWXQDWHO\ZHNQRZWKDW6FDODZLOOJHQHUDWHDbodyUHDGHUPHWKRGLQHYHU\FRQFUHWH
VXEFODVV DVORQJDVZHXVHWKHQDPHbodyFRQVLVWHQWO\ 6RZHFDQGHFODUHWKDWPHWKRG
DEVWUDFWLQHttpMethodWKHQXVHLWDVZHVHHILW7KHIROORZLQJH[DPSOHGHPRQVWUDWHV
WKLVWHFKQLTXH
// code-examples/ObjectSystem/sealed/http-body-script.scala

sealed abstract class HttpMethod() {


def body: String
def bodyLength = body.length

Sealed Class Hierarchies | 153

Download at WoweBook.Com
}

case class Connect(body: String) extends HttpMethod


case class Delete (body: String) extends HttpMethod
case class Get (body: String) extends HttpMethod
case class Head (body: String) extends HttpMethod
case class Options(body: String) extends HttpMethod
case class Post (body: String) extends HttpMethod
case class Put (body: String) extends HttpMethod
case class Trace (body: String) extends HttpMethod

def handle (method: HttpMethod) = method match {


case Connect (body) => println("connect: " + body)
case Delete (body) => println("delete: " + body)
case Get (body) => println("get: " + body)
case Head (body) => println("head: " + body)
case Options (body) => println("options: " + body)
case Post (body) => println("post: " + body)
case Put (body) => println("put: " + body)
case Trace (body) => println("trace: " + body)
}

val methods = List(


Connect("connect body..."),
Delete ("delete body..."),
Get ("get body..."),
Head ("head body..."),
Options("options body..."),
Post ("post body..."),
Put ("put body..."),
Trace ("trace body..."))

methods.foreach { method =>


handle(method)
println("body length? " + method.bodyLength)
}

:HGHFODUHGbodyDEVWUDFWLQHttpMethod:HDGGHGDVLPSOHbodyLengthPHWKRGWKDW
FDOOVbody7KHORRSDWWKHHQGRIWKHVFULSWFDOOV bodyLength5XQQLQJWKLVVFULSWSUR
GXFHVWKHIROORZLQJRXWSXW
connect: connect body...
body length? 15
delete: delete body...
body length? 14
get: get body...
body length? 11
head: head body...
body length? 12
options: options body...
body length? 15
post: post body...
body length? 12
put: put body...
body length? 11

154 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
trace: trace body...
body length? 13

$VDOZD\VHYHU\IHDWXUHKDVSOXVHVDQGPLQXVHV&DVHFODVVHVDQGVHDOHGFODVVKLHUDU
FKLHVKDYHYHU\XVHIXOSURSHUWLHVEXWWKH\DUHQ¦WVXLWDEOHIRUDOOVLWXDWLRQV

The Scala Type Hierarchy


:HKDYHPHQWLRQHGDQXPEHURIW\SHVLQ6FDOD¦VW\SHKLHUDUFK\DOUHDG\/HW¦VORRNDW
WKHJHQHUDOVWUXFWXUHRIWKHKLHUDUFK\DVLOOXVWUDWHGLQ)LJXUH

)LJXUH6FDOD¦VW\SHKLHUDUFK\

7DEOHVDQGGLVFXVVWKHW\SHVVKRZQLQ)LJXUHDVZHOODVVRPHRWKHULP
SRUWDQWW\SHVWKDWDUHQ¦WVKRZQ6RPHGHWDLOVDUHRPLWWHGIRUFODULW\:KHQWKHXQGHU
O\LQJ£UXQWLPH¤LVGLVFXVVHGWKHSRLQWVPDGHDSSO\HTXDOO\WRWKH-90DQGWKH1(7
&/5H[FHSWZKHUHQRWHG

The Scala Type Hierarchy | 155

Download at WoweBook.Com
7DEOH$Q\$Q\9DODQG$Q\5HI
Name Parent Description
Any none The root of the hierarchy. Defines a few final methods like ==, !=, isInstanceOf[T] (for type
checking), and asInstanceOf[T] (for type casting), as well as default versions of equals,
hashCode, and toString, which are designed to be overridden by subclasses.
AnyVal Any The parent of all value types, which correspond to the primitive types on the runtime platform, plus
Unit. All the AnyVal instances are immutable value instances, and all the AnyVal types are
abstract final. Hence, none of them can be instantiated with new. Rather, new instances are
created with literal values (e.g., 3.14 for a Double) or by calling methods on instances that return
new values.
AnyRef Any The parent of all reference types, including all java.* and scala.* types. It is equivalent to
java.lang.Object for the JVM and object (System.Object) for the .NET runtime. Instances
of reference types are created with new.

7KHYDOXHW\SHVDUHFKLOGUHQRIAnyVal
7DEOH'LUHFWVXEW\SHVRI$Q\9DOWKHYDOXHW\SHV
Name Runtime primitive type
Boolean Boolean (true and false).
Byte Byte.
Char Char.
Short Short.
Int Int.
Long Long.
Float Float.
Double Double.
Unit Serves the same role as void in most imperative languages. Used primarily as a function return value.
There is only one instance of Unit, named (). Think of it as a tuple with zero items.

$OORWKHUW\SHVWKHUHIHUHQFHW\SHVDUHFKLOGUHQRIAnyRef7DEOHOLVWVVRPHRIWKH
PRUHFRPPRQO\XVHGUHIHUHQFHW\SHV1RWHWKDWWKHUHDUHVRPHVLJQLILFDQWGLIIHUHQFHV
EHWZHHQWKHYHUVLRQ;DQGFROOHFWLRQV
7DEOH'LUHFWDQGLQGLUHFWVXEW\SHVRI$Q\5HIWKHUHIHUHQFHW\SHV
Name Parent Description
Collection[+T] Iterable[T] Trait for collections of known size.
Either[+T1, +T2] AnyRef Used most often as a return type when a method could return an instance
of one of two unrelated types. For example, an exception or a “successful”
result. The Either can be pattern matched for its Left or Right
subtypes. (It is analogous to Option, with Some and None.) For the

156 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
Name Parent Description
exception-handling idiom, it is conventional to use Left for the
exception.
FunctionN[-T1, -T2, AnyRef Trait representing a function that takes N arguments, each of which can
..., -TN, +R] have its own type, and returns a value of type R. (Traits are defined for
N = 0 to 22.) The variance annotations (+ and -) in front of the types will
be explained in “Variance Under Inheritance” on page 251.
Iterable[+T] AnyRef Trait with methods for operating on collections of instances. Users
implement the abstract elements method to return an Iterable
instance.
List[+T] Seq[T] sealed abstract class for ordered collections with functional-
style list semantics. It is the most widely used collection in Scala, so it is
defined in the scala package, rather than one of the collection packages.
(In Scala version2.8, it is actually defined in scala.collec
tion.immutable and “aliased” in package object scala). It
has two subclasses, case object Nil, which extends List[Noth
ing] and represents an empty list, and case final class ::
[T], which represents a non-empty list, characterized by a head element
and a tail list, which would be Nil for a one-element list.
Nothing All other types Nothing is the subtype of all other types. It has no instances. It is used
primarily for defining other types in a type-safe way, such as the special
List subtype Nil. See also “Nothing and Null” on page 267.
Null All reference types Null has one instance, null, corresponding to the runtime’s concept
of null.
Option[T] Product Wraps an optional item. It is a sealed abstract type and the only
allowed instances are an instance of its derived case class
Some[T], wrapping an instance of T, or its derived case object
None, which extends Option[Nothing].
Predef AnyRef An object that defines and imports many commonly used types and
methods. See “The Predef Object” on page 145 for details.
Product AnyRef Trait with methods for determining arity and getting the nth item in a
“Cartesian product.” Subtraits are defined for Product, called
ProductN, for dimension N from 1 through 22.
ScalaObject AnyRef Mixin trait added to all Scala reference type instances.
Seq[+T] Collection[T] Trait for ordered collections.
TupleN ProductN Separate case classes for arity N = 1 through 22. Tuples support the
literal syntax (x1, x2, ..., xN).

%HVLGHV ListVRPHRIWKHRWKHUOLEUDU\FROOHFWLRQVLQFOXGH Map Set QueueDQG Stack


7KHVHRWKHUFROOHFWLRQVFRPHLQWZRYDULHWLHVPXWDEOHDQGLPPXWDEOH7KHLPPXWDEOH
FROOHFWLRQVDUHLQWKHSDFNDJH scala.collection.immutableZKLOHWKHPXWDEOHFROOHF
WLRQVDUHLQscala.collection.mutable2QO\DQLPPXWDEOHYHUVLRQRIListLVSURYLGHG
IRUDPXWDEOHOLVWXVHD ListBufferZKLFKFDQUHWXUQD ListYLDWKH toListPHWKRG
)RU 6FDOD YHUVLRQ  WKH FROOHFWLRQV LPSOHPHQWDWLRQV UHXVH FRGH IURP

The Scala Type Hierarchy | 157

Download at WoweBook.Com
scala.collection.generic8VHUVRIWKHFROOHFWLRQVZRXOGQRUPDOO\QRWXVHDQ\W\SHV
GHILQHG LQ WKLV SDFNDJH :H¦OO H[SORUH VRPH RI WKHVH FROOHFWLRQV LQ JUHDWHU GHWDLO LQ
£)XQFWLRQDO'DWD6WUXFWXUHV¤RQSDJH
&RQVLVWHQW ZLWK LWV HPSKDVLV RQ IXQFWLRQDO SURJUDPPLQJ VHH &KDSWHU   6FDOD HQ
FRXUDJHV\RXWRXVHWKHLPPXWDEOHFROOHFWLRQVVLQFH ListLVDXWRPDWLFDOO\LPSRUWHG
DQG Predef GHILQHV W\SHV Map DQG Set WKDW UHIHU WR WKH LPPXWDEOH YHUVLRQV RI WKHVH
FROOHFWLRQV$OORWKHUFROOHFWLRQVKDYHWREHLPSRUWHGH[SOLFLWO\
PredefGHILQHVDQXPEHURILPSOLFLWFRQYHUVLRQPHWKRGVIRUWKHYDOXHW\SHV H[FOXGLQJ
Unit 7KHUHDUHLPSOLFLWFRQYHUVLRQVWRWKHFRUUHVSRQGLQJscala.runtime.RichXW\SHV
)RUH[DPSOHWKH byteWrapperPHWKRGFRQYHUWVD ByteWRD scala.runtime.RichByte
7KHUHDUHLPSOLFLWFRQYHUVLRQVEHWZHHQWKH£QXPHULF¤W\SHV¢Byte Short Int Long
DQGFloat¢WRWKHRWKHUW\SHVWKDWDUH£ZLGHU¤WKDQWKHRULJLQDO)RUH[DPSOHByteWR
IntIntWRLongIntWRDoubleHWF)LQDOO\WKHUHDUHFRQYHUVLRQVWRWKHFRUUHVSRQGLQJ
-DYDZUDSSHUW\SHVHJIntWRjava.lang.Integer:HGLVFXVVLPSOLFLWFRQYHUVLRQVLQ
PRUHGHWDLOLQ£,PSOLFLW&RQYHUVLRQV¤RQSDJH
7KHUHDUHVHYHUDOH[DPSOHVRIOptionHOVHZKHUHHJ£2SWLRQ6RPHDQG1RQH$YRLG
LQJQXOOV¤RQSDJH+HUHLVDVFULSWWKDWLOOXVWUDWHVXVLQJDQ EitherUHWXUQYDOXHWR
KDQGOHDWKURZQH[FHSWLRQRUVXFFHVVIXOUHVXOW DGDSWHGIURPKWWSGFVREUDOEORJVSRW
FRPFDWFKLQJH[FHSWLRQVKWPO 
// code-examples/ObjectSystem/typehierarchy/either-script.scala

def exceptionToLeft[T](f: => T): Either[java.lang.Throwable, T] = try {


Right(f)
} catch {
case ex => Left(ex)
}

def throwsOnOddInt(i: Int) = i % 2 match {


case 0 => i
case 1 => throw new RuntimeException(i + " is odd!")
}

for(i <- 0 to 3)
exceptionToLeft(throwsOnOddInt(i)) match {
case Left(ex) => println("Oops, got exception " + ex.toString)
case Right(x) => println(x)
}

7KH exceptionToLeftPHWKRGHYDOXDWHV f,WFDWFKHVD ThrowableDQGUHWXUQVLWDVWKH


LeftYDOXHRUUHWXUQVWKHQRUPDOUHVXOWDVWKHRightYDOXH7KHforORRSXVHVWKLVPHWKRG
WRLQYRNH throwsOnOddInt,WSDWWHUQPDWFKHVRQWKHUHVXOWDQGSULQWVDQDSSURSULDWH
PHVVDJH7KHRXWSXWRIWKHVFULSWLVWKHIROORZLQJ
0
Oops, got exception java.lang.RuntimeException: 1 is odd!
2
Oops, got exception java.lang.RuntimeException: 3 is odd!

158 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
$ FunctionNWUDLWZKHUH NLVWRLVLQVWDQWLDWHGIRUDQDQRQ\PRXVIXQFWLRQZLWK
NDUJXPHQWV6RFRQVLGHUWKHIROORZLQJDQRQ\PRXVIXQFWLRQ
(t1: T1, ..., tN: TN) => new R(...)

,WLVV\QWDFWLFVXJDUIRUWKHIROORZLQJFUHDWLRQRIDQDQRQ\PRXVFODVV
new FunctionN {
def apply(t1: T1, ..., tN: TN): R = new R(...)

// other methods
}

:H¦OOUHYLVLW FunctionNLQ£9DULDQFH8QGHU,QKHULWDQFH¤RQSDJHDQG£)XQFWLRQ
7\SHV¤RQSDJH

Linearization of an Object’s Hierarchy


%HFDXVHRIVLQJOHLQKHULWDQFHWKHLQKHULWDQFHKLHUDUFK\ZRXOGEHOLQHDULIZHLJQRUHG
PL[HGLQWUDLWV:KHQWUDLWVDUHFRQVLGHUHGHDFKRIZKLFKPD\EHGHULYHGIURPRWKHU
WUDLWVDQGFODVVHVWKHLQKHULWDQFHKLHUDUFK\IRUPVDGLUHFWHGDF\FOLFJUDSK VHH>6FD
OD6SHF@ 7KHWHUPOLQHDUL]DWLRQUHIHUVWRWKHDOJRULWKPXVHGWR£IODWWHQ¤WKLVJUDSK
IRUWKHSXUSRVHVRIUHVROYLQJPHWKRGORRNXSSULRULWLHVFRQVWUXFWRULQYRFDWLRQRUGHU
ELQGLQJRIsuperHWF
,QIRUPDOO\ZHVDZLQ£6WDFNDEOH7UDLWV¤RQSDJHWKDWZKHQDQLQVWDQFHKDVPRUH
WKDQRQHWUDLWWKH\ELQGULJKWWROHIWDVGHFODUHG&RQVLGHUWKHIROORZLQJH[DPSOHRI
OLQHDUL]DWLRQ
// code-examples/ObjectSystem/linearization/linearization1-script.scala

class C1 {
def m = List("C1")
}

trait T1 extends C1 {
override def m = { "T1" :: super.m }
}

trait T2 extends C1 {
override def m = { "T2" :: super.m }
}

trait T3 extends C1 {
override def m = { "T3" :: super.m }
}

class C2 extends T1 with T2 with T3 {


override def m = { "C2" :: super.m }
}

val c2 = new C2
println(c2.m)

Linearization of an Object’s Hierarchy | 159

Download at WoweBook.Com
5XQQLQJWKLVVFULSW\LHOGVWKHIROORZLQJRXWSXW
List(C2, T3, T2, T1, C1)

7KLVOLVWRIVWULQJVEXLOWXSE\WKHmPHWKRGVUHIOHFWVWKHOLQHDUL]DWLRQRIWKHLQKHULWDQFH
KLHUDUFK\ZLWKDIHZPLVVLQJSLHFHVZH¦OOGLVFXVVVKRUWO\:H¦OODOVRVHHZK\&LVDW
WKHHQGRIWKHOLVW)LUVWOHW¦VVHHZKDWWKHLQYRFDWLRQVHTXHQFHRIWKHFRQVWUXFWRUVORRNV
OLNH
// code-examples/ObjectSystem/linearization/linearization2-script.scala

var clist = List[String]()

class C1 {
clist ::= "C1"
}

trait T1 extends C1 {
clist ::= "T1"
}

trait T2 extends C1 {
clist ::= "T2"
}

trait T3 extends C1 {
clist ::= "T3"
}

class C2 extends T1 with T2 with T3 {


clist ::= "C2"
}

val c2 = new C2
println(clist.reverse)

5XQQLQJWKLVVFULSW\LHOGVWKHIROORZLQJRXWSXW
List(C1, T1, T2, T3, C2)

6RWKHFRQVWUXFWLRQVHTXHQFHLVWKHUHYHUVH :HKDGWRUHYHUVHWKHOLVWRQWKHODVWOLQH
EHFDXVHWKHZD\LWZDVFRQVWUXFWHGSXWWKHHOHPHQWVLQWKHUHYHUVHRUGHU 7KLVLQYR
FDWLRQRUGHUPDNHVVHQVH)RUSURSHUFRQVWUXFWLRQWRRFFXUWKHSDUHQWW\SHVQHHGWR
EH FRQVWUXFWHG EHIRUH WKH GHULYHG W\SHV VLQFH D GHULYHG W\SH RIWHQ XVHV ILHOGV DQG
PHWKRGVLQWKHSDUHQWW\SHVGXULQJLWVFRQVWUXFWLRQSURFHVV
7KHRXWSXWRIWKHILUVWOLQHDUL]DWLRQVFULSWLVDFWXDOO\PLVVLQJWKUHHW\SHVDWWKHHQG7KH
IXOOOLQHDUL]DWLRQIRUUHIHUHQFHW\SHVDFWXDOO\HQGVZLWK ScalaObject AnyRefDQG Any
6RWKHOLQHDUL]DWLRQIRUC2LVDFWXDOO\
List(C2, T3, T2, T1, C1, ScalaObject, AnyRef, Any)

6FDODLQVHUWVWKHScalaObjectWUDLWDVWKHODVWPL[LQMXVWEHIRUHAnyRefDQGAnyWKDWDUH
WKHSHQXOWLPDWHDQGXOWLPDWHSDUHQWFODVVHVRIDQ\UHIHUHQFHW\SH2IFRXUVHWKHVHWKUHH

160 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
W\SHVGRQRWVKRZXSLQWKHRXWSXWRIWKHVFULSWVEHFDXVHZHXVHGDQDGKRFmPHWKRG
WRILJXUHRXWWKHEHKDYLRUE\EXLOGLQJXSDQRXWSXWVWULQJ
7KH£YDOXHW\SHV¤VXEFODVVHVRIAnyValDUHDOOGHFODUHGabstract final7KHFRPSLOHU
PDQDJHVLQVWDQWLDWLRQRIWKHP6LQFHZHFDQ¦WVXEFODVVWKHPWKHLUOLQHDUL]DWLRQVDUH
VLPSOHDQGVWUDLJKWIRUZDUG
7KHOLQHDUL]DWLRQGHILQHVWKHRUGHULQZKLFKPHWKRGORRNXSRFFXUV/HW¦VH[DPLQHLW
PRUHFORVHO\
$OORXUFODVVHVDQGWUDLWVGHILQHWKHPHWKRG m7KHRQHLQ C2LVFDOOHGILUVWVLQFHWKH
LQVWDQFHLVRIWKDWW\SHC2.mFDOOVsuper.mZKLFKUHVROYHVWRT3.m7KHVHDUFKDSSHDUV
WREHEUHDGWKILUVWUDWKHUWKDQGHSWKILUVW,ILWZHUHGHSWKILUVWLWZRXOGLQYRNH C1.m
DIWHUT3.m$IWHUZDUGT3.mT2.mWKHQT1.mDQGILQDOO\C1.mDUHLQYRNHGC1LVWKHSDUHQW
RIWKHWKUHHWUDLWV)URPZKLFKRIWKHWUDLWVGLGZHWUDYHUVHWRC1"$FWXDOO\LWLVEUHDGWK
ILUVWZLWK£GHOD\HG¤HYDOXDWLRQDVZHZLOOVHH/HW¦VPRGLI\RXUILUVWH[DPSOHDQGVHH
KRZZHJRWWRC1
// code-examples/ObjectSystem/linearization/linearization3-script.scala

class C1 {
def m(previous: String) = List("C1("+previous+")")
}

trait T1 extends C1 {
override def m(p: String) = { "T1" :: super.m("T1") }
}

trait T2 extends C1 {
override def m(p: String) = { "T2" :: super.m("T2") }
}

trait T3 extends C1 {
override def m(p: String) = { "T3" :: super.m("T3") }
}

class C2 extends T1 with T2 with T3 {


override def m(p: String) = { "C2" :: super.m("C2") }
}

val c2 = new C2
println(c2.m(""))

1RZZHSDVVWKHQDPHRIWKHFDOOHURIsuper.mDVDSDUDPHWHUWKHQC1SULQWVRXWZKR
FDOOHGLW5XQQLQJWKLVVFULSW\LHOGVWKHIROORZLQJRXWSXW
List(C2, T3, T2, T1, C1(T1))

,W¦VWKHODVWRQHT1:HPLJKWKDYHH[SHFWHGT3IURPD£QDwYH¤DSSOLFDWLRQRIEUHDGWK
ILUVWWUDYHUVDO
+HUHLVWKHDFWXDODOJRULWKPIRUFDOFXODWLQJWKHOLQHDUL]DWLRQ$PRUHIRUPDOGHILQLWLRQ
LVJLYHQLQ>6FDOD6SHF@

Linearization of an Object’s Hierarchy | 161

Download at WoweBook.Com
Linearization Algorithm for Reference Types
 3XWWKHDFWXDOW\SHRIWKHLQVWDQFHDVWKHILUVWHOHPHQW
 6WDUWLQJZLWKWKHULJKWPRVWSDUHQWW\SHDQGZRUNLQJOHIWFRPSXWHWKHOLQHDUL]DWLRQ
RIHDFKW\SHDSSHQGLQJLWVOLQHDUL]DWLRQWRWKHFXPXODWLYHOLQHDUL]DWLRQ ,JQRUH
ScalaObjectAnyRefDQGAnyIRUQRZ
 :RUNLQJIURPOHIWWRULJKWUHPRYHDQ\W\SHLILWDSSHDUVDJDLQWRWKHULJKWRIWKH
FXUUHQWSRVLWLRQ
 $SSHQGScalaObjectAnyRefDQGAny

7KLVH[SODLQVKRZZHJRWWRC1IURPT1LQWKHSUHYLRXVH[DPSOHT3DQGT2DOVRKDYHLW
LQWKHLUOLQHDUL]DWLRQVEXWWKH\FRPHEHIRUHT1VRWKHC1WHUPVWKH\FRQWULEXWHGZHUH
GHOHWHG
/HW¦VZRUNWKURXJKWKHDOJRULWKPXVLQJDVOLJKWO\PRUHLQYROYHGH[DPSOH
// code-examples/ObjectSystem/linearization/linearization4-script.scala

class C1 {
def m = List("C1")
}

trait T1 extends C1 {
override def m = { "T1" :: super.m }
}

trait T2 extends C1 {
override def m = { "T2" :: super.m }
}

trait T3 extends C1 {
override def m = { "T3" :: super.m }
}

class C2A extends T2 {


override def m = { "C2A" :: super.m }
}

class C2 extends C2A with T1 with T2 with T3 {


override def m = { "C2" :: super.m }
}

def calcLinearization(obj: C1, name: String) = {


val lin = obj.m ::: List("ScalaObject", "AnyRef", "Any")
println(name + ": " + lin)
}

calcLinearization(new C2, "C2 ")


println("")
calcLinearization(new T3 {}, "T3 ")
calcLinearization(new T2 {}, "T2 ")

162 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
calcLinearization(new T1 {}, "T1 ")
calcLinearization(new C2A, "C2A")
calcLinearization(new C1, "C1 ")

7KHRXWSXWLVWKHIROORZLQJ
C2 : List(C2, T3, T1, C2A, T2, C1, ScalaObject, AnyRef, Any)

T3 : List(T3, C1, ScalaObject, AnyRef, Any)


T2 : List(T2, C1, ScalaObject, AnyRef, Any)
T1 : List(T1, C1, ScalaObject, AnyRef, Any)
C2A: List(C2A, T2, C1, ScalaObject, AnyRef, Any)
C1 : List(C1, ScalaObject, AnyRef, Any)

7R KHOS XV DORQJ ZH FDOFXODWHG WKH OLQHDUL]DWLRQV IRU WKH RWKHU W\SHV DQG ZH DOVR
DSSHQGHG ScalaObject AnyRefDQG AnyWRUHPLQGRXUVHOYHVWKDWWKH\VKRXOGDOVREH
WKHUH:HDOVRUHPRYHGWKHORJLFWRSDVVWKHFDOOHU¦VQDPHWR m7KDWFDOOHURI C1ZLOO
DOZD\VEHWKHHOHPHQWWRLWVLPPHGLDWHOHIW
6ROHW¦VZRUNWKURXJKWKHDOJRULWKPIRUC2DQGFRQILUPRXUUHVXOWV:H¦OOVXSSUHVVWKH
ScalaObjectAnyRefDQGAnyIRUFODULW\XQWLOWKHHQG6HH7DEOH

7DEOH+DQGFDOFXODWLRQRI&OLQHDUL]DWLRQ&H[WHQGV&$ZLWK7ZLWK7ZLWK7^`
# Linearization Description
1 C2 Add the type of the instance.
2 C2, T3, C1 Add the linearization for T3 (farthest on the right).
3 C2, T3, C1, T2, C1 Add the linearization for T2.
4 C2, T3, C1, T2, C1, T1, C1 Add the linearization for T1.
5 C2, T3, C1, T2, C1, T1, C1, C2A, T2, C1 Add the linearization for C2A.
6 C2, T3, T2, T1, C2A, T2, C1 Remove duplicates of C1; all but the last C1.
7 C2, T3, T1, C2A, T2, C1 Remove duplicate T2; all but the last T2.
8 C2, T3, T1, C2A, T2, C1, ScalaObject, Finish!
AnyRef, Any

:KDWWKHDOJRULWKPGRHVLVSXVKDQ\VKDUHGW\SHVWRWKHULJKWXQWLOWKH\FRPHDIWHU
DOOWKHW\SHVWKDWGHULYHIURPWKHP
7U\PRGLI\LQJWKHODVWVFULSWZLWKGLIIHUHQWKLHUDUFKLHVDQGVHHLI\RXFDQUHSURGXFHWKH
UHVXOWVXVLQJWKHDOJRULWKP

2YHUO\ FRPSOH[ W\SH KLHUDUFKLHV FDQ UHVXOW LQ PHWKRG ORRNXS £VXU
SULVHV¤,I\RXKDYHWRZRUNWKURXJKWKLVDOJRULWKPWRILJXUHRXWZKDW¦V
JRLQJRQWU\WRVLPSOLI\\RXUFRGH

Linearization of an Object’s Hierarchy | 163

Download at WoweBook.Com
Recap and What’s Next
:H KDYH ILQLVKHG RXU VXUYH\ RI 6FDOD¦V REMHFW PRGHO ,I \RX FRPH IURP DQ REMHFW
RULHQWHG ODQJXDJH EDFNJURXQG \RX QRZ NQRZ HQRXJK DERXW 6FDOD WR UHSODFH \RXU
H[LVWLQJREMHFWRULHQWHGODQJXDJHZLWKREMHFWRULHQWHG6FDOD
+RZHYHUWKHUHLVPXFKPRUHWRFRPH6FDODVXSSRUWVIXQFWLRQDOSURJUDPPLQJZKLFK
RIIHUVSRZHUIXOPHFKDQLVPVIRUDGGUHVVLQJDQXPEHURIGHVLJQSUREOHPVVXFKDVFRQ
FXUUHQF\:H¦OOVHHWKDWIXQFWLRQDOSURJUDPPLQJDSSHDUVWRFRQWUDGLFWREMHFWRULHQWHG
SURJUDPPLQJDWOHDVWRQWKHVXUIDFH7KDWVDLGDJXLGLQJSULQFLSOHEHKLQG6FDODLVWKDW
WKHVHWZRSDUDGLJPVFRPSOHPHQWHDFKRWKHUPRUHWKDQWKH\FRQIOLFW&RPELQHGWKH\
JLYH\RXPRUHRSWLRQVIRUEXLOGLQJUREXVWVFDODEOHVRIWZDUH6FDODOHWV\RXFKRRVHWKH
WHFKQLTXHVWKDWZRUNEHVWIRU\RXUQHHGV

164 | Chapter 7:—The Scala Object System

Download at WoweBook.Com
CHAPTER 8
Functional Programming in Scala

(YHU\GHFDGHRUWZRDPDMRUFRPSXWLQJLGHDJRHVPDLQVWUHDP7KHVHLGHDVPD\KDYH
OXUNHGLQWKHEDFNJURXQGRIDFDGHPLFFRPSXWHUVFLHQFHUHVHDUFKRUSRVVLEO\LQVRPH
OHVVHUNQRZQILHOGRILQGXVWU\7KHWUDQVLWLRQWRPDLQVWUHDPDFFHSWDQFHFRPHVLQUH
VSRQVHWRDSHUFHLYHGSUREOHPIRUZKLFKWKHLGHDLVZHOOVXLWHG2EMHFWRULHQWHGSUR
JUDPPLQJZKLFKZDVLQYHQWHGLQWKHVZHQWPDLQVWUHDPLQWKHVDUJXDEO\
LQUHVSRQVHWRWKHHPHUJHQFHRIJUDSKLFDOXVHULQWHUIDFHVIRUZKLFKWKH223SDUDGLJP
LVDQDWXUDOILW
)XQFWLRQDOSURJUDPPLQJDSSHDUVWREHH[SHULHQFLQJDVLPLODUEUHDNRXW/RQJWKHWRSLF
RIFRPSXWHUVFLHQFHUHVHDUFKDQGHYHQROGHUWKDQREMHFWRULHQWHGSURJUDPPLQJIXQF
WLRQDOSURJUDPPLQJRIIHUVHIIHFWLYHWHFKQLTXHVIRUFRQFXUUHQWSURJUDPPLQJZKLFKLV
JURZLQJLQLPSRUWDQFH
%HFDXVHIXQFWLRQDOSURJUDPPLQJLVOHVVZLGHO\XQGHUVWRRGWKDQREMHFWRULHQWHGSUR
JUDPPLQJZHZRQ¦WDVVXPHWKDW\RXKDYHSULRUH[SHULHQFHZLWKLW:H¦OOVWDUWWKLV
FKDSWHUZLWKSOHQW\RIEDFNJURXQGLQIRUPDWLRQ$V\RX¦OOVHHIXQFWLRQDOSURJUDPPLQJ
LV QRW RQO\ D YHU\ HIIHFWLYH ZD\ WR DSSURDFK FRQFXUUHQW SURJUDPPLQJ ZKLFK ZH¦OO
H[SORUH LQ GHSWK LQ &KDSWHU  EXW IXQFWLRQDO SURJUDPPLQJ FDQ DOVR LPSURYH \RXU
REMHFWV
2IFRXUVHZHFDQ¦WSURYLGHDQH[KDXVWLYHLQWURGXFWLRQWRIXQFWLRQDOSURJUDPPLQJ7R
OHDUQPRUHDERXWLW>2¦6XOOLYDQ@KDVDPRUHGHWDLOHGLQWURGXFWLRQLQWKHFRQWH[W
RIWKH+DVNHOOODQJXDJH>$EHOVRQ@>9DQ5R\@DQG>7XUEDN@RIIHUWKRU
RXJK LQWURGXFWLRQV WR JHQHUDO SURJUDPPLQJ DSSURDFKHV LQFOXGLQJ IXQFWLRQDO SUR
JUDPPLQJ)LQDOO\>2NDVDNL@DQG>5DEKL@GLVFXVVIXQFWLRQDOGDWDVWUXFWXUHV
DQGDOJRULWKPVLQGHWDLO

What Is Functional Programming?


'RQ¦WDOOSURJUDPPLQJODQJXDJHVKDYHIXQFWLRQVRIVRPHVRUW":KHWKHUWKH\DUHFDOOHG
PHWKRGV SURFHGXUHV RU GOTOs SURJUDPPHUV DUH DOZD\V GHDOLQJ LQ IXQFWLRQV

165

Download at WoweBook.Com
)XQFWLRQDOSURJUDPPLQJLVEDVHGRQWKHEHKDYLRURIIXQFWLRQVLQWKHPDWKHPDWLFDO
VHQVHZLWKDOOWKHLPSOLFDWLRQVWKDWVWDUWLQJSRLQWLPSOLHV

Functions in Mathematics
,QPDWKHPDWLFVIXQFWLRQVKDYHQRVLGHHIIHFWV&RQVLGHUWKHFODVVLFIXQFWLRQsin(x)
y = sin(x)

1RPDWWHUKRZPXFKZRUNsin(x)GRHVDOOWKHUHVXOWVDUHUHWXUQHGDQGDVVLJQHGWRy
1RJOREDOVWDWHRIDQ\NLQGLVPRGLILHGLQWHUQDOO\E\sin(x)+HQFHZHVD\WKDWVXFK
DIXQFWLRQLVIUHHRIVLGHHIIHFWVRUSXUH
7KLVSURSHUW\VLPSOLILHVHQRUPRXVO\WKHFKDOOHQJHRIDQDO\]LQJWHVWLQJDQGGHEXJJLQJ
DIXQFWLRQ<RXFDQGRWKHVHWKLQJVZLWKRXWKDYLQJWRNQRZDQ\WKLQJDERXWWKHFRQWH[W
LQZKLFKWKHIXQFWLRQLVLQYRNHGH[FHSWIRUDQ\RWKHUIXQFWLRQVLWPLJKWFDOO+RZHYHU
\RXFDQDQDO\]HWKHPLQWKHVDPHZD\ZRUNLQJERWWRPXSWRYHULI\WKHZKROH£VWDFN¤
7KLVREOLYLRXVQHVVWRWKHVXUURXQGLQJFRQWH[WLVNQRZQDV5HIHUHQWLDO7UDQVSDUHQF\
<RXFDQFDOOVXFKDIXQFWLRQDQ\ZKHUHDQGEHFRQILGHQWWKDWLWZLOODOZD\VEHKDYHWKH
VDPH ZD\ ,I QR JOREDO VWDWH LV PRGLILHG FRQFXUUHQW LQYRFDWLRQ RI WKH IXQFWLRQ LV
VWUDLJKWIRUZDUGDQGUHOLDEOH
,QIXQFWLRQDOSURJUDPPLQJ\RXFDQFRPSRVHIXQFWLRQVIURPRWKHUIXQFWLRQV)RUH[
DPSOHtan(x) = sin(x)/cos(x)$QLPSOLFDWLRQRIFRPSRVDELOLW\LVWKDWIXQFWLRQVFDQ
EHWUHDWHGDVYDOXHV,QRWKHUZRUGVIXQFWLRQVDUHILUVWFODVVMXVWOLNHGDWD<RXFDQ
DVVLJQIXQFWLRQVWRYDULDEOHV<RXFDQSDVVIXQFWLRQVWRRWKHUIXQFWLRQV<RXFDQUHWXUQ
IXQFWLRQVDVYDOXHVIURPIXQFWLRQV,QWKHIXQFWLRQDOSDUDGLJPIXQFWLRQVEHFRPHD
SULPLWLYHW\SHDEXLOGLQJEORFNWKDW¦VMXVWDVHVVHQWLDOWRWKHZRUNRISURJUDPPLQJDV
LQWHJHUVRUVWULQJV
:KHQDIXQFWLRQWDNHVRWKHUIXQFWLRQVDVDUJXPHQWVRUUHWXUQVDIXQFWLRQLWLVFDOOHG
DKLJKHURUGHUIXQFWLRQ,QPDWKHPDWLFVWZRH[DPSOHVRIKLJKHURUGHUIXQFWLRQVIURP
FDOFXOXVDUHGHULYDWLRQDQGLQWHJUDWLRQ

Variables that Aren’t


7KHZRUG£YDULDEOH¤WDNHVRQDQHZPHDQLQJLQIXQFWLRQDOSURJUDPPLQJ,I\RXFRPH
IURPDSURFHGXUDORUREMHFWRULHQWHGSURJUDPPLQJEDFNJURXQG\RXDUHDFFXVWRPHG
WRYDULDEOHVWKDWDUHPXWDEOH,QIXQFWLRQDOSURJUDPPLQJYDULDEOHVDUHLPPXWDEOH
7KLVLVDQRWKHUFRQVHTXHQFHRIWKHPDWKHPDWLFDORULHQWDWLRQ,QWKHH[SUHVVLRQ y =
sin(x)RQFH\RXSLFNxWKHQyLVIL[HG$VDQRWKHUH[DPSOHLI\RXLQFUHPHQWWKHLQWHJHU
E\\RXGRQ¦W£PRGLI\WKHREMHFW¤\RXFUHDWHDQHZYDOXHWRUHSUHVHQW
7REHPRUHSUHFLVHLWLVWKHYDOXHVWKDWDUHLPPXWDEOH)XQFWLRQDOSURJUDPPLQJODQ
JXDJHVSUHYHQW\RXIURPDVVLJQLQJDQHZYDOXHWRDYDULDEOHWKDWDOUHDG\KDVDYDOXH

166 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
,PPXWDELOLW\LVGLIILFXOWZKHQ\RX¦UHQRWXVHGWRLW,I\RXFDQ¦WFKDQJHDYDULDEOHWKHQ
\RXFDQ¦WKDYHORRSFRXQWHUVIRUH[DPSOH:H¦UHDFFXVWRPHGWRREMHFWVWKDWFKDQJH
WKHLUVWDWHZKHQZHFDOOPHWKRGVRQWKHP/HDUQLQJWRWKLQNLQLPPXWDEOHWHUPVWDNHV
VRPHHIIRUW
+RZHYHULPPXWDELOLW\KDVHQRUPRXVEHQHILWVIRUFRQFXUUHQF\$OPRVWDOOWKHGLIILFXOW\
RIPXOWLWKUHDGHGSURJUDPPLQJOLHVLQV\QFKURQL]LQJDFFHVVWRVKDUHGPXWDEOHVWDWH,I
\RXUHPRYHPXWDELOLW\WKHQWKHSUREOHPVHVVHQWLDOO\JRDZD\,WLVWKHFRPELQDWLRQRI
UHIHUHQWLDOO\ WUDQVSDUHQW IXQFWLRQV DQG LPPXWDEOH YDOXHV WKDW PDNH IXQFWLRQDO SUR
JUDPPLQJFRPSHOOLQJDVDEHWWHUZD\WRZULWHFRQFXUUHQWVRIWZDUH
7KHVH TXDOLWLHV EHQHILW SURJUDPV LQ RWKHU ZD\V $OPRVW DOO WKH FRQVWUXFWV ZH KDYH
LQYHQWHGLQRGG\HDUVRIFRPSXWHUSURJUDPPLQJKDYHEHHQDWWHPSWVWRPDQDJH
FRPSOH[LW\+LJKHURUGHUIXQFWLRQVDQGUHIHUHQWLDOWUDQVSDUHQF\SURYLGHYHU\IOH[LEOH
EXLOGLQJEORFNVIRUFRPSRVLQJSURJUDPV
,PPXWDELOLW\JUHDWO\UHGXFHVUHJUHVVLRQEXJVPDQ\RIZKLFKDUHFDXVHGE\XQLQWHQ
GHGVWDWHFKDQJHVLQRQHSDUWRIDSURJUDPGXHWRLQWHQGHGFKDQJHVLQDQRWKHUSDUW
7KHUHDUHRWKHUFRQWULEXWRUVWRVXFKQRQORFDOHIIHFWVEXWPXWDELOLW\LVRQHRIWKHPRVW
LPSRUWDQW
,W¦VFRPPRQLQREMHFWRULHQWHGGHVLJQVWRHQFDSVXODWHDFFHVVWRGDWDVWUXFWXUHVLQRE
MHFWV,IWKHVHVWUXFWXUHVDUHPXWDEOHZHFDQ¦WVLPSO\VKDUHWKHPZLWKFOLHQWV:HKDYH
WRDGGVSHFLDODFFHVVRUPHWKRGVWRFRQWURODFFHVVVRFOLHQWVFDQ¦WPRGLI\WKHPRXWVLGH
RXUFRQWURO7KHVHDGGLWLRQVLQFUHDVHFRGHVL]HZKLFKLQFUHDVHVWKHWHVWLQJDQGPDLQ
WHQDQFHEXUGHQDQGWKH\LQFUHDVHWKHHIIRUWUHTXLUHGE\FOLHQWVWRXQGHUVWDQGWKHDG
KRFIHDWXUHVRIRXU$3,V
,QFRQWUDVWZKHQZHKDYHLPPXWDEOHGDWDVWUXFWXUHVPDQ\RIWKHVHSUREOHPVVLPSO\
JRDZD\:HFDQSURYLGHDFFHVVWRFROOHFWLRQVZLWKRXWIHDURIGDWDORVVRUFRUUXSWLRQ
2IFRXUVHWKHJHQHUDOSULQFLSOHVRIPLQLPDOFRXSOLQJVWLOODSSO\VKRXOGFOLHQWVFDUHLI
DSetRUListLVXVHGDVORQJforeachLVDYDLODEOH"
,PPXWDEOHGDWDDOVRLPSOLHVWKDWORWVRIFRSLHVZLOOEHPDGHZKLFKFDQEHH[SHQVLYH
)XQFWLRQDOGDWDVWUXFWXUHVRSWLPL]HIRUWKLVSUREOHP VHH>2NDVDNL@ DQGPDQ\RI
WKHEXLOWLQ6FDODW\SHVDUHHIILFLHQWDWFUHDWLQJQHZFRSLHVIURPH[LVWLQJFRSLHV
,W¦VWLPHWRGLYHLQWRWKHSUDFWLFDOLWLHVRIIXQFWLRQDOSURJUDPPLQJLQ6FDOD:H¦OOGLVFXVV
RWKHUDVSHFWVDQGEHQHILWVRIWKHDSSURDFKDVZHSURFHHG

Functional Programming in Scala


$VDK\EULGREMHFWIXQFWLRQDOODQJXDJH6FDODGRHVQRWUHTXLUHIXQFWLRQVWREHSXUH
QRUGRHVLWUHTXLUHYDULDEOHVWREHLPPXWDEOH,WGRHVKRZHYHUHQFRXUDJH\RXWRZULWH
\RXU FRGH WKLV ZD\ ZKHQHYHU SRVVLEOH <RX KDYH WKH IUHHGRP WR XVH SURFHGXUDO RU
REMHFWRULHQWHGWHFKQLTXHVZKHQDQGZKHUHWKH\VHHPPRVWDSSURSULDWH

Functional Programming in Scala | 167

Download at WoweBook.Com
7KRXJK IXQFWLRQDO ODQJXDJHV DUH DOO DERXW HOLPLQDWLQJ VLGH HIIHFWV D ODQJXDJH WKDW
QHYHUDOORZHGIRUVLGHHIIHFWVZRXOGEHXVHOHVV,QSXWDQGRXWSXW ,2 DUHLQKHUHQWO\
DERXWVLGHHIIHFWVDQG,2LVHVVHQWLDOWRDOOSURJUDPPLQJWDVNV)RUWKLVUHDVRQDOO
IXQFWLRQDOODQJXDJHVSURYLGHPHFKDQLVPVIRUSHUIRUPLQJVLGHHIIHFWVLQDFRQWUROOHG
ZD\
6FDODGRHVQ¦WUHVWULFWZKDW\RXFDQGREXWZHHQFRXUDJH\RXWRXVHLPPXWDEOHYDOXHV
DQGSXUHIXQFWLRQVDQGPHWKRGVZKHQHYHUSRVVLEOH:KHQPXWDELOLW\DQGVLGHHIIHFWV
DUHQHFHVVDU\SXUVXHWKHPLQD£SULQFLSOHG¤ZD\LVRODWHGLQZHOOGHILQHGPRGXOHVDQG
IRFXVHGRQLQGLYLGXDOWDVNV
,I\RX¦UHQHZWRIXQFWLRQDOSURJUDPPLQJNHHSLQPLQGWKDWLW¦VHDV\WRIDOOEDFNWRROG
KDELWV:HHQFRXUDJH\RXWRPDVWHUWKHIXQFWLRQDOVLGHRI6FDODDQGWROHDUQWRXVHLW
HIIHFWLYHO\

$IXQFWLRQWKDWUHWXUQVUnitLPSOLHVWKDWWKHIXQFWLRQKDVSXUHVLGHHI
IHFWVPHDQLQJWKDWLILWGRHVDQ\XVHIXOZRUNWKDWZRUNPXVWEHDOOVLGH
HIIHFWVVLQFHWKHIXQFWLRQGRHVQ¦WUHWXUQDQ\WKLQJ

:H¦YHVHHQPDQ\H[DPSOHVRIKLJKHURUGHUIXQFWLRQVDQGFRPSRVDELOLW\LQ6FDOD)RU
H[DPSOHList.mapWDNHVDIXQFWLRQWRWUDQVIRUPHDFKHOHPHQWRIWKHOLVWWRVRPHWKLQJ
HOVH
// code-examples/FP/basics/list-map-example-script.scala

List(1, 2, 3, 4, 5) map { _ * 2 }

5HFDOOWKDW_ * 2LVDIXQFWLRQOLWHUDOWKDWLVVKRUWKDQGIRUi => i * 2)RUHDFKDUJXPHQW


WRWKHIXQFWLRQ\RXFDQXVH_LIWKHDUJXPHQWLVXVHGRQO\RQFH:HDOVRXVHGWKHLQIL[
RSHUDWRUQRWDWLRQWRLQYRNH map+HUH¦VDQH[DPSOHWKDW£UHGXFHV¤WKHVDPHOLVWE\
PXOWLSO\LQJDOOWKHHOHPHQWVWRJHWKHU
// code-examples/FP/basics/list-reduceLeft-example-script.scala

List(1, 2, 3, 4, 5) reduceLeft { _ * _ }

7KHILUVW_UHSUHVHQWVWKHDUJXPHQWWKDWLVDFFXPXODWLQJWKHYDOXHRIWKHUHGXFWLRQDQG
WKHVHFRQG_UHSUHVHQWVWKHFXUUHQWHOHPHQWRIWKHOLVW
%RWK H[DPSOHV VXFFHVVIXOO\ £ORRSHG¤ WKURXJK WKH OLVW ZLWKRXW WKH XVH RI D PXWDEOH
FRXQWHUWRWUDFNLWHUDWLRQV0RVWFRQWDLQHUVLQWKH6FDODOLEUDU\SURYLGHIXQFWLRQDOO\
SXUHLWHUDWLRQPHWKRGV,QRWKHUFDVHVUHFXUVLRQLVWKHSUHIHUUHGZD\WRWUDYHUVHDGDWD
VWUXFWXUH RU SHUIRUP DQ DOJRULWKP :H¦OO UHWXUQ WR WKLV WRSLF LQ £5HFXU
VLRQ¤RQSDJH

168 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
Function Literals and Closures
/HW¦VH[SDQGRXUSUHYLRXVmapH[DPSOHDELW
// code-examples/FP/basics/list-map-closure-example-script.scala

var factor = 3
val multiplier = (i:Int) => i * factor

val l1 = List(1, 2, 3, 4, 5) map multiplier

factor = 5
val l2 = List(1, 2, 3, 4, 5) map multiplier

println(l1)
println(l2)

:HGHILQHGDYDULDEOH factorWRXVHDVWKHPXOWLSOLFDWLRQIDFWRUDQGZHSXOOHGRXW
WKH SUHYLRXV DQRQ\PRXV IXQFWLRQ LQWR D YDOXH FDOOHG multiplier WKDW QRZ XVHV
factor7KHQZHPDSRYHUDOLVWRILQWHJHUVDVZHGLGEHIRUH$IWHUWKHILUVWFDOOWR
mapZHFKDQJHfactorDQGPDSDJDLQ+HUHLVWKHRXWSXW
List(3, 6, 9, 12, 15)
List(5, 10, 15, 20, 25)

(YHQWKRXJKmultiplierZDVDQLPPXWDEOHIXQFWLRQYDOXHLWVEHKDYLRUFKDQJHGZKHQ
factorFKDQJHG
7KHUHDUHWZRIUHHYDULDEOHVLQ multiplier iDQG factor2QHRIWKHP iLVDIRUPDO
SDUDPHWHUWRWKHIXQFWLRQ+HQFHLWLVERXQGWRDQHZYDOXHHDFKWLPH multiplierLV
FDOOHG
+RZHYHUfactorLVQRWDIRUPDOSDUDPHWHUEXWDUHIHUHQFHWRDYDULDEOHLQWKHHQFORVLQJ
VFRSH +HQFH WKH FRPSLOHU FUHDWHV D FORVXUH WKDW HQFRPSDVVHV RU £FORVHV RYHU¤
multiplierDQGWKHH[WHUQDOFRQWH[WRIWKHXQERXQGYDULDEOHV multiplierUHIHUHQFHV
WKHUHE\ELQGLQJWKRVHYDULDEOHVDVZHOO
7KLVLVZK\WKHEHKDYLRURI multiplierFKDQJHGDIWHUFKDQJLQJ factor,WUHIHUHQFHV
factorDQGUHDGVLWVFXUUHQWYDOXHHDFKWLPH,IDIXQFWLRQKDVQRH[WHUQDOUHIHUHQFHV
WKHQLWLVWULYLDOO\FORVHGRYHULWVHOI1RH[WHUQDOFRQWH[WLVUHTXLUHG

Purity Inside Versus Outside


,IZHFDOOHGsin(x)WKRXVDQGVRIWLPHVZLWKWKHVDPHYDOXHRIxLWZRXOGEHZDVWHIXOLI
LWFDOFXODWHGWKHVDPHYDOXHHYHU\VLQJOHWLPH(YHQLQ£SXUH¤IXQFWLRQDOOLEUDULHVLWLV
FRPPRQWRSHUIRUPLQWHUQDORSWLPL]DWLRQVOLNHFDFKLQJSUHYLRXVO\FRPSXWHGYDOXHV
VRPHWLPHVFDOOHGPHPRL]DWLRQ &DFKLQJLQWURGXFHVVLGHHIIHFWVDVWKHVWDWHRIWKH
FDFKHLVPRGLILHG
+RZHYHUWKLVODFNRISXULW\VKRXOGEHRSDTXHWRWKHXVHU H[FHSWSHUKDSVLQWHUPVRI
WKH SHUIRUPDQFH LPSDFW  ,I \RX DUH GHVLJQLQJ IXQFWLRQDO OLEUDULHV HQVXUH WKDW WKH\

Functional Programming in Scala | 169

Download at WoweBook.Com
SUHVHUYHWKHSXULW\RIWKHLUDEVWUDFWLRQVLQFOXGLQJWKHEHKDYLRURIUHIHUHQWLDOWUDQVSDU
HQF\DQGLWVLPSOLFDWLRQVIRUFRQFXUUHQF\
<RXFDQVHHH[DPSOHVRIIXQFWLRQDOOLEUDULHVZLWKPXWDEOHLQWHUQDOVLQWKH6FDODOLEUDU\
7KHPHWKRGVLQListRIWHQXVHPXWDEOHORFDOYDULDEOHVIRUHIILFLHQWWUDYHUVDO7KHORFDO
YDULDEOHVDUHWKUHDGVDIHDVDUHWKHWUDYHUVDOVVLQFHListsWKHPVHOYHVDUHLPPXWDEOH

Recursion
5HFXUVLRQSOD\VDODUJHUUROHLQSXUHIXQFWLRQDOSURJUDPPLQJWKDQLQLPSHUDWLYHSUR
JUDPPLQJLQSDUWEHFDXVHRIWKHUHVWULFWLRQWKDWYDULDEOHVDUHLPPXWDEOH)RUH[DPSOH
\RXFDQ¦WKDYHORRSFRXQWHUVZKLFKZRXOGFKDQJHRQHDFKSDVVWKURXJKDORRS2QH
ZD\WRLPSOHPHQWORRSLQJLQDSXUHO\IXQFWLRQDOZD\LVZLWKUHFXUVLRQ
&DOFXODWLQJ IDFWRULDOV SURYLGHV D JRRG H[DPSOH +HUH LV DQ LPSHUDWLYH ORRS
LPSOHPHQWDWLRQ
// code-examples/FP/recursion/factorial-loop-script.scala

def factorial_loop(i: BigInt): BigInt = {


var result = BigInt(1)
for (j <- 2 to i.intValue)
result *= j
result
}

for (i <- 1 to 10)


format("%s: %s\n", i, factorial_loop(i))

%RWKWKHORRSFRXQWHU jDQGWKH resultDUHPXWDEOHYDULDEOHV )RUVLPSOLFLW\ZH¦UH


LJQRULQJLQSXWQXPEHUVWKDWDUHOHVVWKDQRUHTXDOWR]HUR 7KHRXWSXWRIWKHVFULSWLV
WKHIROORZLQJ
1: 1
2: 2
3: 6
4: 24
5: 120
6: 720
7: 5040
8: 40320
9: 362880
10: 3628800

+HUH¦VDILUVWSDVVDWDUHFXUVLYHLPSOHPHQWDWLRQ
// code-examples/FP/recursion/factorial-recur1-script.scala

def factorial(i: BigInt): BigInt = i match {


case _ if i == 1 => i
case _ => i * factorial(i - 1)
}

170 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
for (i <- 1 to 10)
format("%s: %s\n", i, factorial(i))

7KHRXWSXWLVWKHVDPHEXWQRZWKHUHDUHQRPXWDEOHYDULDEOHV5HFXUVLRQQRWRQO\
KHOSV XV DYRLG PXWDEOH YDULDEOHV LW LV DOVR WKH PRVW QDWXUDO ZD\ WR H[SUHVV VRPH
IXQFWLRQVSDUWLFXODUO\PDWKHPDWLFDOIXQFWLRQV7KHUHFXUVLYHGHILQLWLRQLQRXUVHFRQG
factorialLVVWUXFWXUDOO\VLPLODUWRDGHILQLWLRQIRUIDFWRULDOVWKDW\RXPLJKWVHHLQD
PDWKHPDWLFVERRN
+RZHYHUWKHUHDUHWZRSRWHQWLDOSUREOHPVZLWKUHFXUVLRQWKHSHUIRUPDQFHRYHUKHDG
RIUHSHDWHGIXQFWLRQLQYRFDWLRQVDQGWKHULVNRIVWDFNRYHUIORZ
3HUIRUPDQFHSUREOHPVLQDUHFXUVLYHVFHQDULRFDQVRPHWLPHVEHDGGUHVVHGZLWKPHPR
L]DWLRQEXWFDUHVKRXOGEHWDNHQWKDWWKHVSDFHUHTXLUHPHQWVRIFDFKLQJGRQ¦WRXWZHLJK
WKHSHUIRUPDQFHEHQHILWV
6WDFNRYHUIORZFDQEHDYRLGHGE\FRQYHUWLQJWKHUHFXUVLYHLQYRFDWLRQLQWRDORRSRI
VRPHNLQG,QIDFWWKH6FDODFRPSLOHUFDQGRWKLVFRQYHUVLRQIRU\RXIRUVRPHNLQGVRI
UHFXUVLYHLQYRFDWLRQVZKLFKZHGHVFULEHQH[W

Tail Calls and Tail-Call Optimization


$SDUWLFXODUNLQGRIUHFXUVLRQLVFDOOHGWDLOFDOOUHFXUVLRQZKLFKRFFXUVZKHQDIXQFWLRQ
FDOOVLWVHOIDVLWVILQDORSHUDWLRQ7DLOFDOOUHFXUVLRQLVYHU\LPSRUWDQWEHFDXVHLWLVWKH
HDVLHVWNLQGRIUHFXUVLRQWRRSWLPL]HE\FRQYHUVLRQLQWRDORRS/RRSVHOLPLQDWHWKH
SRWHQWLDORIDVWDFNRYHUIORZDQGWKH\LPSURYHSHUIRUPDQFHE\HOLPLQDWLQJWKHUHFXU
VLYHIXQFWLRQFDOORYHUKHDG:KLOHWDLOUHFXUVLRQRSWLPL]DWLRQVDUHQRW\HWVXSSRUWHG
QDWLYHO\RQWKH-90scalacFDQGRWKHP
+RZHYHURXUIDFWRULDOH[DPSOHLVQRWDWDLOUHFXUVLRQEHFDXVHfactorialFDOOVLWVHOIDQG
WKHQGRHVDPXOWLSOLFDWLRQZLWKWKHUHVXOWV7KHUHLVDZD\WRLPSOHPHQWfactorialLQ
DWDLOUHFXUVLYHZD\:HDFWXDOO\VDZDQLPSOHPHQWDWLRQLQ£1HVWLQJ0HWKRG'HILQL
WLRQV¤RQSDJH+RZHYHUWKDWH[DPSOHGLGQ¦WXVHVRPHFRQVWUXFWVZH¦YHOHDUQHG
DERXWVLQFHVXFKDVforFRPSUHKHQVLRQVDQGSDWWHUQPDWFKLQJ6RKHUH¦VDQHZLP
SOHPHQWDWLRQRIfactorialFDOFXODWHGZLWKWDLOFDOOUHFXUVLRQ
// code-examples/FP/recursion/factorial-recur2-script.scala

def factorial(i: BigInt): BigInt = {


def fact(i: BigInt, accumulator: BigInt): BigInt = i match {
case _ if i == 1 => accumulator
case _ => fact(i - 1, i * accumulator)
}
fact(i, 1)
}

for (i <- 1 to 10)


format("%s: %s\n", i, factorial(i))

Tail Calls and Tail-Call Optimization | 171

Download at WoweBook.Com
7KLVVFULSWSURGXFHVWKHVDPHRXWSXWDVEHIRUH1RZfactorialGRHVDOOWKHZRUNZLWK
DQHVWHGPHWKRGfactWKDWLVWDLOUHFXUVLYHEHFDXVHLWSDVVHVDQaccumulatorDUJXPHQW
WRKROGWKHFRPSXWDWLRQLQSURJUHVV7KLVDUJXPHQWLVFRPSXWHGZLWKDPXOWLSOLFDWLRQ
EHIRUHWKHUHFXUVLYHFDOOWR factZKLFKLVQRZWKHYHU\ODVWWKLQJWKDWLVGRQH,QRXU
SUHYLRXVLPSOHPHQWDWLRQWKLVPXOWLSOLFDWLRQZDVGRQHDIWHUWKHFDOOWRfact:KHQZH
FDOOfact(1)ZHVLPSO\UHWXUQWKHDFFXPXODWHGYDOXH
,I \RX FDOO RXU RULJLQDO QRQWDLO UHFXUVLYH LPSOHPHQWDWLRQ RI factorial ZLWK D ODUJH
QXPEHU¢VD\¢\RX¦OOFDXVHDVWDFNRYHUIORZRQDW\SLFDOGHVNWRSFRPSXWHU
7KHWDLOUHFXUVLYHLPSOHPHQWDWLRQZRUNVVXFFHVVIXOO\UHWXUQLQJDYHU\ODUJHQXPEHU
7KLVLGLRPRIQHVWLQJDWDLOUHFXUVLYHIXQFWLRQWKDWXVHVDQDFFXPXODWRULVDYHU\XVHIXO
WHFKQLTXH IRU FRQYHUWLQJ PDQ\ UHFXUVLYH DOJRULWKPV LQWR WDLO UHFXUVLRQV WKDW FDQ EH
RSWLPL]HGLQWRORRSVE\scalac

7KHWDLOFDOORSWLPL]DWLRQZRQ¦WEHDSSOLHGZKHQDPHWKRGWKDWFDOOV
LWVHOIPLJKWEHRYHUULGGHQLQDGHULYHGW\SH7KHPHWKRGPXVWEHSULYDWH
RUILQDOGHILQHGLQDQ objectRUQHVWHGLQDQRWKHUPHWKRG OLNH fact
HDUOLHU 7KHQHZ@tailrecDQQRWDWLRQLQYHUVLRQZLOOWULJJHUDQHUURU
LI WKH FRPSLOHU FDQ¦W RSWLPL]H WKH DQQRWDWHG PHWKRG 6HH £$QQRWD
WLRQV¤RQSDJH

Trampoline for Tail Calls


$WUDPSROLQHLVDORRSWKDWZRUNVWKURXJKDOLVWRIIXQFWLRQVFDOOLQJHDFKRQHLQWXUQ
7KHPHWDSKRURIERXQFLQJWKHIXQFWLRQVRIIDWUDPSROLQHLVWKHVRXUFHRIWKHQDPH
&RQVLGHUDNLQGRIUHFXUVLRQZKHUHDIXQFWLRQAGRHVQ¦WFDOOLWVHOIUHFXUVLYHO\EXWLQ
VWHDGLWFDOOVDQRWKHUIXQFWLRQ BZKLFKFDOOV AZKLFKFDOOV BHWF7KLVNLQGRIEDFN
DQGIRUWKUHFXUVLRQFDQDOVREHFRQYHUWHGLQWRDORRSXVLQJDWUDPSROLQH1RWHWKDW
WUDPSROLQHV LPSRVH D SHUIRUPDQFH RYHUKHDG EXW WKH\ DUH LGHDO IRU SXUH IXQFWLRQDO
UHFXUVLRQV YHUVXVDQLPSHUDWLYHHTXLYDOHQW WKDWZRXOGRWKHUZLVHH[KDXVWWKHVWDFN
6XSSRUWIRUWKLVRSWLPL]DWLRQLVSODQQHGIRU6FDODYHUVLRQDOWKRXJKLWKDVQRW\HW
EHHQLPSOHPHQWHGDWWKHWLPHRIWKLVZULWLQJ

Functional Data Structures


7KHUHDUHVHYHUDOGDWDVWUXFWXUHVWKDWDUHFRPPRQLQIXQFWLRQDOSURJUDPPLQJPRVW
RIZKLFKDUHFRQWDLQHUVOLNHFROOHFWLRQV/DQJXDJHVOLNH(UODQJUHO\RQYHU\IHZW\SHV
ZKLOHRWKHUIXQFWLRQDOODQJXDJHVSURYLGHDULFKHUW\SHV\VWHP
7KHFRPPRQGDWDVWUXFWXUHVVXSSRUWWKHVDPHVXEVHWRIKLJKHURUGHUIXQFWLRQVIRU
UHDGRQO\WUDYHUVDODQGDFFHVVWRWKHHOHPHQWVLQWKHGDWDVWUXFWXUHV7KHVHIHDWXUHV
PDNHWKHPVXLWDEOHDV£SURWRFROV¤IRUPLQLPL]LQJWKHFRXSOLQJEHWZHHQFRPSRQHQWV
ZKLOHVXSSRUWLQJGDWDH[FKDQJH

172 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
,QIDFWWKHVHGDWDVWUXFWXUHVDQGWKHLURSHUDWLRQVDUHVRXVHIXOWKDWPDQ\ODQJXDJHV
VXSSRUWWKHPLQFOXGLQJWKRVHWKDWDUHQRWFRQVLGHUHGIXQFWLRQDOODQJXDJHVOLNH-DYD
DQG5XE\-DYDGRHVQ¦WVXSSRUWKLJKHURUGHUIXQFWLRQVGLUHFWO\,QVWHDGIXQFWLRQYDO
XHVKDYHWREHZUDSSHGLQREMHFWV5XE\XVHVprocsDQGlambdasDVIXQFWLRQYDOXHV

Lists in Functional Programming


/LVWVDUHWKHPRVWFRPPRQGDWDVWUXFWXUHLQIXQFWLRQDOSURJUDPPLQJ7KH\DUHWKH
FRUHRIWKHILUVWIXQFWLRQDOSURJUDPPLQJODQJXDJH/LVS
,QWKHLQWHUHVWRILPPXWDELOLW\DQHZOLVWLVFUHDWHGZKHQ\RXDGGDQHOHPHQWWRDOLVW
,WLVFRQYHQWLRQDOWRSUHSHQGWKHQHZHOHPHQWWRWKHOLVWDVZH¦YHVHHQEHIRUH
// code-examples/FP/datastructs/list-script.scala

val list1 = List("Programming", "Scala")


val list2 = "People" :: "should" :: "read" :: list1
println(list2)

%HFDXVHWKH::RSHUDWRUELQGVWRWKHULJKWWKHGHILQLWLRQRIlist2LVHTXLYDOHQWWRERWK
RIWKHIROORZLQJYDULDWLRQV
val list2 = ("People" :: ("should" :: ("read" :: list1)))
val list2 = list1.::("read").::("should").::("People")

,QWHUPVRISHUIRUPDQFHSUHSHQGLQJLV2  :H¦OOVHHZK\ZKHQZHGLYHLQWR6FDOD¦V
LPSOHPHQWDWLRQRIListLQ£$&ORVHU/RRNDW/LVWV¤RQSDJHDIWHUZHKDYHOHDUQHG
PRUHDERXWSDUDPHWHUL]HGW\SHVLQ6FDOD
8QOLNHVRPHRIWKHRWKHUFROOHFWLRQV6FDODRQO\GHILQHVDQLPPXWDEOHList+RZHYHU
LWDOVRGHILQHVVRPHPXWDEOHOLVWW\SHVVXFKDVListBufferDQGLinkedList

Maps in Functional Programming


3HUKDSVWKHVHFRQGPRVWFRPPRQGDWDVWUXFWXUHLVWKHPDSUHIHUUHGWRDVDKDVKRU
GLFWLRQDU\LQRWKHUODQJXDJHVDQGQRWWREHFRQIXVHGZLWKWKH mapIXQFWLRQZHVDZ
HDUOLHU0DSVDUHXVHGWRKROGSDLUVRINH\VDQGYDOXHV
,QWKHLQWHUHVWRIPLQLPDOLVPPDSVFRXOGEHLPSOHPHQWHGZLWKOLVWV(YHU\HYHQHOH
PHQWLQWKHOLVW FRXQWLQJIURP]HUR FRXOGEHDNH\IROORZHGE\WKHYDOXHLQWKHQH[W
RGGSRVLWLRQ,QSUDFWLFHPDSVDUHXVXDOO\LPSOHPHQWHGLQRWKHUZD\VIRUHIILFLHQF\
6FDODVXSSRUWVWKHVSHFLDOLQLWLDOL]DWLRQV\QWD[ZHVDZSUHYLRXVO\
val stateCapitals = Map(
"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
// ...
"Wyoming" -> "Cheyenne")

Functional Data Structures | 173

Download at WoweBook.Com
7KHscala.collection.Map[A,+B]WUDLWRQO\GHILQHVPHWKRGVIRUUHDGLQJWKHMap7KHUH
DUH GHULYHG WUDLWV IRU LPPXWDEOH DQG PXWDEOH PDSV scala.collection.immuta
ble.Map[A,+B] DQG scala.collection.mutable.Map[A,B] UHVSHFWLYHO\ 7KH\ GHILQH +
DQG-RSHUDWRUVIRUDGGLQJDQGUHPRYLQJHOHPHQWVDQG++DQG--RSHUDWRUVIRUDGGLQJ
DQGUHPRYLQJHOHPHQWVGHILQHGLQ IteratorsRI PairsZKHUHHDFK PairLVDNH\YDOXH
SDLU

<RXPLJKWKDYHQRWLFHGWKDWWKH+GRHVQRWDSSHDULQIURQWRIWKHBW\SH
SDUDPHWHUVIRUscala.collection.mutable.Map<RX¦OOVHHZK\LQ£9DU
LDQFHRI0XWDEOH7\SHV¤RQSDJH

Sets in Functional Programming


6HWVDUHOLNHOLVWVEXWWKH\UHTXLUHHDFKHOHPHQWWREHXQLTXH6HWVFRXOGDOVREHLP
SOHPHQWHGXVLQJOLVWVDVORQJDVWKHHTXLYDOHQWRIWKHOLVW£FRQV¤RSHUDWRU :: ILUVW
FKHFNVWKDWWKHHOHPHQWGRHVQ¦WDOUHDG\H[LVWLQWKHVWRUDJHOLVW7KLVSURSHUW\PHDQV
WKDWHOHPHQWLQVHUWLRQZRXOGEH2 1 LIDVWRUDJHOLVWZHUHXVHGDQGWKHRUGHURIWKH
HOHPHQWVLQWKHVHWZRXOGQ¦WQHFHVVDULO\PDWFKWKHRUGHURI£LQVHUWLRQ¤RSHUDWLRQV,Q
SUDFWLFHVHWVDUHXVXDOO\LPSOHPHQWHGZLWKPRUHHIILFLHQWGDWDVWUXFWXUHV
-XVWDVIRUMapWKHscala.collection.Set[A]WUDLWRQO\GHILQHVPHWKRGVIRUUHDGLQJWKH
Set 7KHUH DUH GHULYHG WUDLWV IRU LPPXWDEOH DQG PXWDEOH VHWV scala.collec
tion.immutable.Set[A]DQG scala.collection.mutable.Set[A]UHVSHFWLYHO\7KH\GH
ILQH+DQG-RSHUDWRUVIRUDGGLQJDQGUHPRYLQJHOHPHQWVDQG++DQG--RSHUDWRUVIRU
DGGLQJDQGUHPRYLQJHOHPHQWVGHILQHGLQ Iterators ZKLFKFRXOGEHRWKHUVHWVOLVWV
HWF 

Other Data Structures in Functional Programming


2WKHUIDPLOLDUGDWDVWUXFWXUHVOLNH TuplesDQG ArraysZLOODSSHDULQIXQFWLRQDOODQ
JXDJHV7\SLFDOO\WKH\¦UHXVHGWRSURYLGHVRPHFRQYHQLHQWIHDWXUHQRWVXSSRUWHGE\D
PRUHFRPPRQIXQFWLRQDOW\SH,QPRVWFDVHVWKH\FRXOGEHUHSODFHGZLWKOLVWV

Traversing, Mapping, Filtering, Folding, and Reducing


7KHIXQFWLRQDOFROOHFWLRQVZHMXVWGLVFXVVHG¢OLVWVPDSVVHWVDVZHOODVWXSOHVDQG
DUUD\V¢DOOVXSSRUWVHYHUDOFRPPRQRSHUDWLRQVEDVHGRQUHDGRQO\WUDYHUVDO,QIDFW
WKLVXQLIRUPLW\FDQEHH[SORLWHGLIDQ\£FRQWDLQHU¤W\SHDOVRVXSSRUWVWKHVHRSHUDWLRQV
)RUH[DPSOHDQOptionFRQWDLQV]HURRURQHHOHPHQWVLILWLVDNoneRUSomeUHVSHFWLYHO\

174 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
Traversal
7KHVWDQGDUGWUDYHUVDOPHWKRGIRU6FDODFRQWDLQHUVLVforeachZKLFKLVGHILQHGE\WKH
IterableWUDLWVWKDWWKHFRQWDLQHUVPL[LQ,WLV2 1 LQWKHQXPEHURIHOHPHQWV+HUH
LVDQH[DPSOHRILWVXVHIRUOLVWVDQGPDSV
// code-examples/FP/datastructs/foreach-script.scala

List(1, 2, 3, 4, 5) foreach { i => println("Int: " + i) }

val stateCapitals = Map(


"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
"Wyoming" -> "Cheyenne")

stateCapitals foreach { kv => println(kv._1 + ": " + kv._2) }

7KHVLJQDWXUHRIforeachLVWKHIROORZLQJ
trait Iterable[+A] {
...
def foreach(f : (A) => Unit) : Unit = ...
...
}

foreach LV D KLJKHURUGHU IXQFWLRQ WKDW WDNHV D IXQFWLRQ DUJXPHQW WKH RSHUDWLRQ WR
SHUIRUPRQHDFKHOHPHQW1RWHWKDWIRUDPDS ALVDFWXDOO\DWXSOHDVVKRZQLQWKH
H[DPSOH$OVRforeachUHWXUQVUnitforeachLVQRWLQWHQGHGWRFUHDWHQHZFROOHFWLRQV
ZH¦OOVHHH[DPSOHVRIRSHUDWLRQVWKDWFUHDWHFROOHFWLRQVVKRUWO\
2QFH \RX KDYH foreach \RX FDQ LPSOHPHQW DOO WKH RWKHU WUDYHUVDO RSHUDWLRQV ZH¦OO
GLVFXVV QH[W DQG PRUH $ ORRN DW Iterable ZLOO VKRZ WKDW LW VXSSRUWV PHWKRGV IRU
ILOWHULQJ FROOHFWLRQV ILQGLQJ HOHPHQWV WKDW PDWFK VSHFLILHG FULWHULD FDOFXODWLQJ WKH
QXPEHURIHOHPHQWVDQGVRIRUWK
7KHPHWKRGVZH¦OOGLVFXVVQH[WDUHKDOOPDUNVRIIXQFWLRQDOSURJUDPPLQJPDSSLQJ
ILOWHULQJIROGLQJDQGUHGXFLQJ

Mapping
:H¦YHHQFRXQWHUHGWKHmapPHWKRGEHIRUH,WUHWXUQVDQHZFROOHFWLRQRIWKHVDPHVL]H
DVWKHRULJLQDOFROOHFWLRQ,WLVDOVRDPHPEHURIIterableDQGLWVVLJQDWXUHLV
trait Iterable[+A] {
...
def map[B](f : (A) => B) : Iterable[B] = ...
...
}

Traversing, Mapping, Filtering, Folding, and Reducing | 175

Download at WoweBook.Com
7KHSDVVHGLQIXQFWLRQ f FDQWUDQVIRUPDQRULJLQDOHOHPHQWRIW\SH AWRDQHZW\SH
B+HUHLVDQH[DPSOH
// code-examples/FP/datastructs/map-script.scala

val stateCapitals = Map(


"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
"Wyoming" -> "Cheyenne")

val lengths = stateCapitals map { kv => (kv._1, kv._2.length) }


println(lengths)

7KLV VFULSW SURGXFHV WKH RXWSXW ArrayBuffer((Alabama,10), (Alaska,6), (Wyoming,


8)) 7KDW LV ZH FRQYHUW WKH Pair[String,String] HOHPHQWV WR DQ ArrayBuffer RI
Pair[String,Int]HOHPHQWV:KHUHGLGWKH ArrayBufferFRPHIURP",WWXUQVRXWWKDW
Iterable.mapFUHDWHVDQGUHWXUQVDQArrayBufferDVWKHQHZIterableFROOHFWLRQ
7KLVEULQJVXSDJHQHUDOFRQIOLFWEHWZHHQLPPXWDEOHW\SHVDQGREMHFWRULHQWHGW\SH
KLHUDUFKLHV,IDEDVHW\SHFUHDWHVDQHZLQVWDQFHRQPRGLILFDWLRQKRZGRHVLWNQRZ
ZKDWNLQGRIW\SHWRFUHDWH"
<RXFRXOGVROYHWKLVSUREOHPWZRZD\V)LUVW\RXFRXOGKDYHHDFKW\SHLQWKHKLHUDUFK\
RYHUULGHPHWKRGVOLNH mapWRUHWXUQDQLQVWDQFHRIWKHLURZQW\SH7KLVDSSURDFKLV
HUURUSURQHWKRXJKDVLWZRXOGEHHDV\WRIRUJHWWRRYHUULGHDOOVXFKPHWKRGVZKHQD
QHZW\SHLVDGGHG
(YHQLI\RXDOZD\VUHPHPEHUWRRYHUULGHHDFKPHWKRG\RXKDYHWKHGLOHPPDRIKRZ
WRLPSOHPHQWWKHRYHUULGH'R\RXFDOOWKHsuperPHWKRGWRUHXVHWKHDOJRULWKPWKHQ
LWHUDWHWKURXJKWKHUHWXUQHGLQVWDQFHWRFUHDWHDQHZLQVWDQFHRIWKHFRUUHFWW\SH"7KDW
ZRXOGEHLQHIILFLHQW<RXFRXOGFRS\DQGSDVWHWKHDOJRULWKPLQWRHDFKRYHUULGHEXW
WKDWFUHDWHVLVVXHVRIFRGHEORDWPDLQWDLQDELOLW\DQGVNHZ
7KHUH¦VDQDOWHUQDWLYHDSSURDFKGRQ¦WHYHQWU\+RZLVWKHQHZLQVWDQFHWKDWLVUHWXUQHG
DFWXDOO\XVHG"'RZHUHDOO\FDUHLILWKDVWKH£ZURQJ¤W\SH".HHSLQPLQGWKDWDOOZH
XVXDOO\FDUHDERXWDUHWKHORZOHYHODEVWUDFWLRQVOLNHOLVWVPDSVDQGVHWV,QWKHFDVH
RI IXQFWLRQDO GDWD VWUXFWXUHV WKH GHULYHG W\SHV ZH PLJKW LPSOHPHQW XVLQJ REMHFW
RULHQWHGLQKHULWDQFHDUHPRVWRIWHQLPSOHPHQWDWLRQRSWLPL]DWLRQV7KH6FDODW\SHKL
HUDUFK\ IRU FRQWDLQHUV GRHV KDYH D IHZ OHYHOV RI DEVWUDFWLRQV DW WKH ERWWRP HJ
CollectionH[WHQGV IterableH[WHQGV AnyRefEXWDERYH CollectionDUH Seq SDUHQWRI
List MapSetHWF
7KDWVDLGLI\RXUHDOO\QHHGDMap\RXFDQFUHDWHRQHHDVLO\HQRXJK
// code-examples/FP/datastructs/map2-script.scala

val stateCapitals = Map(


"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
"Wyoming" -> "Cheyenne")

val map2 = stateCapitals map { kv => (kv._1, kv._2.length) }

176 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
// val lengths = Map(map2) // ERROR: won't work
val lengths = Map[String,Int]() ++ map2

println(lengths)

7KHFRPPHQWHGRXWOLQHVXJJHVWVWKDWLWZRXOGEHQLFHLI\RXFRXOGVLPSO\SDVVWKH
QHZIterableWRMap.applyEXWWKLVGRHVQ¦WZRUN+HUHLVWKHVLJQDWXUHRIMap.apply
object Map {
...
def apply[A, B](elems : (A, B)*) : Map[A, B] = ...
...
}

,WH[SHFWVDYDULDEOHDUJXPHQWOLVWQRWDQIterable+RZHYHUZHFDQFUHDWHDQHPSW\
PDSRIWKHULJKWW\SHDQGWKHQDGGWKHQHZIterableWRLWXVLQJWKH++PHWKRGZKLFK
UHWXUQVDQHZMap
6RZHFDQJHWWKH MapZHZDQWZKHQZHPXVWKDYHRQH:KLOHLWZRXOGEHQLFHLI
PHWKRGVOLNHmapUHWXUQHGWKHVDPHFROOHFWLRQW\SHZHVDZWKDWWKHUHLVQRHDV\ZD\
WRGRWKLV,QVWHDGZHDFFHSWWKDWmapDQGVLPLODUPHWKRGVUHWXUQDQDEVWUDFWLRQOLNH
IterableDQGWKHQUHO\RQWKHVSHFLILFVXEW\SHVWRWDNH IterablesDVLQSXWDUJXPHQWV
IRUSRSXODWLQJWKHFROOHFWLRQ
$UHODWHG MapRSHUDWLRQLV flatMapZKLFKFDQEHXVHGWR£IODWWHQ¤DKLHUDUFKLFDOGDWD
VWUXFWXUHUHPRYH£HPSW\¤HOHPHQWVHWF+HQFHXQOLNH mapLWPD\QRWUHWXUQDQHZ
FROOHFWLRQRIWKHVDPHVL]HDVWKHRULJLQDOFROOHFWLRQ
// code-examples/FP/datastructs/flatmap-script.scala

val graph = List(


"a", List("b1", "b2", "b3"), List("c1", List("c21", Nil, "c22"), Nil, "e")
)

def flatten(list: List[_]): List[_] = list flatMap {


case head :: tail => head :: flatten(tail)
case Nil => Nil
case x => List(x)
}

println(flatten(graph))

7KLVVFULSWUHGXFHVWKHKLHUDUFKLFDO graphWR List(a, b1, b2, b3, c1, c21, c22, e)
1RWLFHWKDWWKHNilHOHPHQWVKDYHEHHQUHPRYHG:HXVHGList[_]EHFDXVHZHZRQ¦W
NQRZZKDWWKHW\SHSDUDPHWHUVDUHIRUDQ\HPEHGGHGOLVWVZKHQZH¦UHWUDYHUVLQJWKH
RXWHUOLVWGXHWRW\SHHUDVXUH
+HUHLVWKHVLJQDWXUHIRUflatMapDORQJZLWKmapIRUFRPSDULVRQ
trait Iterable[+A] {
...
def map[B] (f : (A) => B) : Iterable[B] = ...
def flatMap[B](f : (A) => Iterable[B]) : Iterable[B]

Traversing, Mapping, Filtering, Folding, and Reducing | 177

Download at WoweBook.Com
...
}

(DFK SDVV PXVW UHWXUQ DQ Iterable[B] QRW D B $IWHU JRLQJ WKURXJK WKH FROOHFWLRQ
flatMapZLOO£IODWWHQ¤DOOWKRVHIterablesLQWRRQHFROOHFWLRQ1RWHWKDWflatMapZRQ¦W
IODWWHQHOHPHQWVEH\RQGRQHOHYHO,IRXUIXQFWLRQOLWHUDOOHDYHVQHVWHGOLVWVLQWDFWWKH\
ZRQ¦WEHIODWWHQHGIRUXV

Filtering
,WLVFRPPRQWRWUDYHUVHDFROOHFWLRQDQGH[WUDFWDQHZFROOHFWLRQIURPLWZLWKHOHPHQWV
WKDWPDWFKFHUWDLQFULWHULD
// code-examples/FP/datastructs/filter-script.scala

val stateCapitals = Map(


"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
"Wyoming" -> "Cheyenne")

val map2 = stateCapitals filter { kv => kv._1 startsWith "A" }

println( map2 )

7KHUHDUHVHYHUDOGLIIHUHQWNLQGVRIPHWKRGVGHILQHGLQIterableIRUILOWHULQJRURWKHU
ZLVHUHWXUQLQJSDUWRIWKHRULJLQDOFROOHFWLRQ FRPPHQWVDGDSWHGIURPWKH6FDODGRFV 
trait Iterable[+A] {
...
// Returns this iterable without its n first elements. If this iterable
// has less than n elements, the empty iterable is returned.
def drop (n : Int) : Collection[A] = ...

// Returns the longest suffix of this iterable whose first element does
// not satisfy the predicate p.
def dropWhile (p : (A) => Boolean) : Collection[A] = ...

// Apply a predicate p to all elements of this iterable object and


// return true, iff there is at least one element for which p yields true.
def exists (p : (A) => Boolean) : Boolean = ...

// Returns all the elements of this iterable that satisfy the predicate p.
// The order of the elements is preserved.
def filter (p : (A) => Boolean) : Iterable[A] = ...

// Find and return the first element of the iterable object satisfying a
// predicate, if any.
def find (p : (A) => Boolean) : Option[A] = ...

// Returns index of the first element satisying a predicate, or -1.


def findIndexOf (p : (A) => Boolean) : Int = ...

// Apply a predicate p to all elements of this iterable object and return


// true, iff the predicate yields true for all elements.

178 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
def forall (p : (A) => Boolean) : Boolean = ...

// Returns the index of the first occurence of the specified object in


// this iterable object.
def indexOf [B >: A](elem : B) : Int = ...

// Partitions this iterable in two iterables according to a predicate.


def partition (p : (A) => Boolean) : (Iterable[A], Iterable[A]) = ...

// Checks if the other iterable object contains the same elements.


def sameElements [B >: A](that : Iterable[B]) : Boolean = ...

// Returns an iterable consisting only over the first n elements of this


// iterable, or else the whole iterable, if it has less than n elements.
def take (n : Int) : Collection[A] = ...

// Returns the longest prefix of this iterable whose elements satisfy the
// predicate p.
def takeWhile (p : (A) => Boolean) : Iterable[A] = ...
}

7\SHVOLNHMapDQGSetKDYHDGGLWLRQDOPHWKRGV

Folding and Reducing


:H¦OOGLVFXVVIROGLQJDQGUHGXFLQJLQWKHVDPHVHFWLRQDVWKH\¦UHVLPLODU%RWKDUH
RSHUDWLRQVIRU£VKULQNLQJ¤DFROOHFWLRQGRZQWRDVPDOOHUFROOHFWLRQRUDVLQJOHYDOXH
)ROGLQJVWDUWVZLWKDQLQLWLDO£VHHG¤YDOXHDQGSURFHVVHVHDFKHOHPHQWLQWKHFRQWH[WRI
WKDWYDOXH,QFRQWUDVWUHGXFLQJGRHVQ¦WVWDUWZLWKDXVHUVXSSOLHGLQLWLDOYDOXH5DWKHU
LWXVHVWKHILUVWHOHPHQWDVWKHLQLWLDOYDOXH
// code-examples/FP/datastructs/foldreduce-script.scala

List(1,2,3,4,5,6) reduceLeft(_ + _)

List(1,2,3,4,5,6).foldLeft(10)(_ * _)

7KLVVFULSWUHGXFHVWKHOLVWRILQWHJHUVE\DGGLQJWKHPWRJHWKHUUHWXUQLQJ,WWKHQ
IROGVWKHVDPHOLVWXVLQJPXOWLSOLFDWLRQZLWKDVHHGRIUHWXUQLQJ
5HGXFLQJFDQ¦WZRUNRQDQHPSW\FROOHFWLRQVLQFHWKHUHZRXOGEHQRWKLQJWRUHWXUQ
,QWKLVFDVHDQH[FHSWLRQLVWKURZQ)ROGLQJRQDQHPSW\FROOHFWLRQZLOOVLPSO\UHWXUQ
WKHVHHGYDOXH
)ROGLQJDOVRRIIHUVPRUHRSWLRQVIRUWKHILQDOUHVXOW+HUHLVD£IROG¤RSHUDWLRQWKDWLV
UHDOO\DPDSRSHUDWLRQ
// code-examples/FP/datastructs/foldleft-map-script.scala

List(1, 2, 3, 4, 5, 6).foldLeft(List[String]()) {
(list, x) => ("<" + x + ">") :: list
}.reverse

Traversing, Mapping, Filtering, Folding, and Reducing | 179

Download at WoweBook.Com
,WUHWXUQV List(<1>, <2>, <3>, <4>, <5>, <6>)1RWHWKDWZHKDGWRFDOO reverseRQ
WKHUHVXOWWRJHWEDFNDOLVWLQWKHVDPHRUGHUDVWKHLQSXWOLVW
+HUHDUHWKHVLJQDWXUHVIRUWKHYDULRXVIROGDQGUHGXFHRSHUDWLRQVLQIterable
trait Iterable[+A] {
...
// Combines the elements of this iterable object together using the
// binary function op, from left to right, and starting with the value z.
def foldLeft [B](z : B)(op : (B, A) => B) : B

// Combines the elements of this list together using the binary function
// op, from right to left, and starting with the value z.
def foldRight [B](z : B)(op : (A, B) => B) : B

// Similar to foldLeft but can be used as an operator with the order of


// list and zero arguments reversed. That is, z /: xs is the same as
// xs foldLeft z
def /: [B](z : B)(op : (B, A) => B) : B

// An alias for foldRight. That is, xs :\ z is the same as xs foldRight z


def :\ [B](z : B)(op : (A, B) => B) : B

// Combines the elements of this iterable object together using the


// binary operator op, from left to right
def reduceLeft [B >: A](op : (B, A) => B) : B

// Combines the elements of this iterable object together using the


// binary operator op, from right to left
def reduceRight [B >: A](op : (A, B) => B) : B

0DQ\SHRSOHFRQVLGHUWKHRSHUDWRUIRUPV:\IRUfoldRightDQG/:IRUfoldLeftWREH
DOLWWOHWRRREVFXUHDQGKDUGWRUHPHPEHU'RQ¦WIRUJHWWKHLPSRUWDQFHRIFRPPXQL
FDWLQJZLWK\RXUUHDGHUVZKHQZULWLQJFRGH
:K\DUHWKHUHOHIWDQGULJKWIRUPVRIIROGDQGUHGXFH")RUWKHILUVWH[DPSOHVZHVKRZHG
DGGLQJDQGPXOWLSO\LQJDOLVWRILQWHJHUVWKH\ZRXOGUHWXUQWKHVDPHUHVXOW&RQVLGHU
DfoldRightYHUVLRQRIRXUODVWH[DPSOHWKDWXVHGIROGWRPDSWKHLQWHJHUVWRVWULQJV
// code-examples/FP/datastructs/foldright-map-script.scala

List(1, 2, 3, 4, 5, 6).foldRight(List[String]()) {
(x, list) => ("<" + x + ">") :: list
}

7KLV VFULSW SURGXFHV List(<1>, <2>, <3>, <4>, <5>, <6>) ZLWKRXW KDYLQJ WR FDOO
reverseDVZHGLGEHIRUH1RWHDOVRWKDWWKHDUJXPHQWVWRWKHIXQFWLRQOLWHUDODUHUH
YHUVHG FRPSDUHG WR WKH DUJXPHQWV IRU foldLeft DV UHTXLUHG E\ WKH GHILQLWLRQ RI
foldRight
%RWK foldLeft DQG reduceLeft SURFHVV WKH HOHPHQWV IURP OHIW WR ULJKW +HUH LV WKH
foldLeftVHTXHQFHIRUList(1,2,3,4,5,6).foldLeft(10)(_ * _)
((((((10 * 1) * 2) * 3) * 4) * 5) * 6)
((((((10) * 2) * 3) * 4) * 5) * 6)

180 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
(((((20) * 3) * 4) * 5) * 6)
((((60) * 4) * 5) * 6)
(((240) * 5) * 6)
((1200) * 6)
(7200)

+HUHLVWKHfoldRightVHTXHQFH
(1 * (2 * (3 * (4 * (5 * (6 * 10))))))
(1 * (2 * (3 * (4 * (5 * (60))))))
(1 * (2 * (3 * (4 * (300)))))
(1 * (2 * (3 * (1200))))
(1 * (2 * (3600)))
(1 * (7200))
(7200)

,WWXUQVRXWWKDWfoldLeftDQGreduceLeftKDYHRQHYHU\LPSRUWDQWDGYDQWDJHRYHUWKHLU
£ULJKWKDQGHG¤EUHWKUHQWKH\DUHWDLOFDOOUHFXUVLYHDQGDVVXFKWKH\FDQEHQHILWIURP
WDLOFDOORSWLPL]DWLRQ
,I\RXVWDUHDWWKHSUHYLRXVEUHDNGRZQVIRUPXOWLSO\LQJWKHLQWHJHUV\RXFDQSUREDEO\
VHHZK\WKH\DUHWDLOFDOOUHFXUVLYH5HFDOOWKDWDWDLOFDOOPXVWEHWKHODVWRSHUDWLRQLQ
DQLWHUDWLRQ)RUHDFKOLQHLQWKHfoldRightVHTXHQFHWKHRXWHUPRVWPXOWLSOLFDWLRQFDQ¦W
EHGRQHXQWLOWKHLQQHUPRVWPXOWLSOLFDWLRQVDOOFRPSOHWHVRWKHRSHUDWLRQLVQ¦WWDLO
UHFXUVLYH
,QWKHIROORZLQJVFULSWWKHILUVWOLQHSULQWVZKLOHWKHVHFRQGOLQHFDXVHVD
VWDFNRYHUIORZ
// code-examples/FP/datastructs/reduceleftright-script.scala

println((1 to 1000000) reduceLeft(_ + _))


println((1 to 1000000) reduceRight(_ + _))

6RZK\KDYHERWKNLQGVRIUHFXUVLRQ",I\RX¦UHQRWZRUULHGDERXWRYHUIORZDULJKW
UHFXUVLRQPLJKWEHWKHPRVWQDWXUDOILWIRUWKHRSHUDWLRQ\RXDUHGRLQJ5HFDOOWKDW
ZKHQZHXVHG foldLeftWRPDSLQWHJHUVWRVWULQJVZHKDGWRUHYHUVHWKHUHVXOW7KDW
ZDVHDV\HQRXJKWRGRLQWKDWFDVHEXWLQJHQHUDOWKHUHVXOWRIDOHIWUHFXUVLRQPLJKW
QRWDOZD\VEHHDV\WRFRQYHUWWRWKHULJKWIRUP

Functional Options
<RX¦OOILQGWKHIXQFWLRQDORSHUDWLRQVZH¦YHH[SORUHGWKURXJKRXWWKH6FDODOLEUDU\DQG
QRW H[FOXVLYHO\ RQ FROOHFWLRQ FODVVHV 7KH DOZD\V KDQG\ Option FRQWDLQHU VXSSRUWV
filtermapflatMapDQGRWKHUIXQFWLRQDOO\RULHQWHGPHWKRGVWKDWDUHDSSOLHGRQO\LI
WKHOptionLVQ¦WHPSW\ WKDWLVLILW¦VDSomeDQGQRWDNone 
/HW¦VVHHWKLVLQSUDFWLFH
// code-examples/FP/datastructs/option-script.scala

val someNumber = Some(5)


val noneNumber = None

Traversing, Mapping, Filtering, Folding, and Reducing | 181

Download at WoweBook.Com
for (option <- List(noneNumber, someNumber)) {
option.map(n => println(n * 5))
}

,QWKLVH[DPSOHZHDWWHPSWWRPXOWLSO\WKHFRQWHQWVRIWZROptionsE\ILYH1RUPDOO\
WU\LQJWRPXOWLSO\DnullYDOXHZRXOGUHVXOWLQDQHUURU%XWEHFDXVHWKHLPSOHPHQWDWLRQ
RI mapRQ OptionRQO\DSSOLHVWKHSDVVHGLQIXQFWLRQZKHQLW¦VQRQHPSW\ZHGRQ¦W
KDYHWRZRUU\DERXWWHVWLQJIRUWKHSUHVHQFHRIDYDOXHRUKDQGOLQJDQH[FHSWLRQZKHQ
ZHPDSRYHUWKHNone
)XQFWLRQDORSHUDWLRQVRQOptionsVDYHXVIURPH[WUDFRQGLWLRQDOH[SUHVVLRQVRUSDWWHUQ
PDWFKLQJ3DWWHUQPDWFKLQJWKRXJKLVDSRZHUIXOWRROZLWKLQWKHFRQWH[WRIIXQFWLRQDO
SURJUDPPLQJDVZH¦OOH[SORUHLQWKHQH[WVHFWLRQ

Pattern Matching
:H¦YHVHHQPDQ\H[DPSOHVRISDWWHUQPDWFKLQJWKURXJKRXWWKLVERRN:HJRWRXUILUVW
WDVWHLQ£$7DVWHRI&RQFXUUHQF\¤RQSDJHZKHUHZHXVHGSDWWHUQPDWFKLQJLQRXU
$FWRUWKDWGUHZJHRPHWULFVKDSHV:HGLVFXVVHGSDWWHUQPDWFKLQJLQGHSWKLQ£3DWWHUQ
0DWFKLQJ¤RQSDJH
3DWWHUQPDWFKLQJLVDIXQGDPHQWDOWRROLQIXQFWLRQDOSURJUDPPLQJ,W¦VMXVWDVLPSRU
WDQWDVSRO\PRUSKLVPLVLQREMHFWRULHQWHGSURJUDPPLQJDOWKRXJKWKHJRDOVRIWKHWZR
WHFKQLTXHVDUHYHU\GLIIHUHQW
3DWWHUQPDWFKLQJLVDQHOHJDQWZD\WRGHFRPSRVHREMHFWVLQWRWKHLUFRQVWLWXHQWSDUWV
IRUSURFHVVLQJ2QWKHIDFHRILWSDWWHUQPDWFKLQJIRUWKLVSXUSRVHVHHPVWRYLRODWHWKH
JRDORIHQFDSVXODWLRQWKDWREMHFWVSURYLGH,PPXWDELOLW\WKRXJKODUJHO\UHFWLILHVWKLV
FRQIOLFW7KHULVNWKDWWKHSDUWVRIDQREMHFWPLJKWEHFKDQJHGRXWVLGHRIWKHFRQWURORI
WKHHQFORVLQJREMHFWLVDYRLGHG
)RUH[DPSOHLIZHKDYHDPersonFODVVWKDWFRQWDLQVDOLVWRIDGGUHVVHVZHGRQ¦WPLQG
H[SRVLQJWKDWOLVWWRFOLHQWVLIWKHOLVWLVLPPXWDEOH7KH\FDQ¦WXQH[SHFWHGO\FKDQJHWKH
OLVW
+RZHYHUH[SRVLQJFRQVWLWXHQWSDUWVSRWHQWLDOO\FRXSOHVFOLHQWVWRWKHW\SHVRIWKRVH
SDUWV:HFDQ¦WFKDQJHKRZWKHSDUWVDUHLPSOHPHQWHGZLWKRXWEUHDNLQJWKHFOLHQWV$
ZD\WRPLQLPL]HWKLVULVNLVWRH[SRVHWKHORZHVWOHYHODEVWUDFWLRQVSRVVLEOH:KHQ
FOLHQWVDFFHVVDSHUVRQ¦VDGGUHVVHVGRWKH\UHDOO\QHHGWRNQRZWKDWWKH\DUHVWRUHGLQ
DListRULVLWVXIILFLHQWWRNQRZWKDWWKH\DUHVWRUHGLQDQIterableRUSeq",IVRWKHQ
ZHFDQFKDQJHWKHLPSOHPHQWDWLRQRIWKHDGGUHVVHVDVORQJDVWKH\VWLOOVXSSRUWWKRVH
DEVWUDFWLRQV2IFRXUVHZH¦YHNQRZQIRUDORQJWLPHLQREMHFWRULHQWHGSURJUDPPLQJ
WKDW \RX VKRXOG RQO\ FRXSOH WR DEVWUDFWLRQV QRW FRQFUHWH GHWDLOV IRU H[DPSOH VHH
>0DUWLQ@ 

182 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
)XQFWLRQDO SDWWHUQ PDWFKLQJ DQG REMHFWRULHQWHG SRO\PRUSKLVP DUH SRZHUIXO
FRPSOHPHQWVWRHDFKRWKHU:HVDZWKLVLQWKH$FWRUH[DPSOHLQ£$7DVWHRI&RQFXU
UHQF\¤RQSDJHZKHUHZHPDWFKHGRQWKH ShapeDEVWUDFWLRQEXWFDOOHGWKHSRO\
PRUSKLFdrawRSHUDWLRQ

Partial Functions
<RX¦YH VHHQ SDUWLDOO\ DSSOLHG IXQFWLRQV RU SDUWLDO IXQFWLRQV WKURXJKRXW WKLV ERRN
:KHQ\RX¦YHVHHQDQXQGHUVFRUHSDVVHGWRDPHWKRG\RX¦YHSUREDEO\VHHQSDUWLDO
DSSOLFDWLRQDWZRUN
3DUWLDOIXQFWLRQVDUHH[SUHVVLRQVLQZKLFKQRWDOORIWKHDUJXPHQWVGHILQHGLQDIXQFWLRQ
DUHVXSSOLHGDVSDUDPHWHUVWRWKHIXQFWLRQ,Q6FDODSDUWLDOIXQFWLRQVDUHXVHGWREXQGOH
XSDIXQFWLRQLQFOXGLQJLWVSDUDPHWHUVDQGUHWXUQW\SHDQGDVVLJQWKDWIXQFWLRQWRD
YDULDEOHRUSDVVLWDVDQDUJXPHQWWRDQRWKHUIXQFWLRQ
7KLVLVDELWFRQIXVLQJXQWLOZHVHHLWLQSUDFWLFH
// code-examples/FP/partial/partial-script.scala

def concatUpper(s1: String, s2: String): String = (s1 + " " + s2).toUpperCase

val c = concatUpper _
println(c("short", "pants"))

val c2 = concatUpper("short", _: String)


println(c2("pants"))

&DOOLQJ concatUpperZLWKDQXQGHUVFRUH _ WXUQVWKHPHWKRGLQWRDIXQFWLRQYDOXH


,Q WKH ILUVW SDUW RI WKH H[DPSOH ZH¦YH DVVLJQHG D SDUWLDOO\ DSSOLHG YHUVLRQ RI
concatUpperWRWKHYDOXHc:HWKHQDSSO\LWLPSOLFLWO\FDOOLQJWKHapplyPHWKRGRQc
E\SDVVLQJSDUDPHWHUVWRLWGLUHFWO\7KHUHWXUQHGYDOXHLVWKHQSULQWHG
,QWKHVHFRQGSDUWZH¦YHVSHFLILHGWKHILUVWSDUDPHWHUWRconcatUpperEXWQRWWKHVHF
RQGDOWKRXJKZHKDYHVSHFLILHGWKHW\SHRIWKHVHFRQGSDUDPHWHU:H¦YHDVVLJQHGWKLV
YDULDQWWRDVHFRQGYDOXHc27RSURGXFHWKHVDPHRXWSXWDVZHVDZEHIRUHZHQHHG
RQO\SDVVLQDVLQJOHYDOXHZKHQZHDSSO\c2:H¦YHDSSOLHGSDUWRIWKHIXQFWLRQLQWKH
DVVLJQPHQWWRc2DQGZH£ILOOLQWKHEODQNV¤ZKHQZHFDOOc2RQWKHQH[WOLQH
:H¦YHVHHQSDUWLDOO\DSSOLHGIXQFWLRQVZLWKRXWWKHXQGHUVFRUHV\QWD[DVZHOO
List("short", "pants").map(println)

,QWKLVH[DPSOHprintlnLVWKHSDUWLDOO\DSSOLHGIXQFWLRQ,W¦VDSSOLHGZKHQLQYRNHGE\
PDSSLQJRYHUHDFKHOHPHQWLQWKHOLVW%HFDXVHWKHPDSRSHUDWLRQH[SHFWVDIXQFWLRQ
DVDQDUJXPHQWZHGRQ¦WQHHGWRZULWH map(println _)7KHWUDLOLQJXQGHUVFRUHWKDW
WXUQVprintlnLQWRDIXQFWLRQYDOXHLVLPSOLHGLQWKLVFRQWH[W
$QRWKHUZD\RIWKLQNLQJRISDUWLDOIXQFWLRQVLVDVIXQFWLRQVWKDWZLOOLQIRUP\RXZKHQ
\RXVXSSO\WKHPZLWKSDUDPHWHUVWKDWDUHRXWRIWKHLUGRPDLQ(YHU\SDUWLDOIXQFWLRQ

Partial Functions | 183

Download at WoweBook.Com
LV DV \RX PLJKW JXHVV RI WKH W\SH PartialFunction 7KLV WUDLW GHILQHV D PHWKRG
orElseWKDWWDNHVDQRWKHUPartialFunction6KRXOGWKHILUVWSDUWLDOIXQFWLRQQRWDSSO\
WKHVHFRQGZLOOEHLQYRNHG
$JDLQWKLVLVHDVLHUXQGHUVWRRGLQSUDFWLFH
// code-examples/FP/partial/orelse-script.scala

val truthier: PartialFunction[Boolean, String] = { case true => "truthful" }


val fallback: PartialFunction[Boolean, String] = { case x => "sketchy" }
val tester = truthier orElse fallback

println(tester(1 == 1))
println(tester(2 + 2 == 5))

,QWKLVH[DPSOHtesterLVDSDUWLDOIXQFWLRQFRPSRVHGRIWZRRWKHUSDUWLDOIXQFWLRQV
truthierDQGfallback,QWKHILUVWprintlnVWDWHPHQWtruthierLVH[HFXWHGEHFDXVHWKH
SDUWLDOIXQFWLRQ¦VLQWHUQDOFDVHPDWFKHV,QWKHVHFRQG fallbackLVH[HFXWHGEHFDXVH
WKHYDOXHRIWKHH[SUHVVLRQLVRXWVLGHRIWKHGRPDLQRItruthier
7KHcaseVWDWHPHQWVZH¦YHVHHQWKURXJKRXUH[SORUDWLRQRI6FDODDUHH[SDQGHGLQWHU
QDOO\ WR SDUWLDOO\ DSSOLHG IXQFWLRQV 7KH IXQFWLRQV SURYLGH WKH DEVWUDFW PHWKRG
isDefinedAtDIHDWXUHRIWKH PartialFunctionWUDLWXVHGWRVSHFLI\WKHERXQGDULHVRID
SDUWLDOIXQFWLRQ¦VGRPDLQ
// code-examples/FP/partial/isdefinedat-script.scala

val pantsTest: PartialFunction[String, String] = {


case "pants" => "yes, we have pants!"
}

println(pantsTest.isDefinedAt("pants"))
println(pantsTest.isDefinedAt("skort"))

+HUHRXUSDUWLDOIXQFWLRQLVDWHVWIRUWKHVWULQJ"pants":KHQZHLQTXLUHDVWRZKHWKHU
WKH VWULQJ "pants" LV GHILQHG IRU WKLV IXQFWLRQ WKH UHVXOW LV true %XW IRU WKH VWULQJ
"skort"WKHUHVXOWLVfalse:HUHZHGHILQLQJRXURZQSDUWLDOIXQFWLRQZHFRXOGSUR
YLGHDQLPSOHPHQWDWLRQRIisDefinedAtWKDWSHUIRUPVDQ\DUELWUDU\WHVWIRUWKHERXQ
GDULHVRIRXUIXQFWLRQ

Currying
-XVWDV\RXHQFRXQWHUHGSDUWLDOO\DSSOLHGIXQFWLRQVEHIRUHZHGHILQHGWKHP\RX¦YHDOVR
VHHQ FXUULHG IXQFWLRQV 1DPHG DIWHU PDWKHPDWLFLDQ +DVNHOO &XUU\ IURP ZKRP WKH
+DVNHOOODQJXDJHDOVRJHWLWVQDPH FXUU\LQJWUDQVIRUPVDIXQFWLRQWKDWWDNHVPXOWLSOH
SDUDPHWHUVLQWRDFKDLQRIIXQFWLRQVHDFKWDNLQJDVLQJOHSDUDPHWHU
,Q6FDODFXUULHGIXQFWLRQVDUHGHILQHGZLWKPXOWLSOHSDUDPHWHUOLVWVDVIROORZV
def cat(s1: String)(s2: String) = s1 + s2

2IFRXUVHZHFRXOGGHILQHPRUHWKDQWZRSDUDPHWHUVRQDFXUULHGIXQFWLRQLIZHOLNH

184 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
:HFDQDOVRXVHWKHIROORZLQJV\QWD[WRGHILQHDFXUULHGIXQFWLRQ
def cat(s1: String) = (s2: String) => s1 + s2

:KLOHWKHSUHYLRXVV\QWD[LVPRUHUHDGDEOHLQRXUHVWLPDWLRQXVLQJWKLVV\QWD[HOLP
LQDWHVWKHUHTXLUHPHQWRIDWUDLOLQJXQGHUVFRUHZKHQWUHDWLQJWKHFXUULHGIXQFWLRQDVD
SDUWLDOO\DSSOLHGIXQFWLRQ
&DOOLQJRXUFXUULHGVWULQJFRQFDWHQDWLRQIXQFWLRQORRNVOLNHWKLVLQWKH6FDOD5(3/
scala> cat("foo")("bar")
res1: java.lang.String = foobar

:HFDQDOVRFRQYHUWPHWKRGVWKDWWDNHPXOWLSOHSDUDPHWHUVLQWRDFXUULHGIRUPZLWK
WKHFunction.curriedPHWKRG
scala> def cat(s1: String, s2: String) = s1 + s2
cat: (String,String)java.lang.String

scala> val curryCat = Function.curried(cat _)


curryCat: (String) => (String) => java.lang.String = <function>

scala> cat("foo", "bar") == curryCat("foo")("bar")


res2: Boolean = true

,QWKLVH[DPSOHZHWUDQVIRUPDIXQFWLRQWKDWWDNHVWZRDUJXPHQWVcatLQWRLWVFXUULHG
HTXLYDOHQWWKDWWDNHVPXOWLSOHSDUDPHWHUOLVWV,I catKDGWDNHQWKUHHSDUDPHWHUVLWV
FXUULHGHTXLYDOHQWZRXOGWDNHWKUHHOLVWVRIDUJXPHQWVDQGVRRQ7KHWZRIRUPVDUH
IXQFWLRQDOO\HTXLYDOHQWDVGHPRQVWUDWHGE\WKHHTXDOLW\WHVWEXWcurryCatFDQQRZEH
XVHGDVWKHEDVLVRIDSDUWLDOO\DSSOLHGIXQFWLRQDVZHOO
scala> val partialCurryCat = curryCat("foo")(_)
partialCurryCat: (String) => java.lang.String = <function>

scala> partialCurryCat("bar")
res3: java.lang.String = foobar

,QSUDFWLFHWKHSULPDU\XVHIRUFXUU\LQJLVWRVSHFLDOL]HIXQFWLRQVIRUSDUWLFXODUW\SHV
RIGDWD<RXFDQVWDUWZLWKDQH[WUHPHO\JHQHUDOFDVHDQGXVHWKHFXUULHGIRUPRID
IXQFWLRQWRQDUURZGRZQWRSDUWLFXODUFDVHV
$VDVLPSOHH[DPSOHRIWKLVDSSURDFKWKHIROORZLQJFRGHSURYLGHVVSHFLDOL]HGIRUPV
RIDEDVHIXQFWLRQWKDWKDQGOHVPXOWLSOLFDWLRQ
def multiplier(i: Int)(factor: Int) = i * factor
val byFive = multiplier(5) _
val byTen = multiplier(10) _

:HVWDUWZLWKmultiplierZKLFKWDNHVWZRSDUDPHWHUVDQLQWHJHUDQGDQRWKHULQWHJHU
WRPXOWLSO\WKHILUVWRQHE\:HWKHQFXUU\WZRVSHFLDOFDVHVRImultiplierLQWRIXQFWLRQ
YDOXHV1RWHWKHWUDLOLQJXQGHUVFRUHVZKLFKLQGLFDWHWRWKHFRPSLOHUWKDWWKHSUHFHGLQJ
H[SUHVVLRQLVWREHFXUULHG,QSDUWLFXODUWKHZLOGFDUGXQGHUVFRUHVLQGLFDWHWKDWWKH
UHPDLQLQJDUJXPHQWV LQWKLVH[DPSOHRQHDUJXPHQW DUHXQVSHFLILHG

Currying | 185

Download at WoweBook.Com
,QWKH6FDODFRQVROHZHJHWSUHGLFWDEOHRXWSXWZKHQFDOOLQJRXUFXUULHGIXQFWLRQV
scala> byFive(2)
res4: Int = 10

scala> byTen(2)
res5: Int = 20

:H¦OOUHYLVLWWKHcurryPHWKRGLQ£)XQFWLRQ7\SHV¤RQSDJH
$V\RXFDQVHHFXUU\LQJDQGSDUWLDOO\DSSOLHGIXQFWLRQVDUHFORVHO\UHODWHGFRQFHSWV
<RXPD\VHHWKHPUHIHUUHGWRDOPRVWLQWHUFKDQJHDEO\EXWZKDW¦VLPSRUWDQWLVWKHLU
DSSOLFDWLRQ QRSXQLQWHQGHG 

Implicits
7KHUHDUHWLPHVZKHQ\RXKDYHDQLQVWDQFHRIRQHW\SHDQG\RXQHHGWRXVHLWLQD
FRQWH[WZKHUHDGLIIHUHQWEXWSHUKDSVDVLPLODUW\SHLVUHTXLUHG)RUWKH£RQHRII¤FDVH
\RXPLJKWFUHDWHDQLQVWDQFHRIWKHUHTXLUHGW\SHXVLQJWKHVWDWHRIWKHLQVWDQFH\RX
DOUHDG\KDYH+RZHYHUIRUWKHJHQHUDOFDVHLIWKHUHDUHPDQ\VXFKRFFXUUHQFHVLQWKH
FRGH\RXZRXOGUDWKHUKDYHDQDXWRPDWHGFRQYHUVLRQPHFKDQLVP
$VLPLODUSUREOHPRFFXUVZKHQ\RXFDOORQHRUPRUHIXQFWLRQVUHSHDWHGO\DQGKDYHWR
SDVVWKHVDPHYDOXHWRDOOWKHLQYRFDWLRQV<RXPLJKWOLNHDZD\RIVSHFLI\LQJDGHIDXOW
YDOXHIRUWKDWSDUDPHWHUVRLWLVQRWQHFHVVDU\WRVSHFLI\LWH[SOLFLWO\DOOWKHWLPH
7KH6FDODNH\ZRUGimplicitFDQEHXVHGWRVXSSRUWERWKQHHGV

Implicit Conversions
&RQVLGHUWKHIROORZLQJFRGHIUDJPHQW
val name: String = "scala"
println(name.capitalize.reverse)

,WSULQWVWKHIROORZLQJ
alacS

:HVDZLQ£7KH3UHGHI2EMHFW¤RQSDJHWKDWPredefGHILQHVWKHStringW\SHWREH
java.lang.String \HW WKH PHWKRGV capitalize DQG reverse DUHQ¦W GHILQHG RQ
java.lang.String+RZGLGWKLVFRGHZRUN"
7KH6FDODOLEUDU\GHILQHVD£ZUDSSHU¤FODVVFDOOHG scala.runtime.RichStringWKDWKDV
WKHVHPHWKRGVDQGWKHFRPSLOHUFRQYHUWHGWKHnameVWULQJWRLWLPSOLFLWO\XVLQJDVSHFLDO
PHWKRGGHILQHGLQPredefFDOOHGstringWrapper
implicit def stringWrapper(x: String) = new runtime.RichString(x)

7KHimplicitNH\ZRUGWHOOVWKHFRPSLOHULWFDQXVHWKLVPHWKRGIRUDQ£LPSOLFLW¤FRQ
YHUVLRQIURPD StringWRD RichStringZKHQHYHUWKHODWWHULVUHTXLUHG7KHFRPSLOHU
GHWHFWHGDQDWWHPSWWRFDOOD capitalizePHWKRGDQGLWGHWHUPLQHGWKDW RichString

186 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
KDVVXFKDPHWKRG7KHQLWORRNHGZLWKLQWKHFXUUHQWVFRSHIRUDQ implicitPHWKRG
WKDWFRQYHUWVStringWRRichStringILQGLQJstringWrapper
$VZH¦OOVHHLQ£9LHZVDQG9LHZ%RXQGV¤RQSDJHWKHVHFRQYHUVLRQPHWKRGVDUH
VRPHWLPHVFDOOHGYLHZVLQWKHVHQVHWKDWRXUstringWrapperFRQYHUVLRQSURYLGHVDYLHZ
IURPStringWRRichString
Predef GHILQHV PDQ\ RWKHU LPSOLFLW FRQYHUVLRQ PHWKRGV PRVW RI ZKLFK IROORZ WKH
QDPLQJFRQYHQWLRQ old2NewZKHUH oldLVWKHW\SHRIREMHFWDYDLODEOHDQG NewLVWKH
GHVLUHGW\SH+RZHYHUWKHUHLVQRUHVWULFWLRQRQWKHQDPHVRIFRQYHUVLRQPHWKRGV
7KHUHDUHDOVRDQXPEHURIRWKHU RichZUDSSHUFODVVHVGHILQHGLQWKH scala.runtime
SDFNDJH
+HUHLVDVXPPDU\RIWKHORRNXSUXOHVXVHGE\WKHFRPSLOHUWRILQGDQGDSSO\FRQYHUVLRQ
PHWKRGV)RUPRUHGHWDLOVVHH>6FDOD6SHF@
 1RFRQYHUVLRQZLOOEHDWWHPSWHGLIWKHREMHFWDQGPHWKRGFRPELQDWLRQW\SHFKHFN
VXFFHVVIXOO\
 2QO\PHWKRGVZLWKWKHimplicitNH\ZRUGDUHFRQVLGHUHG
 2QO\ LPSOLFLW PHWKRGV LQ WKH FXUUHQW VFRSH DUH FRQVLGHUHG DV ZHOO DV LPSOLFLW
PHWKRGVGHILQHGLQWKHFRPSDQLRQREMHFWRIWKHWDUJHWW\SH
 ,PSOLFLWPHWKRGVDUHQ¦WFKDLQHGWRJHWIURPWKHDYDLODEOHW\SHWKURXJKLQWHUPHGL
DWH W\SHV WR WKH target W\SH 2QO\ D PHWKRG WKDW WDNHV D VLQJOH DYDLODEOH W\SH
LQVWDQFHDQGUHWXUQVDWDUJHWW\SHLQVWDQFHZLOOEHFRQVLGHUHG
 1RFRQYHUVLRQLVDWWHPSWHGLIPRUHWKDQRQHSRVVLEOHFRQYHUVLRQPHWKRGFRXOG
EHDSSOLHG7KHUHPXVWEHRQHDQGRQO\RQHSRVVLELOLW\
:KDWLI\RXFDQ¦WGHILQHDFRQYHUVLRQPHWKRGLQDFRPSDQLRQREMHFWWRVDWLVI\WKH
WKLUGUXOHSHUKDSVEHFDXVH\RXFDQ¦WPRGLI\RUFUHDWHWKHFRPSDQLRQREMHFW",QWKLV
FDVHGHILQHWKHPHWKRGVRPHZKHUHHOVHDQGLPSRUWLW1RUPDOO\\RXZLOOGHILQHDQ
objectZLWKMXVWWKHFRQYHUVLRQPHWKRG V QHHGHG+HUHLVDQH[DPSOH
// code-examples/FP/implicits/implicit-conversion-script.scala
import scala.runtime.RichString

class FancyString(val str: String)

object FancyString2RichString {
implicit def fancyString2RichString(fs: FancyString) =
new RichString(fs.str)
}

import FancyString2RichString._

val fs = new FancyString("scala")


println(fs.capitalize.reverse)

Implicits | 187

Download at WoweBook.Com
:HFDQ¦WPRGLI\ RichStringRU PredefWRDGGDQLPSOLFLWFRQYHUVLRQPHWKRGIRURXU
FXVWRP FancyString FODVV ,QVWHDG ZH GHILQH DQ object QDPHG FancyString2Rich
StringDQGGHILQHWKHFRQYHUVLRQPHWKRGLQLW:HWKHQLPSRUWWKHFRQWHQWVRIWKLV
REMHFWDQGWKHFRQYHUWHUJHWVLQYRNHGLPSOLFLWO\LQWKHODVWOLQH7KHRXWSXWRIWKLVVFULSW
LVWKHIROORZLQJ
alacS

7KLVSDWWHUQIRUHIIHFWLYHO\DGGLQJQHZPHWKRGVWRFODVVHVKDVEHHQFDOOHG3LPS0\
/LEUDU\ VHH>2GHUVN\@ 

Implicit Function Parameters


:HVDZLQ&KDSWHUWKDW6FDODYHUVLRQDGGVVXSSRUWIRUGHIDXOWDUJXPHQWYDOXHV
OLNH\RXILQGLQRWKHUODQJXDJHVOLNH5XE\DQG&7KHUHDUHWZRRWKHUZD\VWRDFKLHYH
WKHVDPHHIIHFWLQDOOYHUVLRQVRI6FDOD7KHILUVWLVWRXVHIXQFWLRQFXUU\LQJDVZHKDYH
VHHQ7KHVHFRQGZD\LVWRGHILQHLPSOLFLWYDOXHVXVLQJWKHimplicitNH\ZRUG
/HW¦VH[DPLQHKRZLPSOLFLWYDOXHVZRUN
// code-examples/FP/implicits/implicit-parameter-script.scala
import scala.runtime.RichString

def multiplier(i: Int)(implicit factor: Int) {


println(i * factor)
}

implicit val factor = 2

multiplier(2)
multiplier(2)(3)

2XU PXOWLSOLHU WDNHV WZR OLVWV RI SDUDPHWHUV 7KH ODWWHU LQFOXGHV DQ LQWHJHU YDOXH
factor PDUNHG implicit 7KLV NH\ZRUG LQIRUPV WKH FRPSLOHU WR VHHN WKH YDOXH IRU
factorIURPWKHVXUURXQGLQJVFRSHLIDYDLODEOHRUWRXVHZKDWHYHUSDUDPHWHUKDVEHHQ
H[SOLFLWO\VXSSOLHGWRWKHIXQFWLRQ
:H¦YHGHILQHGRXURZQfactorYDOXHLQVFRSHDQGWKDWYDOXHLVXVHGLQWKHILUVWFDOOWR
multiplier ,Q WKH VHFRQG FDOO ZH¦UH H[SOLFLWO\ SDVVLQJ LQ D YDOXH IRU factor DQG LW
RYHUULGHVWKHYDOXHLQWKHVXUURXQGLQJVFRSH
(VVHQWLDOO\LPSOLFLWIXQFWLRQSDUDPHWHUVEHKDYHDVSDUDPHWHUVZLWKDGHIDXOWYDOXH
ZLWKWKHNH\GLIIHUHQFHEHLQJWKDWWKHYDOXHFRPHVIURPWKHVXUURXQGLQJVFRSH+DG
RXUfactorYDOXHUHVLGHGLQDFODVVRUREMHFWZHZRXOGKDYHKDGWRLPSRUWLWLQWRWKH
ORFDOVFRSH,IWKHFRPSLOHUFDQ¦WGHWHUPLQHWKHYDOXHWRXVHIRUDQLPSOLFLWSDUDPHWHU
DQHUURURI£QRLPSOLFLWDUJXPHQWPDWFKLQJSDUDPHWHU¤ZLOORFFXU

188 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
Final Thoughts on Implicits
,PSOLFLWVFDQEHSHULORXVO\FORVHWR£PDJLF¤:KHQXVHGH[FHVVLYHO\WKH\REIXVFDWHWKH
FRGH¦VEHKDYLRUIRUWKHUHDGHU$OVREHFDUHIXODERXWWKHLPSOHPHQWDWLRQRIDFRQYHU
VLRQPHWKRGHVSHFLDOO\LIWKHUHWXUQW\SHLVQRWH[SOLFLWO\GHFODUHG,IDIXWXUHFKDQJH
WRWKHPHWKRGDOVRFKDQJHVWKHUHWXUQW\SHLQVRPHVXEWOHZD\WKHFRQYHUVLRQPD\
VXGGHQO\IDLOWRZRUN,QJHQHUDOLPSOLFLWVFDQFDXVHP\VWHULRXVEHKDYLRUWKDWLVKDUG
WRGHEXJ
:KHQGHFLGLQJKRZWRLPSOHPHQW£GHIDXOW¤YDOXHVIRUPHWKRGDUJXPHQWVDPDMRU
DGYDQWDJHRIXVLQJGHIDXOWDUJXPHQWYDOXHV LQ6FDODYHUVLRQ LVWKDWWKHPHWKRG
PDLQWDLQHU GHFLGHV ZKDW WR XVH DV WKH GHIDXOW YDOXH 7KH LPSOHPHQWDWLRQ LV PRUH
VWUDLJKWIRUZDUG DQG \RX DYRLG WKH £PDJLF¤ RI LPSOLFLW PHWKRGV +RZHYHU D GLVDG
YDQWDJHRIXVLQJGHIDXOWDUJXPHQWYDOXHVLVWKDWLWPLJKWEHGHVLUDEOHWRXVHDGLIIHUHQW
£GHIDXOW¤YDOXHEDVHGRQWKHFRQWH[WLQZKLFKWKHPHWKRGLVEHLQJFDOOHG6FDODYHUVLRQ
SURYLGHVVRPHIOH[LELOLW\DV\RXFDQXVHDQH[SUHVVLRQIRUDQDUJXPHQWQRWMXVWD
FRQVWDQWYDOXH+RZHYHUWKDWIOH[LELOLW\PLJKWQRWEHHQRXJKLQZKLFKFDVHLPSOLFLWV
DUHDYHU\IOH[LEOHDQGSRZHUIXODOWHUQDWLYH

8VHLPSOLFLWVVSDULQJO\DQGFDXWLRXVO\$OVRFRQVLGHUDGGLQJDQH[SOLFLW
UHWXUQW\SHWR£QRQWULYLDO¤FRQYHUVLRQPHWKRGV

Call by Name, Call by Value


7\SLFDOO\SDUDPHWHUVWRIXQFWLRQVDUHE\YDOXHSDUDPHWHUVWKDWLVWKHYDOXHRIWKH
SDUDPHWHULVGHWHUPLQHGEHIRUHLWLVSDVVHGWRWKHIXQFWLRQ,QPRVWFLUFXPVWDQFHVWKLV
LVWKHEHKDYLRUZHZDQWDQGH[SHFW
%XWZKDWLIZHQHHGWRZULWHDIXQFWLRQWKDWDFFHSWVDVDSDUDPHWHUDQH[SUHVVLRQWKDW
ZHGRQ¦WZDQWHYDOXDWHGXQWLOLW¦VFDOOHGZLWKLQRXUIXQFWLRQ")RUWKLVFLUFXPVWDQFH
6FDODRIIHUVE\QDPHSDUDPHWHUV
$E\QDPHSDUDPHWHULVVSHFLILHGE\RPLWWLQJWKHSDUHQWKHVHVWKDWQRUPDOO\DFFRPSDQ\
DIXQFWLRQSDUDPHWHUDVIROORZV
def myCallByNameFunction(callByNameParameter: => ReturnType)

:LWKRXWWKLVV\QWDFWLFVKRUWFXWWKLVPHWKRGGHILQLWLRQZRXOGORRNOLNHWKHIROORZLQJ
def myCallByNameFunction(callByNameParameter: () => ReturnType)

$QGZKDW¦VPRUHZHZRXOGKDYHWRLQFOXGHWKRVHXQVLJKWO\HPSW\SDUHQWKHVHVLQ
HYHU\FDOOWRWKDWPHWKRG8VHRIE\QDPHSDUDPHWHUVUHPRYHVWKDWUHTXLUHPHQW
:HFDQXVHE\QDPHSDUDPHWHUVWRLPSOHPHQWSRZHUIXOORRSLQJFRQVWUXFWVDPRQJ
RWKHUWKLQJV/HW¦VJRFUD]\DQGLPSOHPHQWRXURZQwhileORRSWKURZLQJFXUU\LQJLQWR
WKHPL[

Call by Name, Call by Value | 189

Download at WoweBook.Com
// code-examples/FP/overrides/call-by-name-script.scala

def whileAwesome(conditional: => Boolean)(f: => Unit) {


if (conditional) {
f
whileAwesome(conditional)(f)
}
}

var count = 0

whileAwesome(count < 5) {
println("still awesome")
count += 1
}

:KDWZRXOGKDSSHQLIZHUHPRYHGWKHDUURZEHWZHHQconditional:DQGBoolean"7KH
H[SUHVVLRQcount < 5ZRXOGEHHYDOXDWHGWRtrueEHIRUHEHLQJSDVVHGLQWRRXUFXVWRP
whileORRSDQGWKHPHVVDJH£VWLOODZHVRPH¤ZRXOGEHSULQWHGWRWKHFRQVROHLQGHIL
QLWHO\%\GHOD\LQJHYDOXDWLRQXQWLOconditionalLVFDOOHGLQVLGHRXUIXQFWLRQZLWKDE\
QDPHSDUDPHWHUZHJHWWKHEHKDYLRUZHH[SHFW

Lazy Vals
,Q£2YHUULGLQJ$EVWUDFWDQG&RQFUHWH)LHOGVLQ7UDLWV¤RQSDJHZHVKRZHGVHYHUDO
VFHQDULRVZKHUHWKHRUGHURILQLWLDOL]DWLRQIRUILHOGVLQRYHUULGHVFHQDULRVFDQEHSURE
OHPDWLF:HGLVFXVVHGRQHVROXWLRQSUHLQLWLDOL]HGILHOGV1RZZHGLVFXVVWKHRWKHU
VROXWLRQZHPHQWLRQHGSUHYLRXVO\lazy valV
+HUHLVWKDWH[DPSOHUHZULWWHQZLWKDlazy val
// code-examples/FP/overrides/trait-lazy-init-val-script.scala

trait AbstractT2 {
println("In AbstractT2:")
val value: Int
lazy val inverse = { println("initializing inverse:"); 1.0/value }
//println("AbstractT2: value = "+value+", inverse = "+inverse)
}

val c2d = new AbstractT2 {


println("In c2d:")
val value = 10
}

println("Using c2d:")
println("c2d.value = "+c2d.value+", inverse = "+c2d.inverse)

7KHLVWKHRXWSXWRIWKHVFULSW
In AbstractT2:
In c2d:
Using c2d:

190 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
initializing inverse:
c2d.value = 10, inverse = 0.1

$VEHIRUHZHDUHXVLQJDQDQRQ\PRXVLQQHUFODVVWKDWLPSOLFLWO\H[WHQGVWKHWUDLW7KH
ERG\RIWKHFODVVZKLFKLQLWLDOL]HVvalueLVHYDOXDWHGDIWHUWKHWUDLW¦VERG\+RZHYHU
QRWHWKDWinverseLVGHFODUHGlazyZKLFKPHDQVWKDWWKHULJKWKDQGVLGHZLOOEHHYDOXDWHG
RQO\ZKHQinverseLVDFWXDOO\XVHG,QWKLVFDVHWKDWKDSSHQVLQWKHODVWprintlnVWDWH
PHQW2QO\WKHQLVinverseLQLWLDOL]HGXVLQJvalueZKLFKLVSURSHUO\LQLWLDOL]HGDWWKLV
SRLQW
7U\XQFRPPHQWLQJWKH printlnVWDWHPHQWDWWKHHQGRIWKH AbstractT2ERG\:KDW
KDSSHQVQRZ"
In AbstractT2:
initializing inverse:
AbstractT2: value = 0, inverse = Infinity
In c2d:
Using c2d:
c2d.value = 10, inverse = Infinity

7KLV println IRUFHV inverse WR EH HYDOXDWHG LQVLGH WKH ERG\ RI AbstractT2 EHIRUH
valueLVLQLWLDOL]HGE\WKHFODVVERG\WKHUHE\UHSURGXFLQJWKHSUREOHPZHKDGEHIRUH
7KLVH[DPSOHUDLVHVDQLPSRUWDQWSRLQWLIRWKHUvalVXVHWKHlazy valLQWKHVDPHFODVV
RUWUDLWERG\WKH\VKRXOGEHGHFODUHG lazyWRR$OVRZDWFKRXWIRUIXQFWLRQFDOOVLQ
WKHERG\WKDWXVHWKHlazy val

,IDvalLVlazyPDNHVXUHDOOXVHVRIWKHvalDUHDOVRlazy

6RKRZLVDlazy valGLIIHUHQWIURPDPHWKRGFDOO",QDPHWKRGFDOOWKHERG\LVH[HFXWHG
HYHU\WLPHWKHPHWKRGLVLQYRNHG)RUDlazy valWKHLQLWLDOL]DWLRQ£ERG\¤LVHYDOXDWHG
RQO\RQFHZKHQWKHYDULDEOHLVXVHGIRUWKHILUVWWLPH7KLVRQHWLPHHYDOXDWLRQPDNHV
OLWWOHVHQVHIRUDPXWDEOHILHOG7KHUHIRUHWKH lazyNH\ZRUGLVQRWDOORZHGRQ varV
7KH\FDQ¦WUHDOO\PDNHXVHRILWDQ\ZD\
<RXFDQDOVRXVHlazy valVWRDYRLGFRVWO\LQLWLDOL]DWLRQVWKDW\RXPD\QRWDFWXDOO\QHHG
DQGWRGHIHULQLWLDOL]DWLRQVWKDWVORZGRZQDSSOLFDWLRQVWDUWXS7KH\ZRUNZHOOLQFRQ
VWUXFWRUVZKHUHLW¦VFOHDUWRRWKHUSURJUDPPHUVWKDWDOOWKHRQHWLPHKHDY\OLIWLQJIRU
LQLWLDOL]LQJDQLQVWDQFHLVGRQHLQRQHSODFH
$QRWKHUXVHIRUOD]LQHVVLVWRPDQDJHSRWHQWLDOO\LQILQLWHGDWDVWUXFWXUHVZKHUHRQO\D
PDQDJHDEOHVXEVHWRIWKHGDWDZLOODFWXDOO\EHXVHG,QIDFWPDWKHPDWLFQRWDWLRQLV
LQKHUHQWO\OD]\:KHQZHZULWHWKH)LERQDFFLVHTXHQFHIRUH[DPSOHZHPLJKWZULWH
LWDVDQLQILQLWHVHTXHQFHVRPHWKLQJOLNHWKLV
Fib = 1, 1, 2, 3, 5, 8, ...

Lazy Vals | 191

Download at WoweBook.Com
6RPHSXUHIXQFWLRQDOODQJXDJHVDUHOD]\E\GHIDXOWVRWKH\PLPLFWKLVEHKDYLRUDV
FORVHO\DVSRVVLEOH7KLVFDQZRUNZLWKRXWH[KDXVWLQJUHVRXUFHVLIWKHXVHUQHYHUWULHV
WRXVHPRUHWKDQDILQLWHVXEVHWRIWKHVHYDOXHV6FDODLVQRWOD]\E\GHIDXOWEXWLWGRHV
RIIHU VXSSRUW IRU ZRUNLQJ ZLWK LQILQLWH GDWD VWUXFWXUHV :H¦OO DGGUHVV WKLV WRSLF LQ
£,QILQLWH'DWD6WUXFWXUHVDQG/D]LQHVV¤RQSDJH

Recap: Functional Component Abstractions


:KHQREMHFWRULHQWHGSURJUDPPLQJZHQWPDLQVWUHDPLQWKHODWH¦VDQGHDUO\¦V
WKHUHZDVJUHDWKRSHWKDWLWZRXOGXVKHULQDQHUDRIUHXVDEOHVRIWZDUHFRPSRQHQWV,W
GLGQ¦WUHDOO\ZRUNRXWWKDWZD\H[FHSWLQVRPHUDUHFDVHVOLNHWKHZLQGRZLQJ$3,VRI
YDULRXVSODWIRUPV
:K\GLGWKLVQRWKDSSHQ"7KHUHDUHFHUWDLQO\PDQ\UHDVRQVEXWDOLNHO\VRXUFHLVWKH
IDFW WKDW VLPSOH VRXUFH RU ELQDU\ LQWHURSHUDELOLW\ SURWRFROV QHYHU PDWHULDOL]HG WKDW
ZRXOGJOXHWKHVHFRPSRQHQWVWRJHWKHU7KHULFKQHVVRIREMHFW$3,VZDVWKHYHU\IDFWRU
WKDWXQGHUPLQHGFRPSRQHQWL]DWLRQ
&RPSRQHQWPRGHOVWKDWKDYHVXFFHHGHGDUHDOOEDVHGRQYHU\VLPSOHIRXQGDWLRQV,Q
WHJUDWHGFLUFXLWV ,&V LQHOHFWURQLFVSOXJLQWREXVHVZLWKQVLJQDOLQJZLUHVWKDWDUH
ERROHDQHLWKHURQRURII)URPWKDWYHU\VLPSOHSURWRFROWKHPRVWH[SORVLYHJURZWK
RIDQ\LQGXVWU\LQKXPDQKLVWRU\ZDVERUQ
+773LVDQRWKHUJRRGH[DPSOH:LWKDKDQGIXORIPHVVDJHW\SHVDQGDYHU\VLPSOH
VWDQGDUGIRUPHVVDJHFRQWHQWLWVHWWKHVWDJHIRUWKH,QWHUQHWUHYROXWLRQ5(67IXOZHE
VHUYLFHVEXLOWRQWRSRI+773DUHDOVRSURYLQJVXFFHVVIXODVFRPSRQHQWVEXWWKH\DUH
MXVWFRPSOH[HQRXJKWKDWFDUHLVUHTXLUHGWRHQVXUHWKDWWKH\ZRUNVXFFHVVIXOO\
6RLVWKHUHKRSHIRUDELQDU\RUVRXUFHOHYHOFRPSRQHQWPRGHO",WSUREDEO\ZRQ¦WEH
REMHFWRULHQWHGDVZH¦YHVHHQ5DWKHULWFRXOGEHPRUHIXQFWLRQDO
&RPSRQHQWVVKRXOGLQWHURSHUDWHE\H[FKDQJLQJDIHZLPPXWDEOHGDWDVWUXFWXUHVHJ
OLVWVDQGPDSVWKDWFDUU\ERWKGDWDDQG£FRPPDQGV¤6XFKDFRPSRQHQWPRGHOZRXOG
KDYHWKHVLPSOLFLW\QHFHVVDU\IRUVXFFHVVDQGWKHULFKQHVVUHTXLUHGWRSHUIRUPUHDOZRUN
1RWLFHKRZWKDWVRXQGVDORWOLNH+773DQG5(67
,QIDFWWKH$FWRUPRGHOKDVPDQ\RIWKHVHTXDOLWLHVDVZH¦OOH[SORUHLQWKHQH[WFKDSWHU

192 | Chapter 8:—Functional Programming in Scala

Download at WoweBook.Com
CHAPTER 9
Robust, Scalable Concurrency
with Actors

The Problems of Shared, Synchronized State


&RQFXUUHQF\LVQ¦WHDV\*HWWLQJDSURJUDPWRGRPRUHWKDQRQHWKLQJDWDWLPHKDV
WUDGLWLRQDOO\PHDQWKDVVOLQJZLWKPXWH[HVUDFHFRQGLWLRQVORFNFRQWHQWLRQDQGWKH
UHVW RI WKH XQSOHDVDQW EDJJDJH WKDW FRPHV DORQJ ZLWK PXOWLWKUHDGLQJ (YHQWEDVHG
FRQFXUUHQF\PRGHOVDOOHYLDWHVRPHRIWKHVHFRQFHUQVEXWFDQWXUQODUJHSURJUDPVLQWR
DUDW¦VQHVWRIFDOOEDFNIXQFWLRQV1RZRQGHUWKHQWKDWFRQFXUUHQWSURJUDPPLQJLVD
WDVNPRVWSURJUDPPHUVGUHDGRUDYRLGDOWRJHWKHUE\UHWUHDWLQJWRPXOWLSOHLQGHSHQG
HQWSURFHVVHVWKDWVKDUHGDWDH[WHUQDOO\ IRUH[DPSOHWKURXJKDGDWDEDVHRUPHVVDJH
TXHXH 
$ODUJHSDUWRIWKHGLIILFXOW\RIFRQFXUUHQWSURJUDPPLQJFRPHVGRZQWRVWDWHKRZGR
\RXNQRZZKDW\RXUPXOWLWKUHDGHGSURJUDPLVGRLQJDQGZKHQ":KDWYDOXHGRHVD
SDUWLFXODUYDULDEOHKROGZKHQ\RXKDYHWKUHDGVUXQQLQJRURU"+RZFDQ\RX
JXDUDQWHHWKDW\RXUSURJUDP¦VPDQ\WHQGULOVDUHQ¦WFOREEHULQJRQHDQRWKHULQDUDFHWR
WDNH DFWLRQ" $ WKUHDGEDVHG FRQFXUUHQF\ SDUDGLJP SRVHV PRUH TXHVWLRQV WKDQ LW
DQVZHUV
7KDQNIXOO\ 6FDOD RIIHUV D UHDVRQDEOH IOH[LEOH DSSURDFK WR FRQFXUUHQF\ WKDW ZH¦OO
H[SORUHLQWKLVFKDSWHU

Actors
7KRXJK\RXPD\KDYHKHDUGRI6FDODDQG$FWRUVLQWKHVDPHEUHDWK$FWRUVDUHQ¦WD
FRQFHSWXQLTXHWR6FDOD$FWRUVRULJLQDOO\LQWHQGHGIRUXVHLQ$UWLILFLDO,QWHOOLJHQFH
UHVHDUFKZHUHILUVWSXWIRUWKLQ VHH>+HZLWW@DQG>$JKD@ 6LQFHWKHQ
YDULDWLRQVRQWKHLGHDRI$FWRUVKDYHDSSHDUHGLQDQXPEHURISURJUDPPLQJODQJXDJHV
PRVWQRWDEO\LQ(UODQJDQG,R$VDQDEVWUDFWLRQ$FWRUVDUHJHQHUDOHQRXJKWKDWWKH\

193

Download at WoweBook.Com
FDQEHLPSOHPHQWHGDVDOLEUDU\ DVLQ6FDOD RUDVWKHIXQGDPHQWDOXQLWRIDFRPSX
WDWLRQDOV\VWHP

Actors in Abstract
)XQGDPHQWDOO\DQ$FWRULVDQREMHFWWKDWUHFHLYHVPHVVDJHVDQGWDNHVDFWLRQRQWKRVH
PHVVDJHV7KHRUGHULQZKLFKPHVVDJHVDUULYHLVXQLPSRUWDQWWRDQ$FWRUWKRXJKVRPH
$FWRU LPSOHPHQWDWLRQV VXFK DV 6FDOD¦V  TXHXH PHVVDJHV LQ RUGHU $Q $FWRU PLJKW
KDQGOHDPHVVDJHLQWHUQDOO\RULWPLJKWVHQGDPHVVDJHWRDQRWKHU$FWRURULWPLJKW
FUHDWHDQRWKHU$FWRUWRWDNHDFWLRQEDVHGRQWKHPHVVDJH$FWRUVDUHDYHU\KLJKOHYHO
DEVWUDFWLRQ
8QOLNHWUDGLWLRQDOREMHFWV\VWHPV ZKLFK\RXPLJKWEHWKLQNLQJWR\RXUVHOIKDYHPDQ\
RIWKHVDPHSURSHUWLHVZH¦YHGHVFULEHG $FWRUVGRQ¦WHQIRUFHDVHTXHQFHRURUGHULQJ
WRWKHLUDFWLRQV7KLVLQKHUHQWHVFKHZLQJRIVHTXHQWLDOLW\FRXSOHGZLWKLQGHSHQGHQFH
IURPVKDUHGJOREDOVWDWHDOORZ$FWRUVWRGRWKHLUZRUNLQSDUDOOHO$VZH¦OOVHHODWHURQ
WKHMXGLFLRXVXVHRILPPXWDEOHGDWDILWVWKH$FWRUPRGHOLGHDOO\DQGIXUWKHUDLGVLQ
VDIHFRPSUHKHQVLEOHFRQFXUUHQWSURJUDPPLQJ
(QRXJKWKHRU\/HW¦VVHH$FWRUVLQDFWLRQ

Actors in Scala
$WWKHLUPRVWEDVLF$FWRUVLQ6FDODDUHREMHFWVWKDWLQKHULWIURPscala.actors.Actor
// code-examples/Concurrency/simple-actor-script.scala

import scala.actors.Actor

class Redford extends Actor {


def act() {
println("A lot of what acting is, is paying attention.")
}
}

val robert = new Redford


robert.start

$VZHFDQVHHDQ$FWRUGHILQHGLQWKLVZD\PXVWEHERWKLQVWDQWLDWHGDQGVWDUWHG
VLPLODUWRKRZWKUHDGVDUHKDQGOHGLQ-DYD,WPXVWDOVRLPSOHPHQWWKHDEVWUDFWPHWKRG
actZKLFKUHWXUQVUnit2QFHZH¦YHVWDUWHGWKLVVLPSOH$FWRUWKHIROORZLQJVDJHDGYLFH
IRUWKHVSLDQVLVSULQWHGWRWKHFRQVROH
A lot of what acting is, is paying attention.

7KH scala.actorsSDFNDJHFRQWDLQVDIDFWRU\PHWKRGIRUFUHDWLQJ$FWRUVWKDWDYRLGV
PXFKRIWKHVHWXSLQWKHDERYHH[DPSOH:HFDQLPSRUWWKLVPHWKRGDQGRWKHUFRQ
YHQLHQFHPHWKRGVIURPscala.actors.Actors._+HUHLVDIDFWRU\PDGH$FWRU

194 | Chapter 9:—Robust, Scalable Concurrency with Actors

Download at WoweBook.Com
// code-examples/Concurrency/factory-actor-script.scala

import scala.actors.Actor
import scala.actors.Actor._

val paulNewman = actor {


println("To be an actor, you have to be a child.")
}

:KLOHDVXEFODVVWKDWH[WHQGVWKHActorFODVVPXVWGHILQHactLQRUGHUWREHFRQFUHWH
DIDFWRU\SURGXFHG$FWRUKDVQRVXFKOLPLWDWLRQ,QWKLVVKRUWHUH[DPSOHWKHERG\RI
WKHPHWKRGSDVVHGWR actorLVHIIHFWLYHO\SURPRWHGWRWKH actPHWKRGIURPRXUILUVW
H[DPSOH3UHGLFWDEO\WKLV$FWRUDOVRSULQWVDPHVVDJHZKHQUXQ,OOXPLQDWLQJEXWZH
VWLOOKDYHQ¦WVKRZQWKHHVVHQWLDOSLHFHRIWKH$FWRUVSX]]OHVHQGLQJPHVVDJHV

Sending Messages to Actors


$FWRUVFDQUHFHLYHDQ\VRUWRIREMHFWDVDPHVVDJHIURPVWULQJVRIWH[WWRQXPHULFW\SHV
WRZKDWHYHUFODVVHV\RX¦YHFRRNHGXSLQ\RXUSURJUDPV)RUWKLVUHDVRQ$FWRUVDQG
SDWWHUQPDWFKLQJJRKDQGLQKDQG$Q$FWRUVKRXOGRQO\DFWRQPHVVDJHVRIIDPLOLDU
W\SHV D SDWWHUQ PDWFK RQ WKH FODVV DQGRU FRQWHQWV RI D PHVVDJH LV JRRG GHIHQVLYH
SURJUDPPLQJDQGLQFUHDVHVWKHUHDGDELOLW\RI$FWRUFRGH
// code-examples/Concurrency/pattern-match-actor-script.scala

import scala.actors.Actor
import scala.actors.Actor._

val fussyActor = actor {


loop {
receive {
case s: String => println("I got a String: " + s)
case i: Int => println("I got an Int: " + i.toString)
case _ => println("I have no idea what I just got.")
}
}
}

fussyActor ! "hi there"


fussyActor ! 23
fussyActor ! 3.33

7KLVH[DPSOHSULQWVWKHIROORZLQJZKHQUXQ
I got a String: hi there
I got an Int: 23
I have no idea what I just got.

7KHERG\RI fussyActorLVD receivePHWKRGZUDSSHGLQD loop loopLVHVVHQWLDOO\D


QLFHVKRUWFXWIRU while(true)LWGRHVZKDWHYHULVLQVLGHLWVEORFNUHSHDWHGO\ receive
EORFNVXQWLOLWJHWVDPHVVDJHRIDW\SHWKDWZLOOVDWLVI\RQHRILWVLQWHUQDOSDWWHUQPDWFK
LQJFDVHV

Actors in Scala | 195

Download at WoweBook.Com
7KHILQDOOLQHVRIWKLVH[DPSOHGHPRQVWUDWHXVHRIWKH ! H[FODPDWLRQSRLQWRUEDQJ
PHWKRGWRVHQGPHVVDJHVWRRXU$FWRU,I\RX¦YHHYHUVHHQ$FWRUVLQ(UODQJ\RX¦OOILQG
WKLV V\QWD[ IDPLOLDU 7KH $FWRU LV DOZD\V RQ WKH OHIWKDQG VLGH RI WKH EDQJ DQG WKH
PHVVDJHEHLQJVHQWWRVDLG$FWRULVDOZD\VRQWKHULJKW,I\RXQHHGDPQHPRQLFIRUWKLV
JUDQXOHRIV\QWDFWLFVXJDULPDJLQHWKDW\RX¦UHDQLUDWHGLUHFWRUVKRXWLQJFRPPDQGVDW
\RXU$FWRUV

The Mailbox
(YHU\$FWRUKDVDPDLOER[LQZKLFKPHVVDJHVVHQWWRWKDW$FWRUDUHTXHXHG/HW¦VVHH
DQH[DPSOHZKHUHZHLQVSHFWWKHVL]HRIDQ$FWRU¦VPDLOER[
// code-examples/Concurrency/actor-mailbox-script.scala

import scala.actors.Actor
import scala.actors.Actor._

val countActor = actor {


loop {
react {
case "how many?" => {
println("I've got " + mailboxSize.toString + " messages in my mailbox.")
}
}
}
}

countActor ! 1
countActor ! 2
countActor ! 3
countActor ! "how many?"
countActor ! "how many?"
countActor ! 4
countActor ! "how many?"

7KLVH[DPSOHSURGXFHVWKHIROORZLQJRXWSXW
I've got 3 messages in my mailbox.
I've got 3 messages in my mailbox.
I've got 4 messages in my mailbox.

1RWHWKDWWKHILUVWDQGVHFRQGOLQHVRIRXWSXWDUHLGHQWLFDO%HFDXVHRXU$FWRUZDVVHW
XSVROHO\WRSURFHVVPHVVDJHVRIWKHVWULQJ"how many?"WKRVHPHVVDJHVGLGQ¦WUHPDLQ
LQLWVPDLOER[2QO\WKHPHVVDJHVRIW\SHVZHGLGQ¦WNQRZDERXW¢LQWKLVFDVHInt¢
UHPDLQHGXQSURFHVVHG

,I \RX VHH DQ $FWRU¦V PDLOER[ VL]H EDOORRQLQJ XQH[SHFWHGO\ \RX¦UH
SUREDEO\VHQGLQJPHVVDJHVRIDW\SHWKDWWKH$FWRUGRHVQ¦WNQRZDERXW
,QFOXGHDFDWFKDOOFDVH _ ZKHQSDWWHUQPDWFKLQJPHVVDJHVWRILQGRXW
ZKDW¦VKDUDVVLQJ\RXU$FWRUV

196 | Chapter 9:—Robust, Scalable Concurrency with Actors

Download at WoweBook.Com
Actors in Depth
1RZWKDWZH¦YHJRWDEDVLFVHQVHRIZKDW$FWRUVDUHDQGKRZWKH\¦UHXVHGLQ6FDODOHW¦V
SXWWKHPWRZRUN6SHFLILFDOO\OHW¦VSXWWKHPWRZRUNFXWWLQJKDLU7KHVOHHSLQJEDUEHU
SUREOHP VHH >6OHHSLQJ%DUEHU3UREOHP@  LV RQH RI D SRSXODU VHW RI FRPSXWHU VFLHQFH
K\SRWKHWLFDOVGHVLJQHGWRGHPRQVWUDWHLVVXHVRIFRQFXUUHQF\DQGV\QFKURQL]DWLRQ
7KHSUREOHPLVWKLVDK\SRWKHWLFDOEDUEHUVKRSKDVMXVWRQHEDUEHUZLWKRQHEDUEHU
FKDLUDQGWKUHHFKDLUVLQZKLFKFXVWRPHUVPD\ZDLWIRUDKDLUFXW:LWKRXWFXVWRPHUV
DURXQGWKHEDUEHUVOHHSV:KHQDFXVWRPHUDUULYHVWKHEDUEHUZDNHVXSWRFXWKLV
KDLU,IWKHEDUEHULVEXV\FXWWLQJKDLUZKHQDFXVWRPHUDUULYHVWKHFXVWRPHUVLWVGRZQ
LQDQDYDLODEOHFKDLU,IDFKDLULVQ¦WDYDLODEOHWKHFXVWRPHUOHDYHV
7KHVOHHSLQJEDUEHUSUREOHPLVXVXDOO\VROYHGZLWKVHPDSKRUHVDQGPXWH[HVEXWZH¦YH
JRWEHWWHUWRROVDWRXUGLVSRVDO6WUDLJKWDZD\ZHVHHVHYHUDOWKLQJVWRPRGHODV$FWRUV
WKHEDUEHULVFOHDUO\RQHDVDUHWKHFXVWRPHUV7KHEDUEHUVKRSLWVHOIFRXOGEHPRGHOHG
DVDQ$FWRUWRRWKHUHQHHGQRWEHDUHDOZRUOGSDUDOOHOWRYHUEDOFRPPXQLFDWLRQLQDQ
$FWRUV\VWHPHYHQWKRXJKZH¦UHVHQGLQJPHVVDJHV
/HW¦V VWDUW ZLWK WKH VOHHSLQJ EDUEHU¦V FXVWRPHUV DV WKH\ KDYH WKH VLPSOHVW
UHVSRQVLELOLWLHV
// code-examples/Concurrency/sleepingbarber/customer.scala

package sleepingbarber

import scala.actors.Actor
import scala.actors.Actor._

case object Haircut

class Customer(val id: Int) extends Actor {


var shorn = false

def act() = {
loop {
react {
case Haircut => {
shorn = true
println("[c] customer " + id + " got a haircut")
}
}
}
}
}

)RUWKHPRVWSDUWWKLVVKRXOGORRNSUHWW\IDPLOLDUZHGHFODUHWKHSDFNDJHLQZKLFK
WKLVFRGHOLYHVZHLPSRUWFRGHIURPWKHscala.actorsSDFNDJHDQGZHGHILQHDFODVV
WKDWH[WHQGVActor7KHUHDUHDIHZGHWDLOVZRUWKQRWLQJKRZHYHU
)LUVWRIDOOWKHUH¦VRXUGHFODUDWLRQRI case object Haircut$FRPPRQSDWWHUQZKHQ
ZRUNLQJZLWK$FWRUVLQ6FDODLVWRXVHD case objectWRUHSUHVHQWDPHVVDJHZLWKRXW

Actors in Scala | 197

Download at WoweBook.Com
LQWHUQDOGDWD,IZHZDQWHGWRLQFOXGHVD\WKHWLPHDWZKLFKWKHKDLUFXWZDVFRPSOHWHG
ZH¦GXVHDcase classLQVWHDG:HGHFODUHHaircutKHUHEHFDXVHLW¦VDPHVVDJHW\SHWKDW
ZLOOEHVHQWVROHO\WRFXVWRPHUV
1RWHDVZHOOWKDWZH¦UHVWRULQJRQHELWRIPXWDEOHVWDWHLQHDFK CustomerZKHWKHURU
QRWWKH\¦YHJRWWHQDKDLUFXW,QWKHLULQWHUQDOORRSHDFK CustomerZDLWVIRUD Haircut
PHVVDJHDQGXSRQUHFHLSWRIRQHZHVHWWKHshornERROHDQWRtrueCustomerXVHVWKH
DV\QFKURQRXVreactPHWKRGWRUHVSRQGWRLQFRPLQJPHVVDJHV,IZHQHHGHGWRUHWXUQ
WKHUHVXOWRISURFHVVLQJWKHPHVVDJHZHZRXOGXVH receiveEXWZHGRQ¦WDQGLQWKH
SURFHVVZHVDYHVRPHPHPRU\DQGWKUHDGXVHXQGHUWKHKRRG
/HW¦VPRYHRQWRWKHEDUEHUKLPVHOI%HFDXVHWKHUH¦VRQO\RQHEDUEHUZHFRXOGKDYH
XVHGWKHactorIDFWRU\PHWKRGWHFKQLTXHPHQWLRQHGHDUOLHUWRFUHDWHKLP)RUWHVWLQJ
SXUSRVHVZH¦YHLQVWHDGGHILQHGRXURZQBarberFODVV
// code-examples/Concurrency/sleepingbarber/barber.scala

package sleepingbarber

import scala.actors.Actor
import scala.actors.Actor._
import scala.util.Random

class Barber extends Actor {


private val random = new Random()

def helpCustomer(customer: Customer) {


if (self.mailboxSize >= 3) {
println("[b] not enough seats, turning customer " + customer.id + " away")
} else {
println("[b] cutting hair of customer " + customer.id)
Thread.sleep(100 + random.nextInt(400))
customer ! Haircut
}
}

def act() {
loop {
react {
case customer: Customer => helpCustomer(customer)
}
}
}
}

7KH FRUH RI WKH Barber FODVV ORRNV YHU\ PXFK OLNH WKH Customer :H ORRS DURXQG
reactZDLWLQJIRUDSDUWLFXODUW\SHRIREMHFW7RNHHSWKDWORRSWLJKWDQGUHDGDEOHZH
FDOODPHWKRG helpCustomerZKHQDQHZ CustomerLVVHQWWRWKHEDUEHU:LWKLQWKDW
PHWKRGZHHPSOR\DFKHFNRQWKHPDLOER[VL]HWRVHUYHDVRXU£FKDLUV¤WKDWFXVWRPHUV
PD\RFFXS\ZHFRXOGKDYHWKHBarberRUShopFODVVHVPDLQWDLQDQLQWHUQDOQueueEXW
ZK\ERWKHUZKHQHDFK$FWRU¦VPDLOER[DOUHDG\LVRQH"

198 | Chapter 9:—Robust, Scalable Concurrency with Actors

Download at WoweBook.Com
,IWKUHHRUPRUHFXVWRPHUVDUHLQWKHTXHXHZHVLPSO\LJQRUHWKDWPHVVDJHLW¦VWKHQ
GLVFDUGHG IURP WKH EDUEHU¦V PDLOER[ 2WKHUZLVH ZH VLPXODWH D VHPLUDQGRP GHOD\
DOZD\VDWOHDVWPLOOLVHFRQGV IRUWKHWLPHLWWDNHVWRFXWDFXVWRPHU¦VKDLUWKHQ
VHQG RII D Haircut PHVVDJH WR WKDW FXVWRPHU :HUH ZH QRW WU\LQJ WR VLPXODWH D
UHDOZRUOGVFHQDULRZHZRXOGRIFRXUVHUHPRYHWKHFDOOWR Thread.sleep()DQGDOORZ
RXUEDUEHUWRUXQIXOOWLOW
1H[WXSZHKDYHDVLPSOHFODVVWRUHSUHVHQWWKHEDUEHUVKRSLWVHOI
// code-examples/Concurrency/sleepingbarber/shop.scala

package sleepingbarber

import scala.actors.Actor
import scala.actors.Actor._

class Shop extends Actor {


val barber = new Barber()
barber.start

def act() {
println("[s] the shop is open")

loop {
react {
case customer: Customer => barber ! customer
}
}
}
}

%\QRZWKLVVKRXOGDOOORRNYHU\IDPLOLDU(DFK ShopFUHDWHVDQGVWDUWVDQHZ Barber


SULQWVDPHVVDJHWHOOLQJWKHZRUOGWKDWWKHVKRSLVRSHQDQGVLWVLQDORRSZDLWLQJIRU
FXVWRPHUV:KHQDCustomerFRPHVLQKH¦VVHQWWRWKHEDUEHU:HQRZVHHDQXQH[
SHFWHGEHQHILWRI$FWRUVWKH\DOORZXVWRGHVFULEHFRQFXUUHQWEXVLQHVVORJLFLQHDVLO\
XQGHUVWRRGWHUPV£6HQGWKHFXVWRPHUWRWKHEDUEHU¤PDNHVSHUIHFWVHQVHPXFKPRUH
VRWKDQ£1RWLI\WKHEDUEHUXQORFNWKHPXWH[DURXQGWKHFXVWRPHUVHDWVLQFUHPHQW
WKHQXPEHURIIUHHVHDWV¤DQGVRIRUWK$FWRUVJHWXVFORVHUWRRXUGRPDLQ
)LQDOO\ZHKDYHDGULYHUIRURXUVLPXODWLRQ
// code-examples/Concurrency/sleepingbarber/barbershop-simulator.scala

package sleepingbarber

import scala.actors.Actor._
import scala.collection.{immutable, mutable}
import scala.util.Random

object BarbershopSimulator {
private val random = new Random()
private val customers = new mutable.ArrayBuffer[Customer]()
private val shop = new Shop()

Actors in Scala | 199

Download at WoweBook.Com
def generateCustomers {
for (i <- 1 to 20) {
val customer = new Customer(i)
customer.start()
customers += customer
}

println("[!] generated " + customers.size + " customers")


}

// customers arrive at random intervals


def trickleCustomers {
for (customer <- customers) {
shop ! customer
Thread.sleep(random.nextInt(450))
}
}

def tallyCuts {
// wait for any remaining concurrent actions to complete
Thread.sleep(2000)

val shornCount = customers.filter(c => c.shorn).size


println("[!] " + shornCount + " customers got haircuts today")
}

def main(args: Array[String]) {


println("[!] starting barbershop simulation")
shop.start()

generateCustomers
trickleCustomers
tallyCuts

System.exit(0)
}
}

$IWHU£RSHQLQJWKHVKRS¤ZHJHQHUDWHDQXPEHURI CustomerREMHFWVDVVLJQLQJDQX
PHULF,'WRHDFKDQGVWRULQJWKHORWLQDQArrayBuffer1H[WZH£WULFNOH¤WKHFXVWRPHUV
LQE\VHQGLQJWKHPDVPHVVDJHVWRWKHVKRSDQGVOHHSLQJIRUDVHPLUDQGRPDPRXQWRI
WLPHEHWZHHQORRSV$WWKHHQGRIRXUVLPXODWHGGD\ZHWDOO\XSWKHQXPEHURIFXV
WRPHUVZKRJRWKDLUFXWVE\ILOWHULQJRXWWKHFXVWRPHUVZKRVHLQWHUQDO shornERROHDQ
ZDVVHWWRtrueDQGDVNLQJIRUWKHVL]HRIWKHUHVXOWLQJVHTXHQFH
&RPSLOHDQGUXQWKHFRGHZLWKLQWKHsleepingbarberGLUHFWRU\DVIROORZV
fsc *.scala
scala -classpath . sleepingbarber.BarbershopSimulator

7KURXJKRXW RXU FRGH ZH¦YH SUHIL[HG FRQVROH PHVVDJHV ZLWK DEEUHYLDWLRQV IRU WKH
FODVVHVIURPZKLFKWKHPHVVDJHVZHUHSULQWHG:KHQZHORRNDWDQH[DPSOHUXQRIRXU
VLPXODWRULW¦VHDV\WRVHHZKHUHHDFKPHVVDJHFDPHIURP

200 | Chapter 9:—Robust, Scalable Concurrency with Actors

Download at WoweBook.Com
[!] starting barbershop simulation
[s] the shop is open
[!] generated 20 customers
[b] cutting hair of customer 1
[b] cutting hair of customer 2
[c] customer 1 got a haircut
[c] customer 2 got a haircut
[b] cutting hair of customer 3
[c] customer 3 got a haircut
[b] cutting hair of customer 4
[b] cutting hair of customer 5
[c] customer 4 got a haircut
[b] cutting hair of customer 6
[c] customer 5 got a haircut
[b] cutting hair of customer 7
[c] customer 6 got a haircut
[b] not enough seats, turning customer 8 away
[b] cutting hair of customer 9
[c] customer 7 got a haircut
[b] not enough seats, turning customer 10 away
[c] customer 9 got a haircut
[b] cutting hair of customer 11
[b] cutting hair of customer 12
[c] customer 11 got a haircut
[b] cutting hair of customer 13
[c] customer 12 got a haircut
[b] cutting hair of customer 14
[c] customer 13 got a haircut
[b] not enough seats, turning customer 15 away
[b] not enough seats, turning customer 16 away
[b] not enough seats, turning customer 17 away
[b] cutting hair of customer 18
[c] customer 14 got a haircut
[b] cutting hair of customer 19
[c] customer 18 got a haircut
[b] cutting hair of customer 20
[c] customer 19 got a haircut
[c] customer 20 got a haircut
[!] 15 customers got haircuts today

<RX¦OOILQGWKDWHDFKUXQ¦VRXWSXWLVSUHGLFWDEO\VOLJKWO\GLIIHUHQW(YHU\WLPHWKHEDU
EHUWDNHVDELWORQJHUWRFXWKDLUWKDQLWGRHVIRUVHYHUDOFXVWRPHUVWRHQWHUWKH£FKDLUV¤
WKHEDUEHU¦VPDLOER[TXHXH ILOOXSDQGQHZFXVWRPHUVVLPSO\OHDYH
2IFRXUVHZHKDYHWRLQFOXGHWKHVWDQGDUGFDYHDWVWKDWFRPHZLWKVLPSOHH[DPSOHV
)RU RQH LW¦V SRVVLEOH WKDW RXU H[DPSOH PD\ QRW EH VXLWDEO\ UDQGRP SDUWLFXODUO\ LI
UDQGRPYDOXHVDUHUHWULHYHGZLWKLQDPLOOLVHFRQGRIRQHDQRWKHU7KLVLVDE\SURGXFW
RIWKHZD\WKH-90JHQHUDWHVUDQGRPQXPEHUVDQGDJRRGUHPLQGHUWREHFDUHIXO
DERXWUDQGRPQHVVLQFRQFXUUHQWSURJUDPV<RX¦GDOVRZDQWWRUHSODFHWKHsleepLQVLGH
tallyCutsZLWKDFOHDUHUVLJQDOWKDWWKHYDULRXVDFWRUVLQWKHV\VWHPDUHGRQHGRLQJWKHLU
ZRUNSHUKDSVE\PDNLQJWKHBarbershopSimulationDQ$FWRUDQGVHQGLQJLWPHVVDJHV
WKDWLQGLFDWHFRPSOHWLRQ

Actors in Scala | 201

Download at WoweBook.Com
7U\ PRGLI\LQJ WKH FRGH WR LQWURGXFH PRUH FXVWRPHUV DGGLWLRQDO PHVVDJH W\SHV
GLIIHUHQW GHOD\V RU WR UHPRYH WKH UDQGRPQHVV DOWRJHWKHU ,I \RX¦UH DQ H[SHULHQFHG
PXOWLWKUHDGHGSURJUDPPHU\RXPLJKWWU\ZULWLQJ\RXURZQVOHHSLQJEDUEHULPSOH
PHQWDWLRQMXVWWRFRPSDUHDQGFRQWUDVW:H¦UHZLOOLQJWREHWWKDWDQLPSOHPHQWDWLRQ
LQ6FDODZLWK$FWRUVZLOOEHWHUVHUDQGHDVLHUWRPDLQWDLQ

Effective Actors
7RJHWWKHPRVWRXWRI$FWRUVWKHUHDUHIHZWKLQJVWRUHPHPEHU)LUVWQRWHWKDWWKHUH
DUHVHYHUDOPHWKRGV\RXFDQXVHWRJHWGLIIHUHQWW\SHVRIEHKDYLRURXWRI\RXU$FWRUV
7DEOHVKRXOGKHOSFODULI\ZKHQWRXVHHDFKPHWKRG
7DEOH$FWRUPHWKRGV
Method Returns Description
act Unit Abstract, top-level method for an Actor. Typically contains one of the
following methods inside it.
receive Result of processing Blocks until a message of matched type is received.
message
receiveWithin Result of processing Like receive, but unblocks after specified number of milliseconds.
message
react Nothing Requires less overhead (threads) than receive.
reactWithin Nothing Like react, but unblocks after specified number of milliseconds.

7\SLFDOO\\RX¦OOZDQWWRXVH reactZKHUHYHUSRVVLEOH,I\RXQHHGWKHUHVXOWVRISUR
FHVVLQJDPHVVDJH WKDWLV\RXQHHGDV\QFKURQRXVUHVSRQVHIURPVHQGLQJDPHVVDJH
WRDQ$FWRU XVHWKHreceiveWithinYDULDQWWRUHGXFH\RXUFKDQFHVRIEORFNLQJLQGHIL
QLWHO\RQDQ$FWRUWKDW¦VJRWWHQZHGJHG
$QRWKHUVWUDWHJ\WRNHHS\RXU$FWRUEDVHGFRGHDV\QFKURQRXVLVWKHXVHRIIXWXUHV$
IXWXUHLVDSODFHKROGHUREMHFWIRUDYDOXHWKDWKDVQ¦W\HWEHHQUHWXUQHGIURPDQDV\Q
FKURQRXVSURFHVV<RXFDQVHQGDPHVVDJHWRDQ$FWRUZLWKWKH!!PHWKRGDYDULDQW
RIWKLVPHWKRGDOORZV\RXWRSDVVDORQJDSDUWLDOIXQFWLRQWKDWLVDSSOLHGWRWKHIXWXUH
YDOXH$V\RXFDQVHHIURPWKHIROORZLQJH[DPSOHUHWULHYLQJDYDOXHIURPD FutureLV
DVVWUDLJKWIRUZDUGDVLQYRNLQJLWV applyPHWKRG1RWHWKDWUHWULHYLQJDYDOXHIURPD
FutureLVDEORFNLQJRSHUDWLRQ
// code-examples/Concurrency/future-script.scala
import scala.actors.Futures._

val eventually = future(5 * 42)


println(eventually())

(DFK $FWRU LQ \RXU V\VWHP VKRXOG KDYH FOHDU UHVSRQVLELOLWLHV 'RQ¦W XVH $FWRUV IRU
JHQHUDOSXUSRVH KLJKO\ VWDWHIXO WDVNV ,QVWHDG WKLQN OLNH D GLUHFWRU ZKDW DUH WKH
GLVWLQFW UROHV LQ WKH £VFULSW¤ RI \RXU DSSOLFDWLRQ DQG ZKDW¦V WKH OHDVW DPRXQW RI

202 | Chapter 9:—Robust, Scalable Concurrency with Actors

Download at WoweBook.Com
LQIRUPDWLRQHDFK$FWRUQHHGVWRGRLWVMRE"*LYHHDFK$FWRUMXVWDFRXSOHRIUHVSRQVL
ELOLWLHVDQGXVHPHVVDJHV XVXDOO\LQWKHIRUPRIDcase classRUcase object WRGHOHJDWH
WKRVHUHVSRQVLELOLWLHVWRRWKHU$FWRUV
'RQ¦WEHKHVLWDQWWRFRS\GDWDZKHQZULWLQJ$FWRUFHQWULFFRGH7KHPRUHLPPXWDEOH
\RXUGHVLJQWKHOHVVOLNHO\\RXDUHWRHQGXSZLWKXQH[SHFWHGVWDWH7KHPRUH\RX
FRPPXQLFDWHYLDPHVVDJHVWKHOHVV\RXKDYHWRZRUU\DERXWV\QFKURQL]DWLRQ$OOWKRVH
PHVVDJHVDQGLPPXWDEOHYDULDEOHVPLJKWDSSHDUWREHRYHUO\FRVWO\%XWZLWKWRGD\¦V
SOHQWLIXOKDUGZDUHWUDGLQJPHPRU\RYHUKHDGIRUFODULW\DQGSUHGLFWDELOLW\VHHPVPRUH
WKDQIDLUIRUPRVWDSSOLFDWLRQV
/DVWO\NQRZZKHQ$FWRUVDUHQ¦WDSSURSULDWH-XVWEHFDXVH$FWRUVDUHDJUHDWZD\WR
KDQGOHFRQFXUUHQF\LQ6FDODGRHVQ¦WPHDQWKDWWKH\¦UHWKHRQO\ZD\DVZH¦OOVHHVRRQ
7UDGLWLRQDOWKUHDGLQJDQGORFNLQJPD\EHWWHUVXLWZULWHKHDY\FULWLFDOSDWKVIRUZKLFK
DPHVVDJLQJDSSURDFKZRXOGLQFXUWRRPXFKRYHUKHDG,QRXUH[SHULHQFH\RXFDQXVH
DSXUHO\$FWRUEDVHGGHVLJQWRSURWRW\SHDFRQFXUUHQWVROXWLRQWKHQXVHSURILOLQJWRROV
WRVXVVRXWSDUWVRI\RXUDSSOLFDWLRQWKDWPLJKWEHQHILWIURPDGLIIHUHQWDSSURDFK

Traditional Concurrency in Scala: Threading and Events


:KLOH$FWRUVDUHDJUHDWZD\WRKDQGOHFRQFXUUHQWRSHUDWLRQVWKH\¦UHQRWWKHRQO\ZD\
WRGRVRLQ6FDOD$V6FDODLVLQWHURSHUDEOHZLWK-DYDWKHFRQFXUUHQF\FRQFHSWVWKDW
\RXPD\EHIDPLOLDUZLWKRQWKH-90VWLOODSSO\

One-Off Threads
)RUVWDUWHUV6FDODSURYLGHVDKDQG\ZD\WRUXQDEORFNRIFRGHLQDQHZWKUHDG
// code-examples/Concurrency/threads/by-block-script.scala

new Thread { println("this will run in a new thread") }

$VLPLODUFRQVWUXFWLVDYDLODEOHLQWKH scala.concurrentSDFNDJHDVDPHWKRGRQWKH
opsREMHFWWRUXQDEORFNDV\QFKURQRXVO\ZLWKspawn
// code-examples/Concurrency/threads/spawn.scala

import scala.concurrent.ops._

object SpawnExample {
def main(args: Array[String]) {
println("this will run synchronously")

spawn {
println("this will run asychronously")
}
}
}

Traditional Concurrency in Scala: Threading and Events | 203

Download at WoweBook.Com
Using java.util.concurrent
,I\RX¦UHIDPLOLDUZLWKWKHYHQHUDEOHjava.util.concurrentSDFNDJH\RX¦OOILQGLWMXVW
DVHDV\WRXVHIURP6FDOD RUKDUGWRXVHGHSHQGLQJRQ\RXUSRLQWRIYLHZ /HW¦VXVH
ExecutorsWRFUHDWHDSRRORIWKUHDGV:H¦OOXVHWKHWKUHDGSRROWRUXQDVLPSOHFODVV
LPSOHPHQWLQJ-DYD¦VRunnableLQWHUIDFHIRUWKUHDGIULHQGO\FODVVHVWKDWLGHQWLILHVZKLFK
WKUHDGLW¦VUXQQLQJRQ
// code-examples/Concurrency/threads/util-concurrent-script.scala

import java.util.concurrent._

class ThreadIdentifier extends Runnable {


def run {
println("hello from Thread " + currentThread.getId)
}
}

val pool = Executors.newFixedThreadPool(5)

for (i <- 1 to 10) {


pool.execute(new ThreadIdentifier)
}

$VLVVWDQGDUGLQ-DYDFRQFXUUHQF\WKH runPHWKRGLVZKHUHDWKUHDGHGFODVVVWDUWV
(YHU\WLPHRXUpoolH[HFXWHVDQHZThreadIdentifierLWVrunPHWKRGLVLQYRNHG$ORRN
DWWKHRXWSXWWHOOVXVWKDWZH¦UHUXQQLQJRQWKHILYHWKUHDGVLQWKHSRROZLWK,'VUDQJLQJ
IURPWR
hello from Thread 9
hello from Thread 10
hello from Thread 11
hello from Thread 12
hello from Thread 13
hello from Thread 9
hello from Thread 11
hello from Thread 10
hello from Thread 10
hello from Thread 13

7KLV LV RI FRXUVH MXVW VFUDWFKLQJ WKH VXUIDFH RI ZKDW LV DYDLODEOH LQ
java.util.concurrent<RX¦OOILQGWKDW\RXUH[LVWLQJNQRZOHGJHRI-DYD¦VDSSURDFKWR
PXOWLWKUHDGLQJVWLOODSSOLHVLQ6FDOD:KDW¦VPRUH\RX¦OOEHDEOHWRDFFRPSOLVKWKHVDPH
WDVNVXVLQJOHVVFRGHZKLFKVKRXOGFRQWULEXWHWRPDLQWDLQDELOLW\DQGSURGXFWLYLW\

Events
7KUHDGLQJDQG$FWRUVDUHQ¦WWKHRQO\ZD\WRGRFRQFXUUHQF\(YHQWEDVHGFRQFXUUHQF\
DSDUWLFXODUDSSURDFKWRDV\QFKURQRXVRUQRQEORFNLQJ,2 1,2 KDVEHFRPHDID
YRUHG ZD\ WR ZULWH VHUYHUV WKDW QHHG WR VFDOH WR WKRXVDQGV RI VLPXOWDQHRXV FOLHQWV
(VFKHZLQJWKHWUDGLWLRQDORQHWRRQHUHODWLRQVKLSRIWKUHDGVWRFOLHQWVWKLVPRGHORI

204 | Chapter 9:—Robust, Scalable Concurrency with Actors

Download at WoweBook.Com
FRQFXUUHQF\ H[SRVHV HYHQWV WKDW RFFXU ZKHQ SDUWLFXODU FRQGLWLRQV DUH PHW IRU
H[DPSOHZKHQGDWDLVUHFHLYHGIURPDFOLHQWRYHUDQHWZRUNVRFNHW 7\SLFDOO\WKH
SURJUDPPHUZLOODVVRFLDWHDFDOOEDFNPHWKRGZLWKHDFKHYHQWWKDW¦VUHOHYDQWWRKHU
SURJUDP
:KLOHWKH java.nioSDFNDJHSURYLGHVDYDULHW\RIXVHIXOSULPLWLYHVIRUQRQEORFNLQJ
,2 EXIIHUVFKDQQHOVHWF LW¦VVWLOODIDLUELWRIZRUNWRFREEOHWRJHWKHUDQHYHQWEDVHG
FRQFXUUHQWSURJUDPIURPWKRVHVLPSOHSDUWV(QWHU$SDFKH0,1$EXLOWDWRS-DYD1,2
DQGGHVFULEHGRQLWVKRPHSDJHDV£DQHWZRUNDSSOLFDWLRQIUDPHZRUNZKLFKKHOSVXVHUV
GHYHORS KLJK SHUIRUPDQFH DQG KLJK VFDODELOLW\ QHWZRUN DSSOLFDWLRQV HDVLO\¤ VHH
>0,1$@ 
:KLOH0,1$PD\EHHDVLHUWRXVHWKDQ-DYD¦VEXLOWLQ1,2OLEUDULHVZH¦YHJRWWHQXVHG
WRVRPHFRQYHQLHQFHVRI6FDODWKDWMXVWDUHQ¦WDYDLODEOHLQ0,1$7KHRSHQVRXUFH
1DJJDWLOLEUDU\ VHH>1DJJDWL@ DGGVD6FDODIULHQGO\OD\HUDWRS0,1$WKDWDFFRUGLQJ
WRLWVDXWKRU£PDNHVLWHDV\WREXLOGSURWRFROILOWHUV>XVLQJD@VHTXHQWLDOVW\OH¤(VVHQ
WLDOO\1DJJDWLLVD'6/IRUSDUVLQJQHWZRUNSURWRFROVZLWK0,1$¦VSRZHUIXO1,2
DELOLWLHVXQGHUWKHKRRG
/HW¦VXVH1DJJDWLWRZULWHWKHIRXQGDWLRQVRIDQ6073HPDLOVHUYHU7RNHHSWKLQJV
VLPSOH ZH¦UH RQO\ GHDOLQJ ZLWK WZR 6073 FRPPDQGV HELO DQG QUIT 7KH IRUPHU
FRPPDQGLGHQWLILHVDFOLHQWDQGWKHODWWHUHQGVWKHFOLHQW¦VVHVVLRQ
:H¦OONHHSRXUVHOYHVKRQHVWZLWKDWHVWVXLWHIDFLOLWDWHGE\WKH6SHFV%HKDYLRU'ULYHQ
'HYHORSPHQWOLEUDU\ VHH£6SHFV¤RQSDJH 
// .../smtpd/src/test/scala/com/programmingscala/smtpd/SmtpDecoderSpec.scala

package com.programmingscala.smtpd

import java.nio.ByteOrder
import net.lag.naggati._
import org.apache.mina.core.buffer.IoBuffer
import org.apache.mina.core.filterchain.IoFilter
import org.apache.mina.core.session.{DummySession, IoSession}
import org.apache.mina.filter.codec._
import org.specs._
import scala.collection.{immutable, mutable}

object SmtpDecoderSpec extends Specification {


private var fakeSession: IoSession = null
private var fakeDecoderOutput: ProtocolDecoderOutput = null
private var written = new mutable.ListBuffer[Request]

def quickDecode(s: String): Unit = {


Codec.decoder.decode(fakeSession, IoBuffer.wrap(s.getBytes), fakeDecoderOutput)
}

"SmtpRequestDecoder" should {
doBefore {
written.clear()
fakeSession = new DummySession

Traditional Concurrency in Scala: Threading and Events | 205

Download at WoweBook.Com
fakeDecoderOutput = new ProtocolDecoderOutput {
override def flush(nextFilter: IoFilter.NextFilter, s: IoSession) = {}
override def write(obj: AnyRef) = written += obj.asInstanceOf[Request]
}
}

"parse HELO" in {
quickDecode("HELO client.example.org\n")
written.size mustEqual 1
written(0).command mustEqual "HELO"
written(0).data mustEqual "client.example.org"
}

"parse QUIT" in {
quickDecode("QUIT\n")
written.size mustEqual 1
written(0).command mustEqual "QUIT"
written(0).data mustEqual null
}
}
}

$IWHUVHWWLQJXSDQHQYLURQPHQWIRUHDFKWHVWUXQRXUVXLWHH[HUFLVHVWKHWZR6073
FRPPDQGVZH¦UHLQWHUHVWHGLQ7KHdoBeforeEORFNUXQVEHIRUHHDFKWHVWJXDUDQWHHLQJ
WKDWPRFNVHVVLRQDQGRXWSXWEXIIHUVDUHLQDFOHDQVWDWH,QHDFKWHVWZH¦UHSDVVLQJD
VWULQJRIK\SRWKHWLFDOFOLHQWLQSXWWRRXUDV\HWXQLPSOHPHQWHG CodecWKHQYHULI\LQJ
WKDWWKHUHVXOWLQJRequest Dcase class FRQWDLQVWKHFRUUHFWcommandDQGdataILHOGV
$VWKHQUITFRPPDQGGRHVQ¦WUHTXLUHDQ\DGGLWLRQDOLQIRUPDWLRQIURPWKHFOLHQWZH
VLPSO\FKHFNWKDWdataLVnull
:LWKRXUWHVWVLQSODFHOHW¦VLPSOHPHQWDEDVLFFRGHF DQHQFRGHUDQGGHFRGHU IRU
6073
// .../smtpd/src/main/scala/com/programmingscala/smtpd/Codec.scala

package com.programmingscala.smtpd

import org.apache.mina.core.buffer.IoBuffer
import org.apache.mina.core.session.{IdleStatus, IoSession}
import org.apache.mina.filter.codec._
import net.lag.naggati._
import net.lag.naggati.Steps._

case class Request(command: String, data: String)


case class Response(data: IoBuffer)

object Codec {
val encoder = new ProtocolEncoder {
def encode(session: IoSession, message: AnyRef, out: ProtocolEncoderOutput) = {
val buffer = message.asInstanceOf[Response].data
out.write(buffer)
}

def dispose(session: IoSession): Unit = {

206 | Chapter 9:—Robust, Scalable Concurrency with Actors

Download at WoweBook.Com
// no-op, required by ProtocolEncoder trait
}
}

val decoder = new Decoder(readLine(true, "ISO-8859-1") { line =>


line.split(' ').first match {
case "HELO" => state.out.write(Request("HELO", line.split(' ')(1))); End
case "QUIT" => state.out.write(Request("QUIT", null)); End
case _ => throw new ProtocolError("Malformed request line: " + line)
}
})
}

:HILUVWGHILQHDRequestcase classLQZKLFKWRVWRUHUHTXHVWGDWDDVLWDUULYHV7KHQ
ZHVSHFLI\WKHencoderSRUWLRQRIRXUFRGHFZKLFKH[LVWVVLPSO\WRZULWHGDWDRXW$
dispose PHWKRG LV GHILQHG EXW QRW IOHVKHG RXW  WR IXOILOO WKH FRQWUDFW RI WKH
ProtocolEncoderWUDLW
7KHGHFRGHULVZKDWZH¦UHUHDOO\LQWHUHVWHGLQreadRequestUHDGVDOLQHSLFNVRXWWKH
ILUVWZRUGLQWKDWOLQHDQGSDWWHUQPDWFKHVRQLWWRILQG6073FRPPDQGV,QWKHFDVH
RID HELOFRPPDQGZHDOVRJUDEWKHVXEVHTXHQWVWULQJRQWKDWOLQH7KHUHVXOWVDUH
SODFHGLQDRequestREMHFWDQGZULWWHQRXWWRstate$V\RXPLJKWLPDJLQHstateVWRUHV
RXUSURJUHVVWKURXJKRXWWKHSDUVLQJSURFHVV
7KRXJKWULYLDOWKHDERYHH[DPSOHGHPRQVWUDWHVMXVWKRZHDV\LWLVWRSDUVHSURWRFROV
ZLWK1DJJDWL1RZWKDWZH¦YHJRWDZRUNLQJFRGHFOHW¦VFRPELQH1DJJDWLDQG0,1$
ZLWK$FWRUVWRZLUHXSDVHUYHU
)LUVWDIHZOLQHVRIVHWXSJUXQWZRUNWRJHWWKLQJVJRLQJIRURXU6073VHUYHU
// .../smtpd/src/main/scala/com/programmingscala/smtpd/Main.scala

package com.programmingscala.smtpd

import net.lag.naggati.IoHandlerActorAdapter
import org.apache.mina.filter.codec.ProtocolCodecFilter
import org.apache.mina.transport.socket.SocketAcceptor
import org.apache.mina.transport.socket.nio.{NioProcessor, NioSocketAcceptor}
import java.net.InetSocketAddress
import java.util.concurrent.{Executors, ExecutorService}
import scala.actors.Actor._

object Main {
val listenAddress = "0.0.0.0"
val listenPort = 2525

def setMaxThreads = {
val maxThreads = (Runtime.getRuntime.availableProcessors * 2)
System.setProperty("actors.maxPoolSize", maxThreads.toString)
}

def initializeAcceptor = {
var acceptorExecutor = Executors.newCachedThreadPool()
var acceptor =

Traditional Concurrency in Scala: Threading and Events | 207

Download at WoweBook.Com
new NioSocketAcceptor(acceptorExecutor, new NioProcessor(acceptorExecutor))
acceptor.setBacklog(1000)
acceptor.setReuseAddress(true)
acceptor.getSessionConfig.setTcpNoDelay(true)
acceptor.getFilterChain.addLast("codec",
new ProtocolCodecFilter(smtpd.Codec.encoder, smtpd.Codec.decoder))
acceptor.setHandler(
new IoHandlerActorAdapter(session => new SmtpHandler(session)))
acceptor.bind(new InetSocketAddress(listenAddress, listenPort))
}

def main(args: Array[String]) {


setMaxThreads
initializeAcceptor
println("smtpd: up and listening on " + listenAddress + ":" + listenPort)
}
}

7RHQVXUHWKDWZH¦UHJHWWLQJWKHPRVWRXWRIWKH$FWRULQVWDQFHVLQRXUVHUYHUZHVHW
WKH actors.maxPoolSizeV\VWHPSURSHUW\WRWZLFHWKHQXPEHURIDYDLODEOHSURFHVVRUV
RQRXUPDFKLQH:HWKHQLQLWLDOL]HDQ NioSocketAcceptorDNH\SLHFHRI0,1$PD
FKLQHU\WKDWDFFHSWVQHZFRQQHFWLRQVIURPFOLHQWV7KHILQDOWKUHHOLQHVRIWKLVFRQILJ
XUDWLRQDUHFULWLFDODVWKH\SXWRXUFRGHFWRZRUNWHOOWKHDFFHSWRUWRKDQGOHUHTXHVWV
ZLWKDVSHFLDOREMHFWDQGVWDUWWKHVHUYHUOLVWHQLQJIRUQHZFRQQHFWLRQVRQSRUW
UHDO6073VHUYHUVUXQRQWKHSULYLOHJHGSRUW 
7KHDIRUHPHQWLRQHGVSHFLDOREMHFWLVDQ$FWRUZUDSSHGLQDQIoHandlerActorAdapter
DEULGJLQJOD\HUEHWZHHQ6FDOD$FWRUVDQG0,1$WKDW¦VSURYLGHGE\1DJJDWL7KLVLV
WKHSLHFHRIRXUVHUYHUWKDWWDONVEDFNWRWKHFOLHQW1RZWKDWZHNQRZZKDWWKHFOLHQW
LVVD\LQJWKDQNVWRWKHGHFRGHUZHDFWXDOO\NQRZZKDWWRVD\EDFN
// .../smtpd/src/main/scala/com/programmingscala/smtpd/SmtpHandler.scala

package com.programmingscala.smtpd

import net.lag.naggati.{IoHandlerActorAdapter, MinaMessage, ProtocolError}


import org.apache.mina.core.buffer.IoBuffer
import org.apache.mina.core.session.{IdleStatus, IoSession}
import java.io.IOException
import scala.actors.Actor
import scala.actors.Actor._
import scala.collection.{immutable, mutable}

class SmtpHandler(val session: IoSession) extends Actor {


start

def act = {
loop {
react {
case MinaMessage.MessageReceived(msg) =>
handle(msg.asInstanceOf[smtpd.Request])
case MinaMessage.SessionClosed => exit()
case MinaMessage.SessionIdle(status) => session.close
case MinaMessage.SessionOpened => reply("220 localhost Tapir SMTPd 0.1\n")

208 | Chapter 9:—Robust, Scalable Concurrency with Actors

Download at WoweBook.Com
case MinaMessage.ExceptionCaught(cause) => {
cause.getCause match {
case e: ProtocolError => reply("502 Error: " + e.getMessage + "\n")
case i: IOException => reply("502 Error: " + i.getMessage + "\n")
case _ => reply("502 Error unknown\n")
}
session.close
}
}
}
}

private def handle(request: smtpd.Request) = {


request.command match {
case "HELO" => reply("250 Hi there " + request.data + "\n")
case "QUIT" => reply("221 Peace out girl scout\n"); session.close
}
}

private def reply(s: String) = {


session.write(new smtpd.Response(IoBuffer.wrap(s.getBytes)))
}

6WUDLJKWDZD\ZHVHHWKHVDPHSDWWHUQWKDWZHVDZLQWKH$FWRUVH[DPSOHVHDUOLHULQ
WKLVFKDSWHUORRSLQJDURXQGD reactEORFNWKDWSDWWHUQPDWFKHVRQDOLPLWHGVHWRI
FDVHV,Q SmtpHandlerDOORIWKRVHFDVHVDUHHYHQWVSURYLGHGE\0,1$)RUH[DPSOH
0,1$ ZLOO VHQG XV MinaMessage.SessionOpened ZKHQ D FOLHQW FRQQHFWV DQG
MinaMessage.SessionClosedZKHQDFOLHQWGLVFRQQHFWV
7KH FDVH ZH¦UH PRVW LQWHUHVWHG LQ LV MinaMessage.MessageReceived :H¦UH KDQGHG D
IDPLOLDU RequestREMHFWZLWKHDFKQHZO\UHFHLYHGYDOLGPHVVDJHDQGZHFDQSDWWHUQ
PDWFKRQWKH commandILHOGWRWDNHDSSURSULDWHDFWLRQ:KHQWKHFOLHQWVD\V HELOZH
FDQUHSO\ZLWKDQDFNQRZOHGJHPHQW:KHQWKHFOLHQWVD\VQUITZHVD\JRRGE\HDQG
GLVFRQQHFWKLP
1RZWKDWZH¦YHJRWDOOWKHSLHFHVLQSODFHOHW¦VKDYHDFRQYHUVDWLRQZLWKRXUVHUYHU
[al3x@jaya ~]$ telnet localhost 2525
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 localhost Tapir SMTPd 0.1
HELO jaya.local
250 Hi there jaya.local
QUIT
221 Peace out girl scout
Connection closed by foreign host.

Traditional Concurrency in Scala: Threading and Events | 209

Download at WoweBook.Com
$EULHIFRQYHUVDWLRQWREHVXUHEXWRXUVHUYHUZRUNV1RZZKDWKDSSHQVLIZHWKURZ
VRPHWKLQJXQH[SHFWHGDWLW"
[al3x@jaya ~]$ telnet localhost 2525
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 localhost Tapir SMTPd 0.1
HELO jaya.local
250 Hi there jaya.local
BAD COMMAND
502 Error: Malformed request line: BAD COMMAND
Connection closed by foreign host.

1LFHO\KDQGOHG*RRGWKLQJZHWRRNWKHWLPHWRGLJRXWWKRVHH[FHSWLRQVZKHQZH
UHFHLYHGDMinaMessage.ExceptionCaughtLQRXUSmtpHandler$FWRU
2IFRXUVHZKDWZH¦YHEXLOWMXVWKDQGOHVWKHEHJLQQLQJDQGHQGRIDFRPSOHWH6073
FRQYHUVDWLRQ$VDQH[HUFLVHWU\ILOOLQJRXWWKHUHVWRIWKHFRPPDQGV2UWRVNLSDKHDG
WR VRPHWKLQJ YHU\ PXFK DNLQ WR ZKDW ZH¦YH EXLOW KHUH FKHFN RXW WKH RSHQ VRXUFH
0DLOVORWSURMHFWRQ*LW+XE VHH>0DLOVORW@ 

Recap and What’s Next


:HOHDUQHGKRZWREXLOGVFDODEOHUREXVWFRQFXUUHQWDSSOLFDWLRQVXVLQJ6FDOD¦V$FWRU
OLEUDU\WKDWDYRLGWKHSUREOHPVRIWUDGLWLRQDODSSURDFKHVEDVHGRQV\QFKURQL]HGDFFHVV
WRVKDUHGPXWDEOHVWDWH:HDOVRGHPRQVWUDWHGWKDW-DYD¦VSRZHUIXOEXLOWLQWKUHDGLQJ
PRGHOLVHDVLO\DFFHVVLEOHIURP6FDOD)LQDOO\ZHOHDUQHGKRZWRFRPELQH$FWRUVZLWK
WKHSRZHUIXO0,1$1,2IUDPHZRUNDQG1DJJDWLWRGHYHORSHYHQWGULYHQDV\QFKUR
QRXVQHWZRUNVHUYHUVIURPWKHJURXQGXSLQMXVWDIHZOLQHVRIFRGH
7KHQH[WFKDSWHUH[DPLQHV6FDOD¦VEXLOWLQVXSSRUWIRUZRUNLQJZLWK;0/

210 | Chapter 9:—Robust, Scalable Concurrency with Actors

Download at WoweBook.Com
CHAPTER 10
Herding XML in Scala

;0/KDVORQJVLQFHEHFRPHWKHOLQJXDIUDQFDRIPDFKLQHWRPDFKLQHFRPPXQLFDWLRQ
RQWKH,QWHUQHW7KHIRUPDW¦VFRPELQDWLRQRIKXPDQUHDGDELOLW\VWDQGDUGL]DWLRQDQG
WRROVXSSRUWKDVPDGHZRUNLQJZLWK;0/DQLQHYLWDELOLW\IRUSURJUDPPHUV<HWZULW
LQJFRGHWKDWGHDOVLQ;0/LVDQXQSOHDVDQWFKRUHLQPRVWSURJUDPPLQJODQJXDJHV
6FDODLPSURYHVWKLVVLWXDWLRQ
$VZLWKWKH$FWRUIXQFWLRQDOLW\ZHOHDUQHGDERXWLQ&KDSWHU6FDOD¦V;0/VXSSRUWLV
LPSOHPHQWHGSDUWO\DVDOLEUDU\ZLWKVRPHEXLOWLQV\QWD[VXSSRUW,WIHHOVWRWKHSUR
JUDPPHU OLNH DQ HQWLUHO\ QDWXUDO SDUW RI WKH ODQJXDJH &RQYHQLHQW RSHUDWRUV DGG D
VSRRQIXORIV\QWDFWLFVXJDUWRWKHWDVNRIGLYLQJGHHSLQWRFRPSOH[GRFXPHQWVWUXF
WXUHV DQG SDWWHUQ PDWFKLQJ IXUWKHU VZHHWHQV WKH GHDO 2XWSXWWLQJ ;0/ LV MXVW DV
SOHDVDQW
8QXVXDOLQSURJUDPPLQJODQJXDJHVDQGSDUWLFXODUO\KDQG\6FDODDOORZVLQOLQH;0/
0RVWDQ\ZKHUH\RXPLJKWSXWDVWULQJ\RXFDQSXW;0/7KLVIHDWXUHPDNHVWHP
SODWLQJDQGFRQILJXUDWLRQDEUHH]HDQGOHWVXVWHVWRXUXVHRI;0/ZLWKRXWVRPXFK
DVRSHQLQJDILOH
/HW¦VH[SORUHZRUNLQJZLWK;0/LQ6FDOD)LUVWZH¦OOORRNDWUHDGLQJDQGQDYLJDWLQJDQ
;0/ GRFXPHQW )LQDOO\ ZH¦OO SURGXFH ;0/ RXWSXW SURJUDPPDWLFDOO\ DQG GHPRQ
VWUDWHXVHVIRULQOLQH;0/

Reading XML
:H¦OOVWDUWZLWKWKHEDVLFVKRZWRWXUQDVWULQJIXOORI;0/LQWRDGDWDVWUXFWXUHZH
FDQZRUNZLWK
// code-examples/XML/reading/from-string-script.scala

import scala.xml._

val someXMLInAString = """


<sammich>
<bread>wheat</bread>

211

Download at WoweBook.Com
<meat>salami</meat>
<condiments>
<condiment expired="true">mayo</condiment>
<condiment expired="false">mustard</condiment>
</condiments>
</sammich>
"""

val someXML = XML.loadString(someXMLInAString)


assert(someXML.isInstanceOf[scala.xml.Elem])

$OOILQHDQGZHOO:H¦YHWUDQVIRUPHGWKHVWULQJLQWRDNodeSeq6FDOD¦VW\SHIRUVWRULQJ
DVHTXHQFHRI;0/QRGHV:HUHRXU;0/GRFXPHQWLQDILOHRQGLVNZHFRXOGKDYH
XVHGWKHloadFilePHWKRGIURPWKHVDPHSDFNDJH
6LQFHZH¦UHVXSSO\LQJWKH;0/RXUVHOYHVZHFDQVNLSWKHXML.loadStringVWHSDQGMXVW
DVVLJQDFKXQNRIPDUNXSWRDvalRUvar
// code-examples/XML/reading/inline-script.scala

import scala.xml._

val someXML =
<sammich>
<bread>wheat</bread>
<meat>salami</meat>
<condiments>
<condiment expired="true">mayo</condiment>
<condiment expired="false">mustard</condiment>
</condiments>
</sammich>

assert(someXML.isInstanceOf[scala.xml.Elem])

Exploring XML
,IZHSDVWHWKHSUHYLRXVH[DPSOHLQWRWKHLQWHUSUHWHUZHFDQH[SORUHRXUVDQGZLFK
XVLQJVRPHKDQG\WRROVSURYLGHGE\NodeSeq
scala> someXML \ "bread"
res2: scala.xml.NodeSeq = <bread>wheat</bread>

7KDWEDFNVODVK¢ZKDWWKHGRFXPHQWDWLRQFDOOVDSURMHFWLRQIXQFWLRQ¢VD\V£)LQGPH
HOHPHQWVQDPHGbread¤:H¦OODOZD\VJHWDNodeSeqEDFNZKHQXVLQJDSURMHFWLRQIXQF
WLRQ,IZH¦UHRQO\LQWHUHVWHGLQZKDW¦VEHWZHHQWKHWDJVZHFDQXVHWKHtextPHWKRG
scala> (someXML \ "bread").text
res3: String = wheat

,W¦VYDOLGV\QWD[WRVD\someXML \ "bread" textZLWKRXWSDUHQWKHVHVRU


WKHGRWEHIRUHWKHFDOOWR text<RX¦OOVWLOOJHWWKHVDPHUHVXOWEXWLW¦V
KDUGHUWRUHDG3DUHQWKHVHVPDNH\RXULQWHQWFOHDU

212 | Chapter 10:—Herding XML in Scala

Download at WoweBook.Com
:H¦YHRQO\LQVSHFWHGWKHRXWHUPRVWOD\HURIRXUVDQGZLFK/HW¦VWU\WRJHWDNodeSeqRI
WKHFRQGLPHQWV
scala> someXML \ "condiment"
res4: scala.xml.NodeSeq =

:KDW ZHQW ZURQJ" 7KH \ IXQFWLRQ GRHVQ¦W GHVFHQG LQWR FKLOG HOHPHQWV RI DQ ;0/
VWUXFWXUH7RGRWKDWZHXVHLWVVLVWHUIXQFWLRQ\\ WZREDFNVODVKHV 
scala> someXML \\ "condiment"
res5: scala.xml.NodeSeq = <condiment expired="true">mayo</condiment>
<condiment expired="false">mustard</condiment>

0XFKEHWWHU :HVSOLWWKHVLQJOHRXWSXWOLQHLQWRWZROLQHVVRLWZRXOGILWRQWKHSDJH
:HGRYHLQWRWKHVWUXFWXUHDQGSXOOHGRXWWKHWZR <condiment>HOHPHQWV/RRNVOLNH
RQHRIWKHFRQGLPHQWVKDVJRQHEDGWKRXJK:HFDQILQGRXWLIDQ\RIWKHFRQGLPHQWV
KDVH[SLUHGE\H[WUDFWLQJLWV expiredDWWULEXWH$OOLWWDNHVLVDQ @EHIRUHWKHDWWULEXWH
QDPH
scala> (someXML \\ "condiment")(0) \ "@expired"
res6: scala.xml.NodeSeq = true

:HXVHGWKH(0)WRSLFNWKHILUVWRIWKHWZRFRQGLPHQWVWKDWZHUHUHWXUQHGE\(someXML
\\ "condiment")

Looping and Matching XML


7KHSUHYLRXVELWRIFRGHH[WUDFWHGWKHYDOXHRIWKHexpiredDWWULEXWH trueLQWKLVFDVH 
EXWLWGLGQ¦WWHOOXVZKLFKFRQGLPHQWLVH[SLUHG,IZHZHUHKDQGHGDQDUELWUDU\;0/
VDQGZLFKKRZZRXOGZHLGHQWLI\WKHH[SLUHGFRQGLPHQWV":HFDQORRSWKURXJKWKH
;0/
// code-examples/XML/reading/for-loop-script.scala

for (condiment <- (someXML \\ "condiment")) {


if ((condiment \ "@expired").text == "true")
println("the " + condiment.text + " has expired!")
}

%HFDXVH NodeSeqLQKHULWVWKHVDPHIDPLOLDUDWWULEXWHVWKDWPRVW6FDODFROOHFWLRQW\SHV
FDUU\WRROVOLNH forORRSVDSSO\GLUHFWO\,QWKHH[DPSOHMXVWVKRZQZHH[WUDFWWKH
<condiment>QRGHVORRSRYHUHDFKRIWKHPDQGWHVWZKHWKHURUQRWWKHLU expiredDW
WULEXWHHTXDOVWKHVWULQJ "true":HKDYHWRVSHFLI\WKDWZHZDQWWKH textRIDJLYHQ
condimentRWKHUZLVHZH¦GJHWDVWULQJUHSUHVHQWDWLRQRIWKHHQWLUHOLQHRI;0/
:HFDQDOVRXVHSDWWHUQPDWFKLQJRQ;0/VWUXFWXUHV&DVHVLQSDWWHUQPDWFKHVFDQEH
ZULWWHQLQWHUPVRI;0/OLWHUDOVH[SUHVVLRQVEHWZHHQFXUO\EUDFHV {} HVFDSHEDFNWR
VWDQGDUG6FDODSDWWHUQPDWFKLQJV\QWD[7RPDWFKDOO;0/QRGHVLQWKHHVFDSHGSRU
WLRQRIDSDWWHUQPDWFKXVHDQXQGHUVFRUH ZLOGFDUG IROORZHGE\DQDVWHULVN _* 7R
ELQGZKDW\RX¦YHPDWFKHGRQWRDYDULDEOHSUHIL[WKHPDWFKZLWKWKHYDULDEOHQDPH
DQGDQ@VLJQ

Reading XML | 213

Download at WoweBook.Com
/HW¦VSXWDOOWKDWWRJHWKHULQWRRQHH[DPSOH:H¦OOLQFOXGHWKHRULJLQDO;0/GRFXPHQW
DJDLQVR\RXFDQIROORZDORQJDVZHSDWWHUQPDWFKRQ;0/
// code-examples/XML/reading/pattern-matching-script.scala

import scala.xml._

val someXML =
<sammich>
<bread>wheat</bread>
<meat>salami</meat>
<condiments>
<condiment expired="true">mayo</condiment>
<condiment expired="false">mustard</condiment>
</condiments>
</sammich>

someXML match {
case <sammich>{ingredients @ _*}</sammich> => {
for (cond @ <condiments>{_*}</condiments> <- ingredients)
println("condiments: " + cond.text)
}
}

+HUHZHELQGWKHFRQWHQWVRIRXU<sammich>VWUXFWXUH WKDWLVZKDW¦VLQVLGHWKHRSHQLQJ
DQGFORVLQJWDJ WRDYDULDEOHFDOOHG ingredients7KHQDVZHLWHUDWHWKURXJKWKHLQ
JUHGLHQWVLQDforORRSZHDVVLJQWKHHOHPHQWVWKDWDUHEHWZHHQWKH<condiments>WDJV
WRDWHPSRUDU\YDULDEOHcond(DFKcondLVSULQWHG
7KHVDPHWRROVWKDWOHWXVHDVLO\PDQLSXODWHFRPSOH[GDWDVWUXFWXUHVLQ6FDODDUHUHDGLO\
DYDLODEOHIRU;0/SURFHVVLQJ$VDUHDGDEOHDOWHUQDWLYHWR;6/76FDOD¦V;0/OLEUDU\
PDNHVUHDGLQJDQGSDUVLQJ;0/DEUHH]H,WDOVRJLYHVXVHTXDOO\SRZHUIXOWRROVIRU
ZULWLQJ;0/ZKLFKZH¦OOH[SORUHLQWKHQH[WVHFWLRQ

Writing XML
:KLOHVRPHODQJXDJHVFRQVWUXFW;0/WKURXJKFRPSOH[REMHFWVHULDOL]DWLRQPHFKD
QLVPV6FDOD¦VVXSSRUWIRU;0/OLWHUDOVPDNHVZULWLQJ;0/IDUVLPSOHU(VVHQWLDOO\
ZKHQ\RXZDQW;0/MXVWZULWH;0/7RLQWHUSRODWHYDULDEOHVDQGH[SUHVVLRQVHVFDSH
RXWWR6FDODZLWKFXUO\EUDFHVDVZHGLGLQWKHSDWWHUQPDWFKLQJH[DPSOHVHDUOLHU
scala> var name = "Bob"
name: java.lang.String = Bob

scala> val bobXML =


| <person>
| <name>{name}</name>
| </person>
bobXML: scala.xml.Elem =
<person>
<name>Bob</name>
</person>

214 | Chapter 10:—Herding XML in Scala

Download at WoweBook.Com
$VZHFDQVHHWKHnameYDULDEOHZDVVXEVWLWXWHGZKHQZHFRQVWUXFWHGWKH;0/GRFX
PHQWDVVLJQHGWR bobXML7KDWHYDOXDWLRQRQO\RFFXUVRQFHZHUH nameVXEVHTXHQWO\
UHGHILQHGWKH<name>HOHPHQWRIbobXMLZRXOGVWLOOFRQWDLQWKHVWULQJ£%RE¤

A Real-World Example
)RUDPRUHFRPSOHWHH[DPSOHOHW¦VVD\ZH¦UHGHVLJQLQJWKDWIDYRULWHODWWHUGD\£KHOOR
ZRUOG¤DEORJJLQJV\VWHP:H¦OOVWDUWZLWKDFODVVWRUHSUHVHQWDQ$WRPIULHQGO\EORJ
SRVW
// code-examples/XML/writing/post.scala

import java.text.SimpleDateFormat
import java.util.Date

class Post(val title: String, val body: String, val updated: Date) {
lazy val dashedDate = {
val dashed = new SimpleDateFormat("yy-MM-dd")
dashed.format(updated)
}

lazy val atomDate = {


val rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'h:m:ss'-05:00'")
rfc3339.format(updated)
}

lazy val slug = title.toLowerCase.replaceAll("\\W", "-")


lazy val atomId = "tag:example.com," + dashedDate + ":/" + slug
}

%H\RQGWKHREYLRXVtitleDQGbodyDWWULEXWHVZH¦YHGHILQHGVHYHUDOOD]LO\ORDGHGYDOXHV
LQRXU PostFODVV7KHVHDWWULEXWHVZLOOFRPHLQKDQG\ZKHQZHWUDQVPXWHRXUSRVWV
LQWRDQ$WRPIHHGWKHVWDQGDUGZD\WRV\QGLFDWHEORJVEHWZHHQFRPSXWHUVRQWKH:HE
$WRPGRFXPHQWVDUHDIODYRURI;0/DQGDSHUIHFWDSSOLFDWLRQIRUGHPRQVWUDWLQJWKH
SURFHVVRIRXWSXWWLQJ;0/ZLWK6FDOD
:H¦OOGHILQHDQAtomFeedFODVVWKDWWDNHVDVHTXHQFHRIPostREMHFWVDVLWVVROHDUJXPHQW
// code-examples/XML/writing/atom-feed.scala

import scala.xml.XML

class AtomFeed(posts: Seq[Post]) {


val feed =
<feed xmlns="">
<title>My Blog</title>
<subtitle>A fancy subtitle.</subtitle>
<link href=""/>
<link href="" rel="self"/>
<updated>{posts(0).atomDate}</updated>
<author>
<name>John Doe</name>
<uri></uri>

Writing XML | 215

Download at WoweBook.Com
</author>
<id></id>
{for (post <- posts) yield
<entry>
<title>{post.title}</title>
<link href={"" + post.slug + ".html"} rel="alternate"/>
<id>{post.atomId}</id>
<updated>{post.atomDate}</updated>
<content type="html">{post.body}</content>
<author>
<name>John Doe</name>
<uri></uri>
</author>
</entry>
}
</feed>

def write = XML.saveFull("/tmp/atom-example.xml", feed, "UTF-8", true, null)


}

:H¦UHPDNLQJKHDY\XVHRIWKHDELOLW\WRHVFDSHRXWWR6FDODH[SUHVVLRQVLQWKLVH[DPSOH
:KHQHYHUZHQHHGDSLHFHRIG\QDPLFLQIRUPDWLRQ¢IRUH[DPSOHWKHGDWHRIWKHILUVW
SRVWLQWKHVHTXHQFHIRUPDWWHGIRUWKH$WRPVWDQGDUG¢ZHVLPSO\HVFDSHRXWDQG
ZULWH6FDODDVZHQRUPDOO\ZRXOG,QWKHODWWHUKDOIRIWKH <feed>HOHPHQWZHXVHD
forFRPSUHKHQVLRQWRyieldVXFFHVVLYHEORFNVRIG\QDPLFDOO\IRUPDWWHG;0/
7KHwritePHWKRGRIAtomFeedGHPRQVWUDWHVWKHXVHRIWKHsaveFullPHWKRGSURYLGHG
E\WKHscala.xmlOLEUDU\saveFullZULWHVDQ;0/GRFXPHQWWRGLVNRSWLRQDOO\LQGLI
IHUHQWHQFRGLQJVFKHPHVDQGZLWKGLIIHUHQWGRFXPHQWW\SHGHFODUDWLRQV$OWHUQDWHO\
WKHsavePHWKRGZLWKLQWKHVDPHSDFNDJHZLOOPDNHXVHRIDQ\java.io.WriterYDULDQW
VKRXOG\RXQHHGEXIIHULQJSLSLQJHWF
:ULWLQJ;0/ZLWK6FDODLVVWUDLJKWIRUZDUGFRQVWUXFWWKHGRFXPHQW\RXQHHGZLWK
LQOLQH;0/XVHLQWHUSRODWLRQZKHUHG\QDPLFFRQWHQWLVWREHVXEVWLWXWHGDQGPDNH
XVHRIWKHKDQG\FRQYHQLHQFHPHWKRGVWRZULWH\RXUFRPSOHWHGGRFXPHQWVWRGLVNRU
WRRWKHURXWSXWVWUHDPV

Recap and What’s Next


;0/KDVEHFRPHXELTXLWRXVLQVRIWZDUHDSSOLFDWLRQV\HWIHZODQJXDJHVPDNHZRUNLQJ
ZLWK;0/DVLPSOHWDVN:HOHDUQHGKRZ6FDODDFFHOHUDWHV;0/GHYHORSPHQWE\PDN
LQJLWHDV\WRUHDGDQGZULWH;0/
,QWKHQH[WFKDSWHUZH¦OOOHDUQKRZ6FDODSURYLGHVULFKVXSSRUWIRUFUHDWLQJ\RXURZQ
'RPDLQ6SHFLILF/DQJXDJHV '6/V 

216 | Chapter 10:—Herding XML in Scala

Download at WoweBook.Com
CHAPTER 11
Domain-Specific Languages in Scala

$'RPDLQ6SHFLILF/DQJXDJHLVDSURJUDPPLQJODQJXDJHWKDWPLPLFVWKHWHUPVLGLRPV
DQGH[SUHVVLRQVXVHGDPRQJH[SHUWVLQWKHWDUJHWHGGRPDLQ&RGHZULWWHQLQD'6/
UHDGVOLNHVWUXFWXUHGSURVHIRUWKHGRPDLQ,GHDOO\DGRPDLQH[SHUWZLWKOLWWOHH[SHUL
HQFHLQSURJUDPPLQJFDQUHDGXQGHUVWDQGDQGYDOLGDWHWKLVFRGH6RPHWLPHVDGR
PDLQH[SHUWPLJKWEHDEOHWRZULWH'6/FRGHHYHQLIKHLVQ¦WDSURIHVVLRQDOSURJUDPPHU
'6/VDUHDODUJHWRSLF:H¦OORQO\WRXFKWKHVXUIDFHRI'6/VDQG6FDOD¦VLPSUHVVLYH
VXSSRUW IRU WKHP )RU PRUH LQIRUPDWLRQ RQ '6/V LQ JHQHUDO VHH >)RZOHU@
>)RUG@ DQG >'HXUVHQ@ 7KH EDVLF EXLOG WRRO ZH XVHG IRU WKH ERRN¦V H[DPSOHV
sake XVHV D '6/ VLPLODU WR WKH YHQHUDEOH make DQG LWV 5XE\ FRXVLQ rake 6HH WKH
5($'0(LQWKHFRGHGRZQORDGDUFKLYHIRUGHWDLOV )RURWKHUH[DPSOHVRI6FDOD£LQ
WHUQDO¤DQG£H[WHUQDO¤'6/VVHH>*KRVKD@DQG>*KRVKE@)RUVRPHDGYDQFHG
ZRUNRQ'6/VXVLQJ6FDOD>+RIHU@H[SORUHVSRO\PRUSKLFVXEVWLWXWLRQRIDOWHUQD
WLYHLPSOHPHQWDWLRQVIRU'6/DEVWUDFWLRQVZKLFKLVXVHIXOIRUDQDO\VLVRSWLPL]DWLRQ
FRPSRVLWLRQHWF
:HOOFUDIWHG'6/VRIIHUVHYHUDOEHQHILWV
(QFDSVXODWLRQ
$'6/KLGHVLPSOHPHQWDWLRQGHWDLOVDQGH[SRVHVRQO\WKRVHDEVWUDFWLRQVUHOHYDQW
WRWKHGRPDLQ
(IILFLHQF\
%HFDXVHLPSOHPHQWDWLRQGHWDLOVDUHHQFDSVXODWHGD'6/RSWLPL]HVWKHHIIRUWUH
TXLUHGWRZULWHRUPRGLI\FRGHIRUDSSOLFDWLRQIHDWXUHV
&RPPXQLFDWLRQ
$'6/KHOSVGHYHORSHUVXQGHUVWDQGWKHGRPDLQDQGGRPDLQH[SHUWVWRYHULI\WKDW
WKHLPSOHPHQWDWLRQPHHWVWKHUHTXLUHPHQWV
4XDOLW\
$'6/PLQLPL]HVWKH£LPSHGDQFHPLVPDWFK¤EHWZHHQIHDWXUHUHTXLUHPHQWVDV
H[SUHVVHGE\GRPDLQH[SHUWVDQGWKHLPSOHPHQWLQJVRXUFHFRGHWKHUHE\PLQL
PL]LQJSRWHQWLDOEXJV

217

Download at WoweBook.Com
+RZHYHU'6/VDOVRKDYHVHYHUDOGUDZEDFNV
'LIILFXOWLHVRIFUHDWLQJJRRG'6/V
*RRG'6/VDUHKDUGHUWRGHVLJQWKDQWUDGLWLRQDO$3,V7KHODWWHUWHQGWRIROORZ
ODQJXDJHLGLRPVIRU$3,GHVLJQZKHUHXQLIRUPLW\LVLPSRUWDQW(YHQWKHQHOHJDQW
HIIHFWLYHDQGHDV\WRXVH$3,VDUHGLIILFXOWWRGHVLJQ,QFRQWUDVWHDFK'6/VKRXOG
UHIOHFW WKH XQLTXH ODQJXDJH LGLRPV RI LWV GRPDLQ 7KH '6/ GHVLJQHU KDV PXFK
JUHDWHUODWLWXGHZKLFKDOVRPHDQVLWLVPXFKKDUGHUWRGHWHUPLQHWKH£EHVW¤GHVLJQ
FKRLFHV
/RQJWHUPPDLQWHQDQFH
'6/V FDQ UHTXLUH PRUH PDLQWHQDQFH RYHU WKH ORQJ WHUP WR IDFWRU LQ GRPDLQ
FKDQJHV $OVR QHZ GHYHORSHUV ZLOO UHTXLUH PRUH WLPH WR OHDUQ KRZ WR XVH DQG
PDLQWDLQD'6/
+RZHYHUZKHQD'6/LVDSSURSULDWHIRUDQDSSOLFDWLRQ¢HJZKHQLWZRXOGEHXVHG
IUHTXHQWO\WRLPSOHPHQWDQGFKDQJHIXQFWLRQDOLW\¢DZHOOGHVLJQHG'6/FDQEHDSRZ
HUIXOWRROIRUEXLOGLQJIOH[LEOHDQGUREXVWDSSOLFDWLRQV
)URP WKH LPSOHPHQWDWLRQ SRLQW RI YLHZ '6/V DUH RIWHQ FODVVLILHG DV LQWHUQDO DQG
H[WHUQDO
$QLQWHUQDO VRPHWLPHVFDOOHGHPEHGGHG '6/LVDQLGLRPDWLFZD\RIZULWLQJFRGHLQD
JHQHUDOSXUSRVHSURJUDPPLQJODQJXDJHOLNH6FDOD1RVSHFLDOSXUSRVHSDUVHULVQHF
HVVDU\IRULQWHUQDO'6/V,QVWHDGWKH\DUHSDUVHGMXVWOLNHDQ\RWKHUFRGHZULWWHQLQWKH
ODQJXDJH,QFRQWUDVWDQH[WHUQDO'6/LVDFXVWRPODQJXDJHZLWKLWVRZQFXVWRPJUDP
PDUDQGSDUVHU
,QWHUQDO'6/VDUHHDVLHUWRFUHDWHEHFDXVHWKH\GRQ¦WUHTXLUHDVSHFLDOSXUSRVHSDUVHU
2QWKHRWKHUKDQGWKHFRQVWUDLQWVRIWKHXQGHUO\LQJODQJXDJHOLPLWWKHRSWLRQVIRU
H[SUHVVLQJGRPDLQFRQFHSWV([WHUQDO'6/VUHPRYHWKLVFRQVWUDLQW<RXFDQGHVLJQWKH
ODQJXDJHDQ\ZD\\RXZDQWDVORQJDV\RXFDQZULWHDUHOLDEOHSDUVHUIRULW7KHGRZQ
VLGHRIH[WHUQDO'6/VLVWKHUHTXLUHPHQWWRZULWHDQGXVHDFXVWRPSDUVHU
'6/VKDYHEHHQDURXQGDORQJWLPH)RUH[DPSOHLQWHUQDO'6/VZULWWHQLQ/LVSDUHDV
ROGDV/LVSLWVHOI,QWHUHVWLQ'6/VKDVVXUJHGUHFHQWO\GULYHQLQSDUWE\WKH5XE\FRP
PXQLW\EHFDXVHWKH\DUHYHU\HDV\WRLPSOHPHQWLQ5XE\$VZH¦OOVHH6FDODSURYLGHV
H[FHOOHQWVXSSRUWIRUWKHFUHDWLRQRILQWHUQDODQGH[WHUQDO'6/V

Internal DSLs
/HW¦V FUHDWH DQ LQWHUQDO '6/ IRU D SD\UROO DSSOLFDWLRQ WKDW FRPSXWHV DQ HPSOR\HH¦V
SD\FKHFNHYHU\SD\SHULRGZKLFKZLOOEHWZRZHHNVORQJ7KHSD\FKHFNZLOOLQFOXGH
WKH HPSOR\HH¦V QHW VDODU\ ZKLFK LV WKH JURVV VDODU\ PLQXV WKH GHGXFWLRQV IRU WD[HV
LQVXUDQFHSUHPLXPV DWOHDVWLQVRPHFRXQWULHV UHWLUHPHQWIXQGFRQWULEXWLRQVHWF

218 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
7REHWWHUXQGHUVWDQGWKHFRQWUDVWVEHWZHHQFRGHWKDWPDNHVXVHRI'6/VDQGFRGHWKDW
GRHV QRWOHW¦V WU\ ERWK WHFKQLTXHV RQ WKH VDPH SUREOHP +HUH¦V KRZ WKH SD\FKHFN
PLJKWEHFDOFXODWHGIRUWZRHPSOR\HHVZLWKRXWWKHKHOSRID'6/
// code-examples/DSLs/payroll/api/payroll-api-script.scala

import payroll.api._
import payroll.api.DeductionsCalculator._
import payroll._
import payroll.Type2Money._

val buck = Employee(Name("Buck", "Trends"), Money(80000))


val jane = Employee(Name("Jane", "Doe"), Money(90000))

List(buck, jane).foreach { employee =>


// Assume annual is based on 52 weeks.
val biweeklyGross = employee.annualGrossSalary / 26.

val deductions = federalIncomeTax(employee, biweeklyGross) +


stateIncomeTax(employee, biweeklyGross) +
insurancePremiums(employee, biweeklyGross) +
retirementFundContributions(employee, biweeklyGross)

val check = Paycheck(biweeklyGross, biweeklyGross - deductions, deductions)

format("%s %s: %s\n", employee.name.first, employee.name.last, check)


}

)RUHDFKHPSOR\HHWKHVFULSWFDOFXODWHVWKHJURVVSD\IRUWKHSD\SHULRGWKHGHGXFWLRQV
DQGWKHUHVXOWLQJQHW7KHVHYDOXHVDUHSODFHGLQWRD PaycheckZKLFKLVSULQWHGRXW
%HIRUHZHGHVFULEHWKHW\SHVZHDUHXVLQJQRWLFHDIHZWKLQJVDERXWWKHforeachORRS
WKDWGRHVWKHZRUN
)LUVWLWLVQRLV\)RUH[DPSOHLWPHQWLRQVemployeeDQGbiweeklyGrossLQFHVVDQWO\$
'6/ZLOOKHOSXVPLQLPL]HWKDW£QRLVH¤DQGIRFXVRQZKDW¦VUHDOO\JRLQJRQ
6HFRQGQRWLFHWKDWWKHFRGHLVLPSHUDWLYH,WVD\V£GLYLGHWKLVDGGWKDW¤DQGVRIRUWK
:H¦OOVHHWKDWRXU'6/VORRNVLPLODUEXWWKH\DUHPRUHGHFODUDWLYHKLGLQJWKHZRUN
IURPWKHXVHU
+HUHLVWKHVLPSOHPaycheckFODVVXVHGLQWKHVFULSW
// code-examples/DSLs/payroll/paycheck.scala

package payroll

/** We're ignoring invalid (?) cases like a negative net


* when deductions exceed the gross.
*/
case class Paycheck(gross: Money, net: Money, deductions: Money) {

def plusGross (m: Money) = Paycheck(gross + m, net + m, deductions)


def plusDeductions (m: Money) = Paycheck(gross, net - m, deductions + m)
}

Internal DSLs | 219

Download at WoweBook.Com
7KHEmployeeW\SHXVHVDNameW\SH
// code-examples/DSLs/payroll/employee.scala

package payroll

case class Name(first: String, last: String)

case class Employee(name: Name, annualGrossSalary: Money)

7KH Money W\SH KDQGOHV DULWKPHWLF URXQGLQJ WR IRXU GHFLPDO SODFHV HWF ,W LJQRUHV
FXUUHQF\H[FHSWIRUWKH toStringPHWKRG3URSHUILQDQFLDODULWKPHWLFLVQRWRULRXVO\
GLIILFXOWWRGRFRUUHFWO\IRUUHDOZRUOGWUDQVDFWLRQV7KLVLPSOHPHQWDWLRQLVQRWSHUIHFWO\
DFFXUDWHEXWLW¦VFORVHHQRXJKIRURXUSXUSRVHV>0RQH\,Q-DYD@SURYLGHVXVHIXOLQIRU
PDWLRQRQGRLQJUHDOPRQH\FDOFXODWLRQV
// code-examples/DSLs/payroll/money.scala

package payroll
import java.math.{BigDecimal => JBigDecimal,
MathContext => JMathContext, RoundingMode => JRoundingMode}

/** Most arithmetic is done using JBigDecimals for tighter control.


*/
class Money(val amount: BigDecimal) {

def + (m: Money) =


Money(amount.bigDecimal.add(m.amount.bigDecimal))
def - (m: Money) =
Money(amount.bigDecimal.subtract(m.amount.bigDecimal))
def * (m: Money) =
Money(amount.bigDecimal.multiply(m.amount.bigDecimal))
def / (m: Money) =
Money(amount.bigDecimal.divide(m.amount.bigDecimal,
Money.scale, Money.jroundingMode))

def < (m: Money) = amount < m.amount


def <= (m: Money) = amount <= m.amount
def > (m: Money) = amount > m.amount
def >= (m: Money) = amount >= m.amount

override def equals (o: Any) = o match {


case m: Money => amount equals m.amount
case _ => false
}

override def hashCode = amount.hashCode * 31

// Hack: Must explicitly call the correct conversion: double2Double


override def toString =
String.format("$%.2f", double2Double(amount.doubleValue))
}

object Money {
def apply(amount: BigDecimal) = new Money(amount)

220 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
def apply(amount: JBigDecimal) = new Money(scaled(new BigDecimal(amount)))
def apply(amount: Double) = new Money(scaled(BigDecimal(amount)))
def apply(amount: Long) = new Money(scaled(BigDecimal(amount)))
def apply(amount: Int) = new Money(scaled(BigDecimal(amount)))

def unapply(m: Money) = Some(m.amount)

protected def scaled(d: BigDecimal) = d.setScale(scale, roundingMode)

val scale = 4
val jroundingMode = JRoundingMode.HALF_UP
val roundingMode = BigDecimal.RoundingMode.ROUND_HALF_UP
val context = new JMathContext(scale, jroundingMode)
}

object Type2Money {
implicit def bigDecimal2Money(b: BigDecimal) = Money(b)
implicit def jBigDecimal2Money(b: JBigDecimal) = Money(b)
implicit def double2Money(d: Double) = Money(d)
implicit def long2Money(l: Long) = Money(l)
implicit def int2Money(i: Int) = Money(i)
}

1RWHWKDWZHXVHscala.BigDecimalZKLFKZUDSVjava.math.BigDecimalDVWKHVWRUDJH
W\SHIRUILQDQFLDOILJXUHV
'HGXFWLRQV DUH FDOFXODWHG XVLQJ IRXU KHOSHU PHWKRGV LQ payroll.api.Deduction
sCalculator
// code-examples/DSLs/payroll/api/deductions-calc.scala

package payroll.api
import payroll.Type2Money._

object DeductionsCalculator {
def federalIncomeTax(empl: Employee, gross: Money) = gross * .25

def stateIncomeTax(empl: Employee, gross: Money) = gross * .05

def insurancePremiums(empl: Employee, gross: Money) = Money(500)

def retirementFundContributions(empl: Employee, gross: Money) = gross * .10


}

(DFK PHWKRG PLJKW XVH WKH HPSOR\HH LQIRUPDWLRQ DQG WKH JURVV VDODU\ IRU WKH SD\
SHULRG,QWKLVFDVHZHXVHYHU\VLPSOHDOJRULWKPVEDVHGRQMXVWWKHJURVVVDODU\H[FHSW
IRULQVXUDQFHSUHPLXPVZKLFKZHWUHDWDVDIL[HGYDOXH
5XQQLQJWKHVFULSWIRUWKHSD\UROO$3,SURGXFHVWKHIROORZLQJRXWSXW
(665) $ scala -cp ... payroll-api-script.scala
Buck Trends: Paycheck($3076.92,$1346.15,$1730.77)
Jane Doe: Paycheck($3461.54,$1576.92,$1884.62)

Internal DSLs | 221

Download at WoweBook.Com
A Payroll Internal DSL
7KHSUHYLRXVFRGHZRUNVZHOOHQRXJKEXWVXSSRVHZHZDQWHGWRVKRZLWWRWKH$F
FRXQWLQJ 'HSDUWPHQW WR FRQILUP WKDW ZH¦UH FDOFXODWLQJ SD\FKHFNV FRUUHFWO\ 0RVW
OLNHO\WKH\ZRXOGJHWORVWLQWKH6FDODLGLRPV6XSSRVHIXUWKHUWKDWZHQHHGWKHDELOLW\
WRFXVWRPL]HWKLVDOJRULWKPIUHTXHQWO\¢IRUH[DPSOHEHFDXVHLWQHHGVWREHFXVWRPL]HG
IRUGLIIHUHQWHPSOR\HHW\SHV VDODULHGKRXUO\HWF RUWRPRGLI\WKHGHGXFWLRQFDOFX
ODWLRQV,GHDOO\ZHZRXOGOLNHWRHQDEOHWKHDFFRXQWDQWVWRGRWKHVHFXVWRPL]DWLRQV
WKHPVHOYHVZLWKRXWRXUKHOS
:HPLJKWDFKLHYHWKHVHJRDOVLIZHFDQH[SUHVVWKHORJLFLQD'6/WKDWLVVXIILFLHQWO\
LQWXLWLYHWRDQDFFRXQWDQW&DQZHPRUSKRXU$3,H[DPSOHLQWRVXFKD'6/"
5HWXUQLQJWRWKHVFULSWIRUWKHSD\UROO$3,ZKDWLIZHKLGHPRVWRIWKHH[SOLFLWUHIHUHQFHV
WRFRQWH[WLQIRUPDWLRQOLNHWKHHPSOR\HHJURVVVDODU\DQGGHGXFWLRQYDOXHV"&RQVLGHU
WKHIROORZLQJWH[W
Rules to calculate an employee's paycheck:
employee's gross salary for 2 weeks
minus deductions for
federalIncomeTax, which is 25% of gross
stateIncomeTax, which is 5% of gross
insurancePremiums, which are 500. in gross's currency
retirementFundContributions are 10% of gross

7KLVUHDGVOLNHQRUPDO(QJOLVKQRWFRGH:HKDYHLQFOXGHGVRPH£EXEEOH¤ZRUGV VHH
>)RUG@ WKDWDLGUHDGDELOLW\EXWGRQ¦WQHFHVVDULO\FRUUHVSRQGWRDQ\WKLQJHVVHQWLDO
VXFKDVtoanisforofDQGwhich:H¦OOHOLPLQDWHVRPHRIWKHVHXQQHFHVVDU\ZRUGV
DQGNHHSRWKHUVLQRXU6FDOD'6/
&RPSDUHGWRWKHYHUVLRQLQWKHSD\UROO$3,VFULSWWKHUH¦VDORWOHVVFOXWWHUREVFXULQJ
WKHHVVHQWLDOVRIWKHDOJRULWKP7KLVLVEHFDXVHZHKDYHPLQLPL]HGH[SOLFLWUHIHUHQFHV
WRWKHFRQWH[WXDOLQIRUPDWLRQ:HRQO\PHQWLRQ employeeWZLFH:HPHQWLRQ gross
ILYHWLPHVEXWKRSHIXOO\LQ£LQWXLWLYH¤ZD\V
7KHUHDUHPDQ\SRVVLEOHLQWHUQDO6FDOD'6/VZHFRXOGFRQVWUXFWWKDWUHVHPEOHWKLVDG
KRF'6/+HUHLVRQHRIWKHPDJDLQLQDVFULSWZKLFKSURGXFHVWKHVDPHRXWSXWDV
EHIRUH
// code-examples/DSLs/payroll/dsl/payroll-dsl-script.scala

import payroll._
import payroll.dsl._
import payroll.dsl.rules_

val payrollCalculator = rules { employee =>


employee salary_for 2.weeks minus_deductions_for { gross =>
federalIncomeTax is (25. percent_of gross)
stateIncomeTax is (5. percent_of gross)
insurancePremiums are (500. in gross.currency)
retirementFundContributions are (10. percent_of gross)
}

222 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
}

val buck = Employee(Name("Buck", "Trends"), Money(80000))


val jane = Employee(Name("Jane", "Doe"), Money(90000))

List(buck, jane).foreach { employee =>


val check = payrollCalculator(employee)
format("%s %s: %s\n", employee.name.first, employee.name.last, check)
}

:H¦OOJRWKURXJKWKHLPSOHPHQWDWLRQVWHSE\VWHSEXWILUVWOHW¦VVXPPDUL]HWKHIHDWXUHV
RI6FDODWKDWDOORZXVWRLPSOHPHQWWKLV'6/

Infix Operator Notation


&RQVLGHUWKLVOLQHLQWKHGHILQLWLRQRIpayrollCalculator
employee salary_for 2.weeks minus_deductions_for { gross =>

7KLVLQIL[QRWDWLRQLVHTXLYDOHQWWRWKHIROORZLQJOHVVUHDGDEOHIRUP
employee.salary_for(2.weeks).minus_deductions_for { gross =>

<RXFDQVHHZK\ZHZURWH2.weeksHDUOLHUEHFDXVHWKHUHVXOWRIWKLVH[SUHVVLRQLVSDVVHG
WR salary_for :LWKRXW WKH SHULRG WKH LQIL[ H[SUHVVLRQ ZRXOG EH SDUVHG DV
employee.salary_for(2).weeks...7KHUHLVQRweeksPHWKRGRQIntRIFRXUVH:H¦OO
UHYLVLWWKLVH[SUHVVLRQLQDPRPHQW
0HWKRGFKDLQLQJOLNHWKLVLVRIWHQLPSOHPHQWHGZKHUHHDFKPHWKRGUHWXUQVthisVR\RX
FDQFRQWLQXHFDOOLQJPHWKRGVRQWKHVDPHLQVWDQFH1RWHWKDWUHWXUQLQJ thisDOORZV
WKRVHPHWKRGFDOOVWRRFFXULQDQ\RUGHU,I\RXQHHGWRLPSRVHDVSHFLILFRUGHULQJWKHQ
UHWXUQDQLQVWDQFHRIDGLIIHUHQWW\SH)RUH[DPSOHLI minus_deductions_forPXVWEH
FDOOHGDIWHUsalary_forWKHQsalary_forVKRXOGUHWXUQDQHZLQVWDQFH
%HFDXVHFKDLQLQJLVVRHDV\ZHFRXOGKDYHFUHDWHGVHSDUDWHPHWKRGVIRU salary for
minusDQGdeductionsDOORZLQJXVWRZULWHWKHIROORZLQJH[SUHVVLRQ
employee salary for 2.weeks minus deductions for { gross =>

1RWHWKDWFDOOVWRforDUHSUHFHGHGE\GLIIHUHQWFDOOVZLWKYHU\GLIIHUHQWPHDQLQJV6R
LIWKHVDPHLQVWDQFHLVXVHGWKURXJKRXWLWZRXOGKDYHWRWUDFNWKH£IORZ¤LQWHUQDOO\
&KDLQLQJGLIIHUHQWLQVWDQFHVZRXOGHOLPLQDWHWKLVSUREOHP+RZHYHUVLQFHQRFRP
SXWDWLRQVDUHDFWXDOO\QHHGHGEHWZHHQWKHVHZRUGVZHFKRVHWKHVLPSOHUGHVLJQZKHUH
ZRUGVDUHMRLQHGWRJHWKHUVHSDUDWHGE\_

Implicit Conversions and User-Defined Types


5HWXUQLQJWR2.weeksVLQFHIntGRHVQ¦WKDYHDweeksPHWKRGZHXVHDQLPSOLFLWFRQ
YHUVLRQWRDDurationLQVWDQFHWKDWZUDSVDQIntVSHFLI\LQJDQDPRXQW

Internal DSLs | 223

Download at WoweBook.Com
// code-examples/DSLs/payroll/dsl/duration.scala

package payroll.dsl

case class Duration(val amount: Int) {


/** @return the number of work days in "amount" weeks. */
def weeks = amount * 5

/** @return the number of work days in "amount" years. */


def years = amount * 260
}

7KHweeksPHWKRGPXOWLSOHVWKDWDPRXQWE\WRUHWXUQWKHFRUUHVSRQGLQJDPRXQWRI
ZRUNGD\V+HQFHZHGHVLJQHGWKHSD\UROOFDOFXODWRUWRZRUNZLWKGD\VDVWKHXQLWRI
WLPH7KLVGHFLVLRQLVFRPSOHWHO\KLGGHQEHKLQGWKH'6/6KRXOGZHODWHUDGGVXSSRUW
IRUZRUNKRXUVLWZRXOGEHHDV\WRUHIDFWRUWKHGHVLJQWRXVHKRXUVLQVWHDG
DurationLVRQHRIWKHDGKRFW\SHVWKDWZHGHVLJQHGWRHQFDSVXODWHWKHLPSOLFLWFRQWH[W
WRLPSOHPHQWKHOSHUPHWKRGVIRUWKH'6/HWF:H¦OOGLVFXVVWKHLPSOLFLWFRQYHUVLRQ
PHWKRGZHQHHGLQDPRPHQW

Apply Methods
$QXPEHURIWKHLPSOHPHQWDWLRQREMHFWVXVHapplyWRLQYRNHEHKDYLRU7KHrulesREMHFW
HQFDSVXODWHVWKHSURFHVVRIEXLOGLQJWKHUXOHVIRUSD\UROOFDOFXODWLRQ,WVapplyPHWKRG
WDNHVDIXQFWLRQOLWHUDOEmployee => Paycheck

Payroll Rules DSL Implementation


1RZOHW¦VH[SORUHWKHLPSOHPHQWDWLRQVWDUWLQJZLWKWKHrulesREMHFWDQGZRUNLQJRXU
ZD\GRZQ
// code-examples/DSLs/payroll/dsl/payroll.scala

package payroll.dsl
import payroll._

object rules {

def apply(rules: Employee => Paycheck) = new PayrollBuilderRules(rules)

implicit def int2Duration(i: Int) = Duration(i)

implicit def employee2GrossPayBuilder(e: Employee) =


new GrossPayBuilder(e)

implicit def grossPayBuilder2DeductionsBuilder(b: GrossPayBuilder)


= new DeductionsBuilder(b)

implicit def double2DeductionsBuilderDeductionHelper(d: Double) =


new DeductionsBuilderDeductionHelper(d)
}

224 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
import rules._
...

7KHIXQFWLRQOLWHUDODUJXPHQWIRU rules.applyLVXVHGWRFRQVWUXFWD PayrollBuilder


RulesWKDWZLOOSURFHVVWKHVSHFLILHGUXOHV,WLVXVHGDWWKHYHU\EHJLQQLQJRIWKH'6/
val payrollCalculator = rules { employee => ...

7KH rules REMHFW DOVR GHILQHV LPSOLFLW FRQYHUVLRQV 7KH ILUVW RQH LV XVHG E\ WKH
2.weeksH[SUHVVLRQ,WFRQYHUWV 2LQWRD DurationLQVWDQFHZKLFKZHGLVFXVVHGSUHYL
RXVO\7KHRWKHUFRQYHUVLRQVDUHXVHGODWHULQWKH'6/WRHQDEOHWUDQVSDUHQWFRQYHUVLRQ
RIDoublesEmployeesHWFLQWRZUDSSHULQVWDQFHVWKDWZHZLOOGHVFULEHVKRUWO\
1RWHWKDWWKHrulesREMHFWLVLPSRUWHGVRWKHVHFRQYHUVLRQVDUHYLVLEOHLQWKHUHVWRIWKH
FXUUHQWILOH,WZLOODOVRQHHGWREHLPSRUWHGLQILOHVWKDWXVHWKH'6/
7KHPayrollBuilderRulesLVRXUILUVWZUDSSHULQVWDQFH,WHYDOXDWHVWKHIXQFWLRQOLWHUDO
IRUWKHZKROHUXOHVHWZUDSSHGLQDtry/catchEORFN
// code-examples/DSLs/payroll/dsl/payroll.scala
...
class PayrollException(message: String, cause: Throwable)
extends RuntimeException(message, cause)

protected[dsl] class PayrollBuilderRules(rules: Employee => Paycheck) {


def apply(employee: Employee) = {
try {
rules(employee)
} catch {
case th: Throwable => new PayrollException(
"Failed to process payroll for employee: " + employee, th)
}
}
}
...

1RWH WKDW ZH SURWHFW DFFHVV WR PayrollBuilderRules EHFDXVH ZH GRQ¦W ZDQW FOLHQWV
XVLQJLWGLUHFWO\+RZHYHUZHOHIWWKHH[FHSWLRQSXEOLFIRUXVHLQcatchFODXVHV <RX
FDQGHFLGHZKHWKHURUQRW\RXOLNHZUDSSLQJDWKURZQH[FHSWLRQLQD£GRPDLQVSHFLILF¤
H[FHSWLRQDVVKRZQ
1RWHWKDWZHKDYHWRSDVVWKHHPSOR\HHDVD£FRQWH[W¤LQVWDQFHLQWKHIXQFWLRQOLWHUDO
:HVDLGWKDWLWLVGHVLUDEOHWRPDNHWKHFRQWH[WDVLPSOLFLWDVSRVVLEOH$FRPPRQWKHPH
LQRXULPSOHPHQWDWLRQFODVVHVOLNHPayrollBuilderRulesLVWRKROGFRQWH[WLQIRUPDWLRQ
LQZUDSSHULQVWDQFHVDQGWRPLQLPL]HWKHLUYLVLELOLW\LQWKH'6/$QDOWHUQDWLYHDS
SURDFKZRXOGEHWRVWRUHFRQWH[WLQVLQJOHWRQREMHFWVVRRWKHULQVWDQFHVFDQJHWWRWKHP
7KLVDSSURDFKUDLVHVWKUHDGVDIHW\LVVXHVXQIRUWXQDWHO\
7RVHHZKDWZHPHDQFRQFHUQLQJWKHFRQWH[WFRQVLGHUWKHSDUWRIRXUVFULSWWKDWXVHV
WKHSD\UROO'6/ZKHUHWKHGHGXFWLRQVDUHVSHFLILHG
... { gross =>
federalIncomeTax is (25. percent_of gross)

Internal DSLs | 225

Download at WoweBook.Com
stateIncomeTax is (5. percent_of gross)
insurancePremiums are (500. in gross.currency)
retirementFundContributions are (10. percent_of gross)
}

&RQVLGHUWKHLQVXUDQFHSUHPLXPVIRUZKLFKDIODWMoney(500)LVGHGXFWHG:K\GLGQ¦W
ZHMXVWZULWHinsurancePremiums are 500.LQVWHDG",WWXUQVRXWZHKDYHWR£VQHDN¤WKH
gross LQVWDQFH LQWR WKH H[SUHVVLRQ VRPHKRZ 7KH QDPH gross LPSOLHV WKDW LW LV D
Money UHSUHVHQWLQJ WKH HPSOR\HH¦V VDODU\ IRU WKH SD\ SHULRG 7ULFNVH\ '6/VHV ,W LV
DFWXDOO\DQRWKHUKHOSHULQVWDQFHDeductionsBuilderZKLFKKROGVWKHZKROHSD\FKHFN
LQFOXGLQJWKHJURVVSD\DQGWKHHPSOR\HHLQVWDQFH7KHQDPH grossLVXVHGPHUHO\
EHFDXVHLWUHDGVZHOOLQWKHSODFHVZKHUHLWLVXVHG
7KLV EORFN LV FDOFXODWLQJ WKH GHGXFWLRQV DQG GHGXFWLQJ WKHP IURP WKH JURVV SD\ WR
GHWHUPLQHWKHQHWSD\7KHgrossLQVWDQFHKDQGOHVWKLVSURFHVV7KHUHLVQR£FRPPX
QLFDWLRQ¤EHWZHHQWKHIRXUOLQHVRIWKHIXQFWLRQOLWHUDO)XUWKHUPRUH federalIncome
Tax insurancePremiumsHWFDUHREMHFWVZLWKQRFRQQHFWLRQWR DeductionsBuilder DV
ZH¦OOVHHVKRUWO\ ,WZRXOGEHJUHDWLIWKH\FRXOGEHPHPEHUVRIDeductionsBuilderRU
SHUKDSVVRPHRWKHUZUDSSHULQVWDQFHHQFORVLQJWKLVVFRSH7KHQHDFKOLQHZRXOGEHD
PHWKRGFDOORQRQHRUWKHRWKHUZUDSSHU8QIRUWXQDWHO\WKLVGRHVQ¦WZRUN+HQFH
HDFKOLQHPXVWVSHFLI\WKH grossLQVWDQFHWRPDLQWDLQFRQWLQXLW\:HMXPSWKURXJK
YDULRXVKRRSVWRVXSSRUWWKHV\QWD[\HWDOORZgrossWREHDYDLODEOHDVQHHGHG
6RZHFRQWULYHGWKHFRQYHQWLRQWKDW£UDZ¤QXPEHUVOLNHWKHLQVXUDQFHGHGXFWLRQ
KDYHWREHTXDOLILHGE\WKHSDUWLFXODUFXUUHQF\XVHGIRUWKHJURVVSD\:H¦OOVHHKRZ
WKHH[SUHVVLRQ500. in gross.currencyZRUNVLQDPRPHQW,WLVVRPHWKLQJRIDKDFN
EXWLWUHDGVZHOODQGLWVROYHVRXUGHVLJQSUREOHP
+HUHLVDSRVVLEOHDOWHUQDWLYHGHVLJQWKDWZRXOGKDYHDYRLGHGWKHSUREOHP
... { builder =>
builder federalIncomeTax (25. percent_of gross)
builder stateIncomeTax (5. percent_of gross)
builder insurancePremiums 500.
builder retirementFundContributions (10. percent_of gross)
}

1RZ WKH IDFW WKDW D builder LV EHLQJ XVHG LV PRUH H[SOLFLW DQG federalIncomeTax
insurancePremiumsHWFDUHPHWKRGVRQWKHEXLOGHU:HRSWHGIRUDPRUHUHDGDEOHVW\OH
ZLWKWKHSHQDOW\RIDKDUGHULPSOHPHQWDWLRQ<RX¦OOVRPHWLPHVKHDUWKHSKUDVHIOXHQW
LQWHUIDFHXVHGWRUHIHUWR'6/VWKDWHPSKDVL]HUHDGDELOLW\
+HUHLVGrossPayBuilder
// code-examples/DSLs/payroll/dsl/payroll.scala
...
import payroll.Type2Money._

protected[dsl] class GrossPayBuilder(val employee: Employee) {

var gross: Money = 0

226 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
def salary_for(days: Int) = {
gross += dailyGrossSalary(employee.annualGrossSalary) * days
this
}

// Assume 260 working days: 52 weeks (including vacation) * 5 days/week.


def weeklyGrossSalary(annual: Money) = annual / 52.0
def dailyGrossSalary(annual: Money) = annual / 260.0
}
...

5HFDOOWKDWrulesGHILQHVDQLPSOLFLWFRQYHUVLRQIURPEmployeeWRWKLVW\SH,WLVLQYRNHG
E\WKHH[SUHVVLRQemployee salary_forVRWKHGrossPayBuilder.salary_forPHWKRGFDQ
EHFDOOHGGrossPayBuilderLQLWLDOL]HVWKHgrossDQGDSSHQGVQHZYDOXHVWRLWZKHQHYHU
salary_for LV FDOOHG ZKLFK DVVXPHV ZH¦UH DGGLQJ JURVV SD\ LQ LQFUHPHQWV RI GD\V
)LQDOO\salary_forUHWXUQVthisWRVXSSRUWFKDLQLQJ
'HGXFWLRQFDOFXODWLRQLVWKHPRVWFRPSOH[SDUW:KHQminus_deductions_forLVXVHG
LQ WKH '6/ LW WULJJHUV WKH LPSOLFLW FRQYHUVLRQ GHILQHG LQ rules IURP WKH GrossPay
BuilderWRDDeductionsBuilder
// code-examples/DSLs/payroll/dsl/payroll.scala
...
protected[dsl] class DeductionsBuilder(gpb: GrossPayBuilder) {

val employee = gpb.employee


var paycheck: Paycheck = new Paycheck(gpb.gross, gpb.gross, 0)

def currency = this

def minus_deductions_for(deductionRules: DeductionsBuilder => Unit) = {


deductionRules(this)
paycheck
}

def addDeductions(amount: Money) = paycheck = paycheck plusDeductions amount

def addDeductionsPercentageOfGross(percentage: Double) = {


val amount = paycheck.gross * (percentage/100.)
addDeductions(amount)
}
}
...

DeductionsBuilder VDYHV WKH employee IURP WKH SDVVHGLQ GrossPayBuilder ZKLFK LW


GRHVQ¦WVDYHDVDILHOG,WDOVRLQLWLDOL]HVWKHpaycheckXVLQJWKHFDOFXODWHGJURVVSD\
1RWHWKDWWKHcurrencyPHWKRGVLPSO\UHWXUQVthis:HGRQ¦WQHHGWRGRDQ\WKLQJZLWK
WKHDFWXDOFXUUHQF\ZKHQWKLVPHWKRGLVLQYRNHG,QVWHDGLWLVXVHGWRVXSSRUWDGHVLJQ
LGLRPWKDWZH¦OOGLVFXVVVKRUWO\
7KHminus_deductions_forGRHVWKHLPSRUWDQWZRUN,WLQYRNHVWKHIXQFWLRQOLWHUDOZLWK
WKHLQGLYLGXDOUXOHVDQGWKHQUHWXUQVWKHFRPSOHWHG PaycheckLQVWDQFHZKLFKLVXOWL
PDWHO\ZKDWrules.applyUHWXUQV

Internal DSLs | 227

Download at WoweBook.Com
2XU UHPDLQLQJ WZR PHWKRGV DUH XVHG WR FDOFXODWH LQGLYLGXDO GHGXFWLRQV 7KH\ DUH
FDOOHGIURPDeductionsBuilderDeductionHelperZKLFKZHVKRZQRZ
// code-examples/DSLs/payroll/dsl/payroll.scala
...
class DeductionCalculator {
def is(builder: DeductionsBuilder) = apply(builder)
def are(builder: DeductionsBuilder) = apply(builder)

def apply(builder: DeductionsBuilder) = {}


}

object federalIncomeTax extends DeductionCalculator


object stateIncomeTax extends DeductionCalculator
object insurancePremiums extends DeductionCalculator
object retirementFundContributions extends DeductionCalculator

protected[dsl] class DeductionsBuilderDeductionHelper(val factor: Double) {


def in (builder: DeductionsBuilder) = {
builder addDeductions Money(factor)
builder
}
def percent_of (builder: DeductionsBuilder) = {
builder addDeductionsPercentageOfGross factor
builder
}
}

1RZ ZH VHH WKDW federalIncomeTax HWF DUH VLQJOHWRQ REMHFWV 1RWH WKH £V\QRQ\P¤
PHWKRGV is DQG are :H XVHG are IRU WKH REMHFWV ZLWK SOXUDO QDPHV OLNH insuran
cePremiumsDQG isIRUWKHVLQJXODUREMHFWVOLNH federalIncomeTax,QIDFWVLQFHERWK
PHWKRGVGHOHJDWHWRapplyWKH\DUHHIIHFWLYHO\EXEEOHZRUGVWKDWWKHXVHUFRXOGRPLW
7KDWLVWKHIROORZLQJWZR'6/OLQHVDUHHTXLYDOHQW
federalIncomeTax is (25. percent_of gross)
federalIncomeTax (25. percent_of gross)

7KH applyPHWKRGWDNHV DeductionsBuilderDQGGRHVQRWKLQJZLWKLW,QIDFWE\WKH


WLPH applyLVFDOOHGWKHGHGXFWLRQKDVDOUHDG\EHHQFDOFXODWHGDQGIDFWRUHGLQWRWKH
SD\FKHFN %\ LPSOLFDWLRQ WKH SUHVHQFH RI H[SUHVVLRQV OLNH federalIncomeTax is DUH
HIIHFWLYHO\V\QWDFWLFVXJDU DWOHDVWDVWKLV'6/LVFXUUHQWO\LPSOHPHQWHG 7KH\DUHD
IDQF\IRUPRIFRPPHQWVEXWDWOHDVWWKH\KDYHWKHYLUWXHRIW\SHFKHFNLQJWKH£NLQGV¤
RIGHGXFWLRQVWKDWDUHDOORZHG2IFRXUVHDVWKHLPSOHPHQWDWLRQHYROYHVWKHVHLQ
VWDQFHVPLJKWGRUHDOZRUN
7R VHH ZK\ DeductionCalculator.apply LV HPSW\ OHW¦V GLVFXVV DeductionsBuil
derDeductionHelper5HFDOOWKDWWKHrulesREMHFWKDVDQLPSOLFLWFRQYHUVLRQPHWKRGWR
FRQYHUWD DoubleWRD DeductionsBuilderDeductionHelper2QFHZHKDYHDKHOSHULQ
VWDQFHZHFDQFDOOHLWKHUWKH inPHWKRGRUWKH percent_ofPHWKRG(YHU\OLQHLQWKH
GHGXFWLRQVIXQFWLRQOLWHUDOH[SORLWVWKLVLQVWDQFH

228 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
)RUH[DPSOH(25. percent_of gross)LVURXJKO\HTXLYDOHQWWRWKHIROORZLQJVWHSV
 &DOO WR rules.double2DeductionsBuilderDeductionHelper(25.) WR FUHDWH D QHZ
DeductionsBuilderDeductionHelper(25.)
 &DOOWRWKHKHOSHU¦Vpercent_of(gross)PHWKRGZKHUHgrossLVDDeductionsBuilder
 gross.addDeductionsPercentageOfGross(factor)
,QRWKHUZRUGVZHXVHG DeductionsBuilderDeductionHelperWRFRQYHUWDQH[SUHVVLRQ
RI WKH IRUP Double method DeductionsBuilder LQWR DQ H[SUHVVLRQ RI WKH IRUP
DeductionsBuilder method2 Double DeductionsBuilder DFFXPXODWHV HDFK GHGXFWLRQ
LQWRWKHSD\FKHFNZH¦UHEXLOGLQJ
7KH H[SUHVVLRQ 500. in gross.currency ZRUNV DOPRVW LGHQWLFDOO\ Deductions
Builder.currencyLVHIIHFWLYHO\DQRWKHUEXEEOHZRUGLWVLPSO\UHWXUQVthisEXWJLYHV
DUHDGDEOHLGLRPIRUWKH'6/7KHinPHWKRGVLPSO\FRQYHUWVWKHDoubleWRDMoneyDQG
SDVVHVLWWRDeductionsBuilder.addDeductions
6R DeductionCalculator.applyGRHVQRWKLQJEHFDXVHDOOWKHZRUNLVDOUHDG\GRQHE\
WKHWLPHapplyLVFDOOHG

Internal DSLs: Final Thoughts


6RZKLFKLVEHWWHUWKHRULJLQDO$3,LPSOHPHQWDWLRQRUWKH'6/LPSOHPHQWDWLRQ"7KH
'6/LPSOHPHQWDWLRQLVFRPSOH[/LNHDQ\ODQJXDJHWHVWLQJLWVUREXVWQHVVFDQEHD
FKDOOHQJH8VHUVZLOOWU\PDQ\FRPELQDWLRQVRIH[SUHVVLRQV7KH\ZLOOSUREDEO\QRW
XQGHUVWDQGWKHFRPSLOHUHUURUPHVVDJHVWKDWUHIHUWRWKHLQWHUQDOVZH¦YHKLGGHQEHKLQG
WKH'6/
'HVLJQLQJ D TXDOLW\ '6/ LV GLIILFXOW :LWK DQ $3, \RX FDQ IROORZ WKH 6FDOD OLEUDU\
FRQYHQWLRQVIRUW\SHVPHWKRGQDPHVHWF+RZHYHUZLWKD'6/\RX¦UHWU\LQJWRLPL
WDWHWKHODQJXDJHRIDQHZGRPDLQ,W¦VKDUGWRJHWLWULJKW
,W¦V ZRUWK WKH HIIRUW WKRXJK $ ZHOOGHVLJQHG '6/ PLQLPL]HV WKH WUDQVODWLRQ HIIRUW
EHWZHHQ UHTXLUHPHQWV DQG FRGH WKHUHE\ LPSURYLQJ FRPPXQLFDWLRQV ZLWK
VWDNHKROGHUVDERXWUHTXLUHPHQWV'6/VDOVRIDFLOLWDWHUDSLGIHDWXUHFKDQJHDQGKLGH
GLVWUDFWLQJ LPSOHPHQWDWLRQ GHWDLOV $V DOZD\V WKHUH LV D FRVWEHQHILW DQDO\VLV \RX
VKRXOGPDNHZKHQGHFLGLQJZKHWKHUWRXVHD'6/
$VVXPLQJ\RX¦YHPDGHWKH£JR¤GHFLVLRQDFRPPRQSUREOHPLQ'6/GHVLJQLVWKH
ILQLVKLQJSUREOHP VHH>)RUG@ +RZGR\RXNQRZZKHQ\RX¦YHILQLVKHGEXLOGLQJ
XSWKHVWDWHRIDQLQVWDQFHDQGLW¦VUHDG\WRXVH"
:HVROYHGWKLVSUREOHPLQWZRZD\V)LUVWZHQHVWHGWKHFDOFXODWLRQVWHSVLQDIXQFWLRQ
OLWHUDO$VVRRQDVrules(employee)ZDVLQYRNHGWKHSD\FKHFNZDVEXLOWWRFRPSOHWLRQ
$OVRDOOWKHVWHSVZHUHHYDOXDWHG£HDJHUO\¤:HGLGQ¦WQHHGWRSXWLQDOOWKHUXOHVWKHQ
UXQWKHPDWWKHHQG2XURQO\RUGHULQJUHTXLUHPHQWZDVWKHQHHGWRFDOFXODWHWKHJURVV

Internal DSLs | 229

Download at WoweBook.Com
SD\ILUVWVLQFHWKHGHGXFWLRQVDUHEDVHGRQLW:HHQIRUFHGWKHFRUUHFWRUGHURILQYR
FDWLRQXVLQJLQVWDQFHVRIGLIIHUHQWW\SHV
7KHUHDUHFDVHVLQZKLFK\RXFDQ¦WHYDOXDWHWKHEXLOGVWHSVHDJHUO\)RUH[DPSOHD'6/
WKDWEXLOGVXSD64/TXHU\VWULQJFDQ¦WUXQDTXHU\DIWHUHDFKVWHSRIWKHEXLOGSURFHVV
,QWKLVFDVHHYDOXDWLRQKDVWRZDLWXQWLOWKHTXHU\VWULQJLVFRPSOHWHO\EXLOW
%\FRQWUDVWLI\RXU'6/VWHSVDUHVWDWHOHVVFKDLQHGPHWKRGLQYRFDWLRQZRUNVMXVWILQH
,QWKLVFDVHLWGRHVQ¦WPDWWHUZKHQ\RXVWRSFDOOLQJFKDLQHGPHWKRGV,I\RXFKDLQ
PHWKRGVWKDWEXLOGXSVWDWH\RX¦OOKDYHWRDGGVRPHVRUWRIdonePHWKRGDQGWUXVWWKH
XVHUVWRDOZD\VXVHLWDWWKHHQG

External DSLs with Parser Combinators


:KHQ\RXZULWHDSDUVHUIRUDQH[WHUQDO'6/\RXFDQXVHDSDUVHUJHQHUDWRUWRROOLNH
$QWOU VHH>$QWOU@ +RZHYHUWKH6FDODOLEUDU\LQFOXGHVDSRZHUIXOSDUVHUFRPELQDWRU
OLEUDU\WKDWFDQEHXVHGIRUSDUVLQJPRVWH[WHUQDO'6/VWKDWKDYHDFRQWH[WIUHHJUDP
PDU$QDWWUDFWLYHIHDWXUHRIWKLVOLEUDU\LVWKHZD\LWGHILQHVDQLQWHUQDO'6/WKDWPDNHV
SDUVHUGHILQLWLRQVORRNYHU\VLPLODUWRIDPLOLDUJUDPPDUQRWDWLRQVOLNH(%1) ([WHQGHG
%DFNXV1DXU)RUP¢VHH>%1)@ 

About Parser Combinators


3DUVHUFRPELQDWRUVDUHEXLOGLQJEORFNVIRUSDUVHUV3DUVHUVWKDWKDQGOHVSHFLILFNLQGV
RILQSXW¢IORDWLQJSRLQWQXPEHUVLQWHJHUVHWF¢FDQEHFRPELQHGWRJHWKHUWRIRUP
RWKHUSDUVHUFRPELQDWRUVIRUODUJHUH[SUHVVLRQV$FRPELQDWRUIUDPHZRUNPDNHVLWHDV\
WR FRPELQH SDUVHUV WR KDQGOH VHTXHQWLDO DQG DOWHUQDWLYH FDVHV UHSHWLWLRQ RSWLRQDO
WHUPVHWF
:H¦OOOHDUQPRUHDERXWSDUVLQJWHFKQLTXHVDQGWHUPLQRORJ\DVZHSURFHHG$FRPSOHWH
H[SRVLWLRQRISDUVLQJWHFKQLTXHVLVEH\RQGRXUVFRSHEXWRXUH[DPSOHVKRXOGJHW\RX
VWDUWHG<RXFDQILQGDGGLWLRQDOH[DPSOHVRISDUVHUVZULWWHQXVLQJ6FDOD¦VSDUVHUFRP
ELQDWRUOLEUDU\LQ>6SLHZDNE@>*KRVKD@DQG>2GHUVN\@

A Payroll External DSL


)RURXUSDUVHUFRPELQDWRUH[DPSOHZH¦OOUHXVHWKHH[DPSOHZHMXVWGLVFXVVHGIRULQ
WHUQDO'6/V:H¦OOPRGLI\WKHJUDPPDUVOLJKWO\VLQFHRXUH[WHUQDO'6/GRHVQRWKDYH
WREHYDOLG6FDODV\QWD[2WKHUFKDQJHVZLOOPDNHSDUVHUFRQVWUXFWLRQHDVLHU+HUH¦VDQ
H[DPSOHZULWWHQLQWKHH[WHUQDO'6/
paycheck for employee "Buck Trends" is salary for 2 weeks minus deductions for {
federal income tax is 25. percent of gross,
state income tax is 5. percent of gross,
insurance premiums are 500. in gross currency,
retirement fund contributions are 10. percent of gross
}

230 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
&RPSDUH WKLV H[DPSOH WR WKH LQWHUQDO '6/ ZH GHILQHG LQ £$ 3D\UROO ,QWHUQDO
'6/¤RQSDJH
... = rules { employee =>
employee salary_for 2.weeks minus_deductions_for { gross =>
federalIncomeTax is (25. percent_of gross)
stateIncomeTax is (5. percent_of gross)
insurancePremiums are (500. in gross.currency)
retirementFundContributions are (10. percent_of gross)
}
}
...

,QRXUQHZ'6/ZHLQVHUWDVSHFLILFHPSOR\HHLQWKHVFULSW:HZRXOGQ¦WH[SHFWDXVHU
WRFRS\DQGSDVWHWKLVVFULSWIRUHYHU\HPSOR\HH$QDWXUDOH[WHQVLRQWKDWZHZRQ¦W
SXUVXH ZRXOG DOORZ WKH XVHU WR ORRS RYHU DOO VDODULHG HPSOR\HHV LQ D GDWDEDVH IRU
H[DPSOH
6RPHRIWKHGLIIHUHQFHVDUH£JUDWXLWRXV¤ZHFRXOGKDYHXVHGWKHVDPHV\QWD[ZHXVHG
SUHYLRXVO\7KHVHFKDQJHVLQFOXGHUHPRYLQJXQGHUVFRUHVEHWZHHQZRUGVLQVRPHH[
SUHVVLRQVDQGH[SDQGLQJFDPHOFDVHZRUGVLQWRVSDFHVHSDUDWHGZRUGV7KDWLVZH
WXUQHGVRPHVLQJOHZRUGVLQWRPXOWLZRUGH[SUHVVLRQV:HPDGHWKHVHFKDQJHVEH
FDXVHWKH\ZLOOEHHDV\WRLPSOHPHQWXVLQJSDUVHUFRPELQDWRUVEXWXVLQJWKHVDPH
PXOWLZRUGH[SUHVVLRQVZRXOGKDYHDGGHGDORWRIFRPSOH[LW\WRWKHLQWHUQDO'6/¦V
LPSOHPHQWDWLRQ
:HQRORQJHUQHHG£ORFDOYDULDEOHV¤OLNHemployeeDQGgross7KRVHZRUGVVWLOODSSHDU
LQWKH'6/EXWRXUSDUVHUZLOONHHSWUDFNRIWKHFRUUHVSRQGLQJLQVWDQFHVLQWHUQDOO\
7KHUHPDLQLQJFKDQJHVDUHSXQFWXDWLRQ,WLVVWLOOFRQYHQLHQWWRVXUURXQGWKHOLVWRI
GHGXFWLRQVZLWKFXUO\EUDFHV:HQRZXVHDFRPPDWRVHSDUDWHWKHLQGLYLGXDOGHGXF
WLRQVDVWKDWZLOOPDNHWKHSDUVHU¦VMREHDVLHU:HFDQDOVRGURSWKHSDUHQWKHVHVZH
XVHGHDUOLHU
7RVHHKRZFORVHO\WKHLQWHUQDO'6/IRU6FDOD¦VSDUVHUFRPELQDWRUOLEUDU\UHVHPEOHVWKH
FRQWH[WIUHHJUDPPDUOHW¦VVWDUWZLWKWKHJUDPPDULWVHOIZULWWHQLQDYDULDWLRQRI(%1)
:H¦OORPLWFRPPDVWRVHSDUDWHVHTXHQFHVIRUFODULW\
paycheck = empl gross deduct;

empl = "paycheck" "for" "employee" employeeName;

gross = "is" "salary" "for" duration;

deduct = "minus" "deductions" "for" "{" deductItems "}";

employeeName = "\"" name " " name "\"";

name = ...

duration = decimalNumber weeksDays;

weeksDays = "week" | "weeks" | "day" | "days";

External DSLs with Parser Combinators | 231

Download at WoweBook.Com
deductItems = R| deductItem { "," deductItem };

deductItem = deductKind deductAmount;

deductKind = tax | insurance | retirement;

tax = fedState "income" "tax";

fedState = "federal" | "state";

insurance = "insurance" "premiums";

retirement = "retirement" "fund" "contributions";

deductAmount = percentage | amount;

percentage = toBe doubleNumber "percent" "of" "gross";

amount = toBe doubleNumber "in" "gross" "currency";

toBe = "is" | "are";

decimalNumber = ...

doubleNumber = ...

:HFDQVHHWKDWPRVWRIWKHWHUPLQDOV WKHOLWHUDOVWULQJV paycheck for employeeWKH


FKDUDFWHUV{DQG}HWF ZLOOEHEXEEOHZRUGVDVGHILQHGLQWKHSUHYLRXVVHFWLRQ:H¦OO
LJQRUHWKHVHDIWHUSDUVLQJ7KHRLVXVHGWRLQGLFDWHDQHPSW\SURGXFWLRQIRUdeductI
temsDOWKRXJKWKHUHZLOOUDUHO\EHQRGHGXFWLRQV
:HGLGQ¦WVSHOORXWWKHGHWDLOVIRUGHFLPDOQXPEHUVGRXEOHQXPEHUVDQGDOORZHG
OHWWHUVLQWKHHPSOR\HHQDPHV:HVLPSO\HOLGHGWKRVHGHILQLWLRQV:H¦OOKDQGOHWKH
GHWDLOVODWHU
(DFKOLQHLQWKHJUDPPDUGHILQHVDSURGXFWLRQUXOH7KHHQGRIWKHGHILQLWLRQLVPDUNHG
ZLWKDVHPLFRORQ$QRQWHUPLQDODSSHDUVRQWKHOHIWKDQGVLGHRIWKHHTXDOVVLJQ7KH
ULJKWKDQGVLGHFRQVLVWVRIWHUPLQDOV HJWKHOLWHUDOVWULQJVDQGFKDUDFWHUVZHMXVWPHQ
WLRQHG  WKDW UHTXLUH QR IXUWKHU SDUVLQJ RWKHU QRQWHUPLQDOV LQFOXGLQJ SRVVLEO\ D
UHFXUVLYHUHIHUHQFHWRWKHOHIWKDQGVLGHQRQWHUPLQDO DQGRSHUDWRUVWKDWH[SUHVVUHOD
WLRQVKLSV EHWZHHQ WKH LWHPV 1RWLFH WKDW WKH JUDPPDU IRUPV KDYH D KLHUDUFKLFDO
GHFRPSRVLWLRQ DOWKRXJK QRW D GLUHFWHG DF\FOLF JUDSK DV JHQHUDOO\ VSHDNLQJ WKHVH
JUDPPDUVFDQKDYHF\FOHV
:HKDYHDFRQWH[WIUHHJUDPPDUEHFDXVHHYHU\SURGXFWLRQUXOHKDVDVLQJOHQRQWHUPL
QDORQWKHOHIWKDQGVLGHRIWKHHTXDOVVLJQLHZLWKRXWDQ\DGGLWLRQDOFRQWH[WLQIRU
PDWLRQUHTXLUHGWRVSHFLI\WKHSURGXFWLRQ¦VDSSOLFDELOLW\DQGPHDQLQJ
3URGXFWLRQUXOHVOLNHtoBe = "is" | "are"PHDQWKHisSURGXFWLRQ DWHUPLQDOLQWKLV
FDVH RUWKHareSURGXFWLRQZLOOPDWFK7KLVLVDQH[DPSOHRIDQDOWHUQDWLYHFRPSRVLWLRQ

232 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
:KHQSURGXFWLRQVDUHVHSDUDWHGE\ZKLWHVSDFHRQWKHULJKWKDQGVLGHRIDQRWKHUSUR
GXFWLRQHJprod1 prod2ERWKSURGXFWLRQVDUHUHTXLUHGWRDSSHDUVHTXHQWLDOO\IRUD
PDWFK 0RVW(%1)IRUPDWVDFWXDOO\UHTXLUHDFRPPDWRVHSDUDWHWKHVHLWHPV +HQFH
WKHVH H[SUHVVLRQV DUH PRUH OLNH £DQG¤ H[SUHVVLRQV EXW VHTXHQWLDO FRPSRVLWLRQ LV VR
FRPPRQWKDWQR&RSHUDWRULVXVHGWKHDQDORJRI|IRUDOWHUQDWLYHFRPSRVLWLRQ
7KHSURGXFWLRQUXOHZLWK"{" deductItem { "," deductItem } "}"GHPRQVWUDWHVKRZ
WRVSHFLI\RSWLRQDO ]HURRUPRUH UHSHWLWLRQV7KLVH[SUHVVLRQPDWFKHVDOLWHUDO{FKDU
DFWHUIROORZHGE\D deductItem DQRWKHUSURGXFWLRQ IROORZHGE\]HURRUPRUHH[
SUHVVLRQVFRQVLVWLQJRIDOLWHUDOFRPPD ,DQGDQRWKHU deductItemDQGILQDOO\HQGLQJ
ZLWKDOLWHUDO }FKDUDFWHU6RPHWLPHVDQDVWHULVNLVXVHGWRLQGLFDWHUHSHWLWLRQ]HURRU
PRUHWLPHVHJprod *)RUUHSHWLWLRQDWOHDVWRQFHprod +LVVRPHWLPHVXVHG
)LQDOO\LIZHKDGRSWLRQDOLWHPVLQRXUJUDPPDUZHZRXOGHQFORVHWKHPLQVTXDUH
EUDFNHWV [...] 7KHUH DUH RWKHU NLQGV RI FRPSRVLWLRQ RSHUDWRUV SRVVLEOH DQG
VXSSRUWHGLQWKH6FDODOLEUDU\ DIHZRIZKLFKZH¦OOGLVFXVV6HHWKH>6FDOD$3,@
HQWU\IRUParsersIRUPRUHGHWDLOV

A Scala Implementation of the External DSL Grammar


+HUHLVWKHSDUVHUZULWWHQXVLQJ6FDOD¦VSDUVHUFRPELQDWRUV$WWKLVSRLQWZHZRQ¦WGR
DQ\WKLQJWRDFWXDOO\FDOFXODWHDQHPSOR\HH¦VSD\FKHFNVRZH¦OODSSHQGV1WRWKHFODVV
QDPH
// code-examples/DSLs/payroll/pcdsl/payroll-parser-comb-v1.scala

package payroll.pcdsl
import scala.util.parsing.combinator._
import org.specs._
import payroll._
import payroll.Type2Money._

class PayrollParserCombinatorsV1 extends JavaTokenParsers {

def paycheck = empl ~ gross ~ deduct

def empl = "paycheck" ~> "for" ~> "employee" ~> employeeName

def gross = "is" ~> "salary" ~> "for" ~> duration

def deduct = "minus" ~> "deductions" ~> "for" ~> "{" ~> deductItems <~ "}"

// stringLiteral provided by JavaTokenParsers


def employeeName = stringLiteral

// decimalNumber provided by JavaTokenParsers


def duration = decimalNumber ~ weeksDays

def weeksDays = "weeks" | "week" | "days" | "day"

def deductItems = repsep(deductItem, "," )

External DSLs with Parser Combinators | 233

Download at WoweBook.Com
def deductItem = deductKind ~> deductAmount

def deductKind = tax | insurance | retirement

def tax = fedState <~ "income" <~ "tax"

def fedState = "federal" | "state"

def insurance = "insurance" ~> "premiums"

def retirement = "retirement" ~> "fund" ~> "contributions"

def deductAmount = percentage | amount

def percentage = toBe ~> doubleNumber <~ "percent" <~ "of" <~ "gross"

def amount = toBe ~> doubleNumber <~ "in" <~ "gross" <~ "currency"

def toBe = "is" | "are"

// floatingPointNumber provided by JavaTokenParsers


def doubleNumber = floatingPointNumber
}

7KHERG\RIPayrollParserCombinatorsV1ORRNVYHU\VLPLODUWRWKHJUDPPDUZHGHILQHG
IRUWKH'6/(DFKSURGXFWLRQUXOHEHFRPHVDPHWKRG7KHWHUPLQDWLQJVHPLFRORQLV
GURSSHGEXWVLQFHWKHSURGXFWLRQLVDPHWKRGLWZRXOGEHYDOLG6FDODWROHDYHLWLQ
:KHUHZHKDGZKLWHVSDFHEHWZHHQHDFKSURGXFWLRQRQWKHULJKWKDQGVLGHZHQRZXVH
DFRPELQDWRURSHUDWRUHLWKHU>RU<7KHFRPELQDWRUIRUVHTXHQWLDOFRPSRVLWLRQ
LVXVHGZKHQZHZDQWWRUHWDLQIRUIXUWKHUSURFHVVLQJWKHUHVXOWVSURGXFHGE\ERWK
SURGXFWLRQV RQ WKH OHIW DQG ULJKW VLGHV RI WKH  )RU H[DPSOH ZKHQ SURFHVVLQJ WKH
paycheckSURGXFWLRQZHZDQWWRNHHSDOOWKUHHUHVXOWVIURP empl grossDQG deduct
+HQFHZHXVHWZRRSHUDWRUV
def paycheck = empl ~ gross ~ deduct

:HXVHDQRWKHUVHTXHQWLDOFRPSRVLWLRQFRPELQDWRU >ZKHQZHQRORQJHUQHHGWKH
UHVXOWRIWKHSURGXFWLRQWRWKHOHIW)RUH[DPSOHZKHQSURFHVVLQJWKHemplSURGXFWLRQ
ZHRQO\ZDQWWRNHHSWKHSDUVHUHVXOWIRUWKHODVWSURGXFWLRQemployeeName
def empl = "paycheck" ~> "for" ~> "employee" ~> employeeName

6LPLODUO\ ZH XVH < ZKHQ ZH QR ORQJHU QHHG WKH UHVXOW IRU WKH SURGXFWLRQ WR WKH
ULJKW)RUH[DPSOHZKHQSURFHVVLQJWKHtaxSURGXFWLRQZHRQO\ZDQWWRNHHSWKHUHVXOW
RIWKHILUVWSURGXFWLRQfedState
def tax = fedState <~ "income" <~ "tax"

2XUKHDY\XVHRIWKH <VHTXHQWLDOFRPELQDWRULQWKHYDULRXVSURGXFWLRQVUHODWHGWR
GHGXFWLRQVLQGLFDWHVWKDWZHDUHQ¦WNHHSLQJWUDFNRIWKHVRXUFHRIHDFKGHGXFWLRQMXVW
WKHDPRXQWRIWKHGHGXFWLRQ$UHDOSD\FKHFNDSSOLFDWLRQZRXOGSULQWWKLVLQIRUPDWLRQ
RI FRXUVH 2XU DLP LV IRU VLPSOLFLW\ $V DQ H[HUFLVH FRQVLGHU KRZ PayrollParser

234 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
CombinatorsV1DQGWKHVXEVHTXHQWUHILQHPHQWVEHORZZRXOGFKDQJHLIZHWUDFNHGWKLV
LQIRUPDWLRQ:RXOG\RXQHFHVVDULO\NHHSWKHSDUVHGVWULQJVRUWUDFNWKHLQIRUPDWLRQ
VRPHRWKHUZD\"
7KH£RU¤FDVHLVH[SUHVVHGZLWKWKH|PHWKRGMXVWDVLQWKHJUDPPDU
def weeksDays = "weeks" | "week" | "days" | "day"

7KH repPHWKRGFDQEHXVHGIRU]HURRUPRUHUHSHWLWLRQV:HDFWXDOO\XVHDVLPLODU
PHWKRGrepsepZKLFKOHWVXVVSHFLI\DVHSDUDWRULQRXUFDVHDFRPPD , 
def deduct = ... ~> "{" ~> repsep(deductItem, "," ) <~ "}"

1RWHWKDWdeductFRPELQHVVHYHUDOIHDWXUHVZHKDYHMXVWGHVFULEHG
/LNHUHSHWLWLRQWKHUHLVDQoptPHWKRGIRURSWLRQDOWHUPVZKLFKZHDUHQ¦WXVLQJ
PayrollParserCombinatorsV1 LQKHULWV IURP JavaTokenParsers ZKLFK LQKHULWV IURP
RegexParsersZKLFKLQKHULWVIURPWKHURRWSDUVHUWUDLW Parsers,W¦VZHOONQRZQWKDW
SDUVLQJQRQWULYLDOJUDPPDUVZLWKMXVWUHJXODUH[SUHVVLRQVWHQGVWREUHDNGRZQSUHWW\
TXLFNO\+RZHYHUXVLQJUHJXODUH[SUHVVLRQVWRSDUVHLQGLYLGXDOWHUPVLQVLGHDSDUVLQJ
IUDPHZRUN FDQ EH YHU\ HIIHFWLYH ,Q RXU H[DPSOH ZH H[SORLW WKH SURGXFWLRQV LQ
JavaTokenParsersWRSDUVHTXRWHGVWULQJV IRUWKHHPSOR\HH¦VQDPH GHFLPDOOLWHUDOV
DQGIORDWLQJSRLQWOLWHUDOV
/HW¦VWU\LWRXW+HUHLVDVSHFLILFDWLRQWKDWH[HUFLVHVWKHSDUVHUIRUWZRFDVHVZLWKRXW
DQGZLWKGHGXFWLRQV
// code-examples/DSLs/payroll/pcdsl/payroll-parser-comb-v1-spec.scala

package payroll.pcdsl
import scala.util.parsing.combinator._
import org.specs._
import payroll._
import payroll.Type2Money._

object PayrollParserCombinatorsV1Spec
extends Specification("PayrollParserCombinatorsV1") {

"PayrollParserCombinatorsV1" should {
"parse rules when there are no deductions" in {
val input = """paycheck for employee "Buck Trends"
is salary for 2 weeks minus deductions for {}"""
val p = new PayrollParserCombinatorsV1
p.parseAll(p.paycheck, input) match {
case p.Success(r,_) => r.toString mustEqual
"""(("Buck Trends"~(2~weeks))~List())"""
case x => fail(x.toString)
}
}

"calculate the gross, net, and deductions for the pay period" in {
val input =
"""paycheck for employee "Buck Trends"
is salary for 2 weeks minus deductions for {

External DSLs with Parser Combinators | 235

Download at WoweBook.Com
federal income tax is 25. percent of gross,
state income tax is 5. percent of gross,
insurance premiums are 500. in gross currency,
retirement fund contributions are 10. percent of gross
}"""
val p = new PayrollParserCombinatorsV1
p.parseAll(p.paycheck, input) match {
case p.Success(r,_) => r.toString mustEqual
"""(("Buck Trends"~(2~weeks))~List(25., 5., 500., 10.))"""
case x => fail(x.toString)
}
}
}
}

7KLVSDUWRIWKHVSHFLILFDWLRQVKRZVXVKRZWRLQVWDQWLDWHDQGXVHWKHSDUVHU
val p = new PayrollParserCombinatorsV1

p.parseAll(p.paycheck, input) match {


case p.Success(r,_) => r.toString mustEqual "..."
case x => fail(x.toString)
}

7KHparseAllPHWKRGLVGHILQHGLQDSDUHQWFODVV:HLQYRNHWKHWRSOHYHOSURGXFWLRQ
PHWKRGpaycheckDQGSDVVLWVUHWXUQYDOXHDVWKHILUVWDUJXPHQWWRparseAllDQGSDVV
WKHVWULQJWRSDUVHDVWKHVHFRQGDUJXPHQW
,IWKHSDUVLQJSURFHVVLVVXFFHVVIXOWKHUHVXOWRIWKHSDUVHLVUHWXUQHGDVDQLQVWDQFHRI
W\SHp.Success[+T]DFDVHFODVVGHFODUHGLQWKHParsersWUDLW:K\LVWKHUHDp.SUHIL["
,WLQGLFDWHVWKDW p.SuccessLVDSDWKGHSHQGHQWW\SHZKLFKZHZLOOGLVFXVVLQ£3DWK
'HSHQGHQW7\SHV¤RQSDJH)RUQRZMXVWNQRZWKDWHYHQWKRXJK SuccessLVGH
ILQHGLQWKH ParsersWUDLWWKHDFWXDOW\SHRIWKHLQVWDQFHLVGHSHQGHQWRQWKH Payroll
ParserCombinatorsV1LQVWDQFHZHFUHDWHG,QRWKHUZRUGVLIZHKDGDQRWKHUSDUVHU
VD\ p2 RI W\SH MyOtherParser WKHQ p2.Success[String] ZRXOG EH GLIIHUHQW IURP
p.Success[String]DQGRQHFRXOGQRWEHVXEVWLWXWHGIRUWKHRWKHU
7KHSuccessLQVWDQFHFRQWDLQVWZRILHOGV7KHILUVWLVWKHUHVXOWRIWKHSDUVHDQLQVWDQFH
RIW\SHT DVVLJQHGWRrLQWKHcaseFODXVH 7KHVHFRQGLVWKHUHPDLQLQJLQSXWVWULQJWR
SDUVHZKLFKZLOOEHHPSW\DIWHUDVXFFHVVIXOSDUVH ZHZLOOKDYHSDUVHGWKHZKROHVWULQJ
DWWKLVSRLQW 7KLVVWULQJLVDVVLJQHGWR_
,I WKH SDUVH IDLOV WKH UHWXUQHG LQVWDQFH LV HLWKHU D p.Failure RU p.Error ZKLFK RXU
H[DPSOHKDQGOHVZLWKDJHQHULFcaseFODXVH%RWKDUHGHULYHGIURPp.NoSuccessZKLFK
FRQWDLQVILHOGVIRUDQHUURUPHVVDJHDQGWKHXQFRQVXPHGLQSXWDWWKHSRLQWRIIDLOXUH
$p.FailureLQDSDUVHUZLOOWULJJHUEDFNWUDFNLQJVRWKDWDUHWU\ZLWKDGLIIHUHQWSDUVHU
FDQEHLQYRNHGE\WKHSDUVHUIUDPHZRUNLISRVVLEOH$Q ErrorUHVXOWGRHVQRWWULJJHU
EDFNWUDFNLQJDQGLVXVHGWRVLJQDOPRUHVHULRXVSUREOHPV
)RUFRPSOHWHQHVVERWKp.SuccessDQGp.NoSuccessGHULYHIURPp.ParseResult

236 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
:H KDYH WZR ELJ XQDQVZHUHG TXHVWLRQV ZKDW GR WKH SURGXFWLRQ PHWKRGV DFWXDOO\
UHWXUQDQGZKDWLVWKHW\SHRIWKHUHVXOWLQVWDQFHUHWXUQHGLQWKHp.Success"
7KHSURGXFWLRQPHWKRGVWKHPVHOYHVUHWXUQSDUVHUV0RVWRIWKHPLQRXUH[DPSOHUH
WXUQ p.Parser[String] DJDLQDSDWKGHSHQGHQWW\SH +RZHYHUEHFDXVHWKH deduct
PHWKRG KDQGOHV UHSHWLWLRQ LW LQYRNHV WKH repsep PHWKRG  LW DFWXDOO\ UHWXUQV D
p.Parser[List[String]]:KHQWKLVSDUVHULVXVHGLWZLOOUHWXUQD List[String]ZLWK
RQHVWULQJFRUUHVSRQGLQJWRHDFKPDWFKLQWKHUHSHWLWLRQ
6RRXUFDOOWRp.parseAll(p.paycheck, input)HDUOLHUSDUVHVWKHinputVWULQJXVLQJWKH
SDUVHUUHWXUQHGE\p.paycheck7KDWEULQJVXVWRWKHVHFRQGTXHVWLRQZKDWLVWKHUHVXOW
RIDVXFFHVVIXOSDUVH"
7RVHHZKDW¦VUHWXUQHGFRPSLOHWKH3D\UROO3DUVHU&RPELQDWRUV9ILOHOLVWHGDWWKHEH
JLQQLQJRIWKLVVHFWLRQDQGLQYRNHWKHscalaLQWHUSUHWHUZLWKWKH-cpRSWLRQWRLQFOXGH
WKHGLUHFWRU\ZKHUHWKHFODVVILOHVZHUHZULWWHQ LWZLOOEHEXLOGLI\RXXVHGWKHEXLOG
SURFHVVIRUWKHFRGHH[DPSOHGLVWULEXWLRQ 
2QFHLQWKHLQWHUSUHWHUHQWHUWKHIROORZLQJH[SUHVVLRQVDIWHUWKHscala>SURPSW <RX
FDQDOVRILQGWKLVLQSXWWKHSD\UROOSDUVHUFRPEVFULSWVFDODILOHLQWKHFRGHH[DPSOH
GLVWULEXWLRQ
scala> import scala.util.parsing.combinator._
import scala.util.parsing.combinator._

scala> import payroll.pcdsl._


import payroll.pcdsl._

scala> val p = new PayrollParserCombinatorsV1


p: payroll.pcdsl.PayrollParserCombinatorsV1 = \
payroll.pcdsl.PayrollParserCombinatorsV1@79e84310

scala> p.empl
res0: p.Parser[String] = Parser (~>)

scala> p.weeksDays
res2: p.Parser[String] = Parser (|)

scala> p.doubleNumber
res3: p.Parser[String] = Parser ()

scala> p.deduct
res1: p.Parser[List[String]] = Parser (<~)

scala> p.paycheck
res4: p.Parser[p.~[p.~[String,p.~[String,String]],List[String]]] = Parser (~)

scala> p.parseAll(p.weeksDays, "weeks")


res5: p.ParseResult[String] = [1.6] parsed: weeks

scala> val input = """paycheck for employee "Buck Trends"


| is salary for 2 weeks minus deductions for {}"""
input: java.lang.String =

External DSLs with Parser Combinators | 237

Download at WoweBook.Com
paycheck for employee "Buck Trends"
is salary for 2 weeks minus deductions for {}

scala> p.parseAll(p.paycheck, input)


res6: p.ParseResult[p.~[p.~[String,p.~[String,String]],List[String]]] = \
[2.53] parsed: (("Buck Trends"~(2~weeks))~List())

scala>

:HLPSRUWWKHQHFHVVDU\W\SHVDQGFUHDWHDPayrollParserCombinatorsV1LQVWDQFH7KHQ
ZHFDOOVHYHUDORIWKHSURGXFWLRQPHWKRGVWRVHHZKDWNLQGRIParserHDFKUHWXUQV7KH
ILUVWWKUHH¢emplweeksDaysDQGdoubleNumber¢UHWXUQp.Parser[String]
1RWHZKDW¦VZULWWHQRQWKHULJKWKDQGVLGHLQWKHRXWSXWIRUWKHILUVWWKUHHSDUVHUVempl
weeksDaysDQGdoubleNumber:HVHHParser (>)Parser (|)DQGParser ()UHVSHF
WLYHO\7KHSDUVHUVUHWXUQHGUHIOHFWWKHGHILQLWLRQVRIWKHSURGXFWLRQUXOHVZKHUHempl
HQGVZLWKDFRPELQDWRURIWKHIRUP prod1 > prod2 weeksDaysUHWXUQVDFRPELQDWRU
RIWKHIRUPprod1 | prod2DQGdoubleNumberUHWXUQVDSDUVHUIRUDVLQJOHSURGXFWLRQ
%HFDXVHdeductFRQVLVWVRIFRPELQDWRUVWKDWKDQGOHUHSHWLWLRQWKHSDUVHUUHWXUQHGE\
deductLVRIW\SHp.Parser[List[String]]DVZHVWDWHGSUHYLRXVO\7KHULJKWKDQGVLGH
RIWKHRXWSXWLVParser (<)EHFDXVHWKHGHILQLWLRQRIdeductHQGVZLWKprod1 < prod2
7KLQJVJHWPRUHLQWHUHVWLQJZKHQZHORRNDWWKHWRSOHYHOSURGXFWLRQpaycheck:KDW
LV p.Parser[p.[p.[String,p.[String,String]],List[String]]] = Parser ()
VXSSRVHGWRPHDQ":HOOWKHULJKWKDQGVLGHVKRXOGEHHDV\WRXQGHUVWDQGQRZWKH
GHILQLWLRQ RI paycheck HQGV LQ prod1  prod2 :KDW LV WKH W\SH SDUDPHWHU IRU
p.ParserRQWKHOHIWKDQGVLGHRIWKHHTXDOVVLJQ"
7KHParsersWUDLWDOVRGHILQHVDFDVHFODVVQDPHGWKDWUHSUHVHQWVDSDLURIVHTXHQWLDO
UXOHV
case class ~[+a, +b](_1: a, _2: b) {
override def toString = "("+ _1 +"~"+ _2 +")"
}

7KHDFWXDOSDWKGHSHQGHQWW\SHLQRXUH[DPSOHLVp.[+a,+b]+HQFHWKHW\SHSDUDP
HWHUTLQp.Parser[T]LVp.[p.[String,p.[String,String]],List[String]]ZKLFKLV
DKLHUDUFKLFDOWUHHRIW\SHV
/HW¦VEUHDNLWGRZQZRUNLQJRXUZD\LQVLGHRXW1RWHWKDWWKHUHDUHWKUHHp.:H¦OO
VWDUWZLWKWKHLQQHUPRVWW\SHp.[String,String]DQGPDSWKHW\SHGHFODUDWLRQWRWKH
RXWSXWZHVDZLQWKHscalaVHVVLRQ"Buck Trends"(2weeksList())
7KH p.[String,String] FRUUHVSRQGV WR WKH SDUVHU WKDW KDQGOHV H[SUHVVLRQV OLNH
2 weeks+HQFHWKHLQVWDQFHFUHDWHGZKHQZHSDUVHGRXUH[DPSOHVWULQJZDVWKHLQ
VWDQFH p.("2", "weeks") &DOOLQJ WKH p..toString PHWKRG SURGXFHV WKH RXWSXW
(2~weeks)
:RUNLQJRXWRQHOHYHOZHKDYH p.[String,p.[String,String]]7KLVFRPELQDWLRQ
SDUVHV paycheck for employee "Buck Trends" is salary for 2 weeks5HFDOOWKDWZH

238 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
GLVFDUGpaycheck for employeeDQGis salary forNHHSLQJRQO\WKHBuck TrendsDQG
2 weeks6RZHFUHDWHDQLQVWDQFH p.("Buck Trends", p.("2", "weeks"))&DOOLQJ
toStringDJDLQUHVXOWVLQWKHVWULQJ("Buck Trends"(2weeks))
)LQDOO\ DW WKH RXWHUPRVW OHYHO \RX FDQ VHH ZH KDYH WKH IROORZLQJ
p.[p.[String,p.[String,String]],List[String]]:H¦YHDOUHDG\GLVFXVVHGHYHU\
WKLQJXSWRWKHODVWList[String]ZKLFKFRPHVIURPWKHdeductSURGXFWLRQ
def deduct = "minus" ~> "deductions" ~> "for" ~>
"{" ~> repsep(deductItem, "," ) <~ "}"

:HGLVFDUGHYHU\WKLQJH[FHSWIRUWKHOLVWRI]HURRUPRUHdeductItems7KHUHDUHQRQH
LQRXUH[DPSOHVRZHJHWDQHPSW\OLVWIRUZKLFKtoStringUHWXUQVList()7KHUHIRUH
FDOOLQJ p..toString RQ RXU RXWHUPRVW W\SH WKH RQH WKDW SDUDPHWHUL]HV p.Parser
UHWXUQVWKHVWULQJ"Buck Trends"(2weeksList()):H¦UHGRQH
:HOO QRW TXLWH :H¦UH VWLOO QRW FDOFXODWLQJ DQ DFWXDO SD\FKHFN IRU RO¦ %XFN /HW¦V
FRPSOHWHRXULPSOHPHQWDWLRQ

Generating Paychecks with the External DSL


$VZHSDUVHWKH'6/ZHZDQWWRORRNXSWKHHPSOR\HHE\QDPHIHWFKKLVRUKHUJURVV
VDODU\IRUWKHVSHFLILHGSD\SHULRGDQGWKHQFDOFXODWHWKHGHGXFWLRQVDVZHJR:KHQ
WKHSDUVHUUHWXUQHGE\ paycheckILQLVKHVZHZDQWWRUHWXUQD PairZLWKWKH Employee
LQVWDQFHDQGWKHFRPSOHWHGPaycheck
:HZLOOUHXVH£GRPDLQ¤FODVVHVOLNHEmployeeMoneyPaycheckHWFIURPHDUOLHULQWKH
FKDSWHU 7R GR WKH FDOFXODWLRQV RQ GHPDQG ZH ZLOO FUHDWH D VHFRQG LWHUDWLRQ RI
PayrollParserCombinatorsV1 WKDW ZH¦OO FDOO PayrollParserCombinators :H¦OO PRGLI\
WKHSDUVHUVUHWXUQHGE\VRPHRIWKHSURGXFWLRQPHWKRGVWRUHWXUQQHZNLQGVRISDUVHUV
:H¦OODOVRGRDGPLQLVWUDWLYHZRUNOLNHVWRULQJUXQQLQJFRQWH[WGDWDDVQHHGHG2XU
LPSOHPHQWDWLRQZRQ¦WEHWKUHDGVDIH<RX¦OOZDQWWRHQVXUHWKDWRQO\RQHWKUHDGXVHV
DJLYHQ PayrollParserCombinators:HFRXOGPDNHLWPRUHUREXVWEXWGRLQJVRLVQ¦W
WKHJRDORIWKLVH[HUFLVH
+HUHLVRXUILQDOPayrollParserCombinators
// code-examples/DSLs/payroll/pcdsl/payroll-parser-comb.scala

package payroll.pcdsl
import scala.util.parsing.combinator._
import org.specs._
import payroll._
import payroll.Type2Money._

class UnknownEmployee(name: Name) extends RuntimeException(name.toString)

class PayrollParserCombinators(val employees: Map[Name, Employee])


extends JavaTokenParsers {

var currentEmployee: Employee = null

External DSLs with Parser Combinators | 239

Download at WoweBook.Com
var grossAmount: Money = Money(0)

/** @return Parser[(Employee, Paycheck)] */


def paycheck = empl ~ gross ~ deduct ^^ {
case e ~ g ~ d => (e, Paycheck(g, g-d, d))
}

/** @return Parser[Employee] */


def empl = "paycheck" ~> "for" ~> "employee" ~> employeeName ^^ { name =>
val names = name.substring(1, name.length-1).split(" ") // remove ""
val n = Name(names(0), names(1));
if (! employees.contains(n))
throw new UnknownEmployee(n)
currentEmployee = employees(n)
currentEmployee
}

/** @return Parser[Money] */


def gross = "is" ~> "salary" ~> "for" ~> duration ^^ { dur =>
grossAmount = salaryForDays(dur)
grossAmount
}

def deduct = "minus" ~> "deductions" ~> "for" ~> "{" ~> deductItems <~ "}"

/**
* "stringLiteral" provided by JavaTokenParsers
* @return Parser[String]
*/
def employeeName = stringLiteral

/**
* "decimalNumber" provided by JavaTokenParsers
* @return Parser[Int]
*/
def duration = decimalNumber ~ weeksDays ^^ {
case n ~ factor => n.toInt * factor
}

def weeksDays = weeks | days

def weeks = "weeks?".r ^^ { _ => 5 }

def days = "days?".r ^^ { _ => 1 }

/** @return Parser[Money] */


def deductItems = repsep(deductItem, ",") ^^ { items =>
items.foldLeft(Money(0)) {_ + _}
}

/** @return Parser[Money] */


def deductItem = deductKind ~> deductAmount

def deductKind = tax | insurance | retirement

240 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
def tax = fedState <~ "income" <~ "tax"

def fedState = "federal" | "state"

def insurance = "insurance" ~> "premiums"

def retirement = "retirement" ~> "fund" ~> "contributions"

def deductAmount = percentage | amount

/** @return Parser[Money] */


def percentage = toBe ~> doubleNumber <~ "percent" <~ "of" <~ "gross" ^^ {
percentage => grossAmount * (percentage / 100.)
}

def amount = toBe ~> doubleNumber <~ "in" <~ "gross" <~ "currency" ^^ {
Money(_)
}

def toBe = "is" | "are"

def doubleNumber = floatingPointNumber ^^ { _.toDouble }

// Support method. Assume 260 (52 * 5) paid work days/year


def salaryForDays(days: Int) =
(currentEmployee.annualGrossSalary / 260.0) * days
}

)RUVLPSOLFLW\ZH¦OOXVHDPDSRI£NQRZQ¤HPSOR\HHVNH\HGE\ NameLQVWDQFHVWKDW
ZHVDYHDVDILHOGLQPayrollParserCombinators$UHDOLPSOHPHQWDWLRQZRXOGSUREDEO\
XVHDGDWDVWRUHRIVRPHNLQG
7KHUHDUHWZRRWKHUILHOGVcurrentEmployeeZKLFKUHPHPEHUVZKLFKHPSOR\HHZHDUH
SURFHVVLQJDQG grossAmountZKLFKUHPHPEHUVWKHJURVVDPRXQWRISD\IRUWKHHP
SOR\HHIRUWKHSD\SHULRG%RWKILHOGVKDYHDVOLJKWGHVLJQVPHOO7KH\DUHPXWDEOH7KH\
DUHVHWRQO\RQFHSHUSDUVHEXWQRWZKHQWKH\DUHGHFODUHGRQO\ZKHQZHSDUVHWKH
LQSXWWKDWDOORZVXVWRFDOFXODWHWKHP<RXPLJKWKDYHDOVRQRWLFHGWKDWLIWKHVDPH
PayrollParserCombinatorsLQVWDQFHLVXVHGPRUHWKDQRQFHZHGRQ¦WUHVHWWKHVHILHOGV
WRWKHLUGHIDXOWYDOXHV1RGRXEWLWZRXOGEHSRVVLEOHWRZULWHVFULSWVLQWKH'6/WKDW
H[SORLWWKLVEXJ
7KHVHZHDNQHVVHVDUHQRWLQKHUHQWWRSDUVHUFRPELQDWRUV7KH\UHIOHFWVLPSOLILFDWLRQV
ZHXVHGIRURXUSXUSRVHV$VDQH[HUFLVH\RXPLJKWWU\LPSURYLQJWKHLPSOHPHQWDWLRQ
WRHOLPLQDWHWKHVHZHDNQHVVHV
:HKDYHDGGHG-DYDGRFVW\OH@returnDQQRWDWLRQVIRUPRVWRIWKHSURGXFWLRQVWRPDNH
LWFOHDUZKDWWKH\DUHQRZUHWXUQLQJ,QVRPHFDVHVWKHSURGXFWLRQVDUHXQFKDQJHGDV
WKHRULJLQDOSDUVHULQVWDQFHVDUHILQHDVLV0RVWRIWKHFKDQJHVUHIOHFWRXUGHVLUHWR
FDOFXODWHWKHSD\FKHFNDVZHJR

External DSLs with Parser Combinators | 241

Download at WoweBook.Com
&RQVLGHUWKHQHZpaycheckSURGXFWLRQ
/** @return Parser[(Employee, Paycheck)] */
def paycheck = empl ~ gross ~ deduct ^^ {
case e ~ g ~ d => (e, Paycheck(g, g-d, d))
}

1RZZHUHWXUQDPairZLWKWKHEmployeeDQGWKHFRPSXWHGPaycheck7KHempl  gross
 deduct FRPELQDWLRQ ZRXOG VWLOO UHWXUQ Parser[String] ZH¦OO GURS WKH SDWK
GHSHQGHQW SUHIL[ IRU QRZ  :H KDYH DGGHG D QHZ FRPELQDWRU ^^ HJ prod1 ^^
func1ZKHUHfunc1LVDIXQFWLRQ,Iprod1VXFFHHGVWKHQWKHUHVXOWRIDSSO\LQJfunc1WR
WKHUHVXOWRIprod1LVUHWXUQHG7KDWLVZHUHWXUQfunc1(prod1)
)RUpaycheckZHJLYHLWDIXQFWLRQOLWHUDOWKDWGRHVDSDWWHUQPDWFKWRH[WUDFWWKHWKUHH
UHVXOWVIURP empl grossDQG deductUHVSHFWLYHO\:HFUHDWHDWXSOH Pair ZLWK e
WKHEmployeeDQGDPaycheckFDOFXODWHGIURPWKHJURVVVDODU\IRUWKHSD\SHULRG LQg
DQGWKHVXPRIDOOWKHGHGXFWLRQV LQd 
,W¦VLPSRUWDQWWRNHHSFOHDUWKDWWKHDQRQ\PRXVIXQFWLRQSDVVHGDVDQDUJXPHQWWR
^^UHWXUQVDWXSOH (Employee, Paycheck)EXWWKHSURGXFWLRQ paycheckPHWKRGLWVHOI
UHWXUQVDParser[(Employee, Paycheck)]7KLVSDWWHUQKDVEHHQWUXHIURPWKHEHJLQQLQJ
DFWXDOO\ZKHUHStringsZHUHDOZD\VLQYROYHGLQRXUILUVWYHUVLRQ,WZLOOUHPDLQWUXHIRU
DOOWKHSURGXFWLRQUXOHVLQPayrollParserCombinators
7KHemplSURGXFWLRQDVVXPHVWKHHPSOR\HH¦VILUVWQDPHDQGODVWQDPHDUHJLYHQ 2E
YLRXVO\WKLVZRXOGEHLQDGHTXDWHLQDUHDODSSOLFDWLRQ
/** @return Parser[Employee] */
def empl = "paycheck" ~> "for" ~> "employee" ~> employeeName ^^ { name =>
val names = name.substring(1, name.length-1).split(" ") // remove ""
val n = Name(names(0), names(1));
if (! employees.contains(n))
throw new UnknownEmployee(n)
currentEmployee = employees(n)
currentEmployee
}

7RFRQVWUXFWWKHQDPHWKHHPEHGGHGGRXEOHTXRWHVKDYHWREHUHPRYHGZKLFKLVZK\
ZHVWDUWE\H[WUDFWLQJWKHVXEVWULQJWKDWWRVVHVWKHILUVWDQGODVWFKDUDFWHUV7KHQDPH
LVXVHGWRORRNXSWKH EmployeeLQVWDQFHLQWKHPDSVDYLQJWKHYDOXHLQWKH curren
tEmployeeILHOG,QJHQHUDOWKHUHLVQRWDORWRI£JUDFHIXO¤HUURUKDQGOLQJLQPayrollPar
serCombinators +RZHYHU WKH empl PHWKRG KDQGOHV WKH FDVH ZKHUH QR HPSOR\HH LV
IRXQG ZLWK WKH VSHFLILHG QDPH WKURZLQJ DQ UnknownEmployee H[FHSWLRQ ZKHQ WKLV
RFFXUV
7KHUHVWRIWKHSURGXFWLRQVZRUNVLPLODUO\6RPHWLPHVDSDUVHUFRQYHUWVDQLQSXWVWULQJ
WRDQInt HJduration RUDMoney HJgross $QLQWHUHVWLQJFDVHLVdeduct,WIROGV
WKHOLVWRIGHGXFWLRQVLQWRDVLQJOHGHGXFWLRQDPRXQWXVLQJDGGLWLRQ7KH foldLeft
PHWKRGWDNHVWZRDUJXPHQWOLVWV7KHILUVWKDVDVLQJOHDUJXPHQWWKDWVSHFLILHVWKHLQLWLDO
YDOXHLQWKLVFDVH]HUR Money7KHVHFRQGDUJXPHQWOLVWKDVDVLQJOHIXQFWLRQOLWHUDO
DUJXPHQWWKDWWDNHVWZRDUJXPHQWVWKHDFFXPXODWHGYDOXHRIWKHIROGLQJRSHUDWLRQ

242 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
DQG DQ LWHP IURP WKH OLVW ,Q WKLV FDVH ZH UHWXUQ WKH VXP RI WKH DUJXPHQWV 6R
foldLeft LWHUDWHV RYHU WKH items FROOHFWLRQ DGGLQJ WKHP WRJHWKHU 6HH £7UDYHUVLQJ
0DSSLQJ )LOWHULQJ )ROGLQJ DQG 5HGXFLQJ¤ RQ SDJH  IRU PRUH LQIRUPDWLRQ RQ
foldLeftDQGUHODWHGRSHUDWLRQV
7KHweeksDQGdaysSURGXFWLRQVUHPLQGXVWKDWZHDUHXVLQJSDUVHUFRPELQDWRUVEDVHG
RQUHJXODUH[SUHVVLRQV :H¦UHDOVRXVLQJstringLiteraldecimalNumberDQGfloating
PointNumberSURYLGHGE\JavaTokenParsers 1RWHWKDWweeksDQGdaysLJQRUHWKHSDUVHG
VWULQJ7KH\MXVWUHWXUQDPXOWLSOLFDWLRQIDFWRUXVHGWRGHWHUPLQHWRWDOGD\VLQWKHSD\
SHULRGLQWKHdurationSURGXFWLRQUXOH
7KHUHDUHRWKHUFRPELQDWRUPHWKRGVIRUDSSO\LQJIXQFWLRQVWRSDUVHUUHVXOWVLQGLIIHUHQW
ZD\V6HHWKHParsers6FDODGRFSDJHIRUGHWDLOV
7KHIROORZLQJ VRPHZKDWLQFRPSOHWH VSHFLILFDWLRQVKRZVWKHFDOFXODWLRQRISD\FKHFNV
ZKHQWKHUHDUHQRGHGXFWLRQVDQGZKHQWKHUHDUHVHYHUDOGHGXFWLRQV
// code-examples/DSLs/payroll/pcdsl/payroll-parser-comb-spec.scala

package payroll.pcdsl
import scala.util.parsing.combinator._
import org.specs._
import payroll._
import payroll.Type2Money._

// Doesn't test "sad path" scenarios...


object PayrollParserCombinatorsSpec
extends Specification("PayrollParserCombinators") {

val salary = Money(100000.1) // for a full year


val gross = salary / 26. // for two weeks
val buck = Employee(Name("Buck", "Trends"), salary)
val employees = Map(buck.name -> buck)

implicit def money2double(m: Money) = m.amount.doubleValue

"PayrollParserCombinators" should {
"calculate the gross == net when there are no deductions" in {
val input = """paycheck for employee "Buck Trends"
is salary for 2 weeks minus deductions for {}"""
val p = new PayrollParserCombinators(employees)
p.parseAll(p.paycheck, input) match {
case p.Success(Pair(employee, paycheck),_) =>
employee mustEqual buck
paycheck.gross must beCloseTo(gross, Money(.001))
paycheck.net must beCloseTo(gross, Money(.001))
// zero deductions?
paycheck.deductions must beCloseTo(Money(0.), Money(.001))
case x => fail(x.toString)
}
}

"calculate the gross, net, and deductions for the pay period" in {
val input =

External DSLs with Parser Combinators | 243

Download at WoweBook.Com
"""paycheck for employee "Buck Trends"
is salary for 2 weeks minus deductions for {
federal income tax is 25. percent of gross,
state income tax is 5. percent of gross,
insurance premiums are 500. in gross currency,
retirement fund contributions are 10. percent of gross
}"""

val p = new PayrollParserCombinators(employees)


p.parseAll(p.paycheck, input) match {
case p.Success(Pair(employee, paycheck),_) =>
employee mustEqual buck
val deductions = (gross * .4) + Money(500)
val net = gross - deductions
paycheck.gross must beCloseTo(gross, Money(.001))
paycheck.net must beCloseTo(net, Money(.001))
paycheck.deductions must beCloseTo(deductions, Money(.001))
case x => fail(x.toString)
}
}
}
}

,I\RXZRUNRXWZKDWWKHUHVXOWVVKRXOGEHIURPWKHLQSXWVWULQJV\RX¦OOVHHWKDWWKH
LPSOHPHQWDWLRQFRUUHFWO\FDOFXODWHVWKHSD\FKHFN
%HVLGHVWKHPDQ\VPDOOGHWDLOVWKDWGLIIHUEHWZHHQWKLVLPSOHPHQWDWLRQRIWKHH[WHUQDO
'6/DQGWKHSUHYLRXVLPSOHPHQWDWLRQRIWKHLQWHUQDO'6/WKHUHLVRQHELJFRQFHSWXDO
GLIIHUHQFHIURPWKHWZRLPSOHPHQWDWLRQV+HUHZHDUHFRPSXWLQJWKHSD\FKHFNDVZH
SDUVH FRGH ZULWWHQ LQ WKH H[WHUQDO '6/ ,Q WKH LQWHUQDO '6/ FDVH ZH JHQHUDWHG D
SD\FKHFNFDOFXODWRUZKHQZHSDUVHGWKH'6/$IWHUZDUGZHXVHGWKDWFDOFXODWRUWR
FRPSXWHSD\FKHFNVIRURQHHPSOR\HHDWDWLPH:HFRXOGKDYHJHQHUDWHGDSD\FKHFN
FDOFXODWRUOLNHZHGLGEHIRUHEXWZHFKRVHDVLPSOHUDSSURDFKWRIRFXVRQWKHFRQ
VWUXFWLRQRIWKHSDUVHULWVHOI$OVRDVZHGLVFXVVHGHDUOLHUZHZHUHQ¦WDVFDUHIXODERXW
WKUHDGVDIHW\DQGRWKHULVVXHVLQWKHLPSOHPHQWDWLRQ

Internal Versus External DSLs: Final Thoughts


6FDODSURYLGHVULFKVXSSRUWIRUFUHDWLQJ\RXURZQLQWHUQDODQGH[WHUQDO'6/V+RZHYHU
DQRQWULYLDO'6/FDQEHDFKDOOHQJHWRLPSOHPHQWDQGGHEXJ)RUWKHH[DPSOHVLQWKLV
FKDSWHUWKHSDUVHUFRPELQDWRUVLPSOHPHQWDWLRQZDVHDVLHUWRGHVLJQDQGZULWHWKDQ
WKH LPSOHPHQWDWLRQ IRU WKH LQWHUQDO '6/ +RZHYHU ZH IRXQG WKDW GHEXJJLQJ WKH
LQWHUQDO'6/ZDVHDVLHU

244 | Chapter 11:—Domain-Specific Languages in Scala

Download at WoweBook.Com
<RXPXVWDOVRFRQVLGHUKRZUREXVWWKHSDUVHUPXVWEHZKHQKDQGOLQJLQYDOLGLQSXW
'HSHQGLQJ RQ WKH OHYHO RI VRSKLVWLFDWLRQ RI WKH XVHUV RI WKH '6/ \RX PD\ QHHG WR
SURYLGHYHU\JRRGIHHGEDFNZKHQHUURUVRFFXUHVSHFLDOO\ZKHQ\RXUXVHUVDUHQRQ
SURJUDPPHUV7KHSDUVHUFRPELQDWRUOLEUDU\LQ6FDODYHUVLRQZLOOSURYLGHLPSURYHG
VXSSRUWIRUHUURUUHFRYHU\DQGUHSRUWLQJFRPSDUHGWRWKHYHUVLRQ;OLEUDU\
7KHYHUVLRQOLEUDU\ZLOODOVRSURYLGHVXSSRUWIRUZULWLQJSDFNUDWSDUVHUVWKDWFDQ
LPSOHPHQWXQDPELJXRXVSDUVLQJH[SUHVVLRQJUDPPDUV 3(*V 7KHLPSOHPHQWD
WLRQRISDFNUDWSDUVHUVDOVRVXSSRUWVPHPRL]DWLRQZKLFKKHOSVLPSURYHSHUIRUPDQFH
DPRQJRWKHUEHQHILWV,I\RXQHHGDIDVWSDUVHUDSDFNUDWSDUVHUZLOOWDNH\RXIXUWKHU
EHIRUH\RXQHHGWRFRQVLGHUPRUHVSHFLDOL]HGWRROVOLNHSDUVHUJHQHUDWRUV

Recap and What’s Next


,W¦VWHPSWLQJWRFUHDWH'6/VZLWKDEDQGRQ'6/VLQ6FDODFDQEHTXLWHIXQWRZRUNZLWK
EXWGRQ¦WXQGHUHVWLPDWHWKHHIIRUWUHTXLUHGWRFUHDWHUREXVW'6/VWKDWPHHW\RXUFOLHQWV
XVDELOLW\QHHGVQRUORQJWHUPPDLQWHQDQFHDQGVXSSRUWLVVXHV
,I\RXFKRRVHWRZULWHD'6/\RXKDYHULFKRSWLRQVLQ6FDOD7KHV\QWD[LVIOH[LEOH\HW
SRZHUIXOHQRXJKWKDWDQLQWHUQDO'6/PD\EHVXIILFLHQW$LQWHUQDO'6/LVDQH[FHOOHQW
VWDUWLQJSRLQWHVSHFLDOO\LIRWKHUSURJUDPPHUVZLOOEHWKHSULPDU\ZULWHUVRIFRGHLQ
WKH'6/
,I\RXH[SHFW\RXUQRQSURJUDPPLQJVWDNHKROGHUVWRUHDGRUHYHQZULWHFRGHZULWWHQ
LQWKH'6/LWPLJKWEHZRUWKWKHH[WUDHIIRUWWRFUHDWHDQH[WHUQDO'6/WKDWHOLPLQDWHV
DVPDQ\RIWKHSURJUDPPLQJODQJXDJHLGLRPVDVSRVVLEOH&RQVLGHUZKHWKHUWKHFRGH
ZULWWHQLQWKH'6/ZLOOQHHGWREHSURFHVVHGIRURWKHUSXUSRVHVOLNHJHQHUDWLQJGRFX
PHQWDWLRQVSUHDGVKHHWVHWF6LQFH\RXZLOOKDYHWRZULWHDSDUVHUIRUWKH'6/DQ\ZD\
LWPLJKWEHVWUDLJKWIRUZDUGWRZULWHRWKHUVWRKDQGOHWKHVHGLIIHUHQWSXUSRVHV
,QWKHQH[WFKDSWHUZH¦OOH[SORUHWKHULFKQHVVRI6FDOD¦VW\SHV\VWHP:H¦YHOHDUQHG
PDQ\RILWVIHDWXUHVDOUHDG\1RZZH¦OOH[SORUHWKHW\SHV\VWHPLQIXOOGHWDLO

Recap and What’s Next | 245

Download at WoweBook.Com
Download at WoweBook.Com
CHAPTER 12
The Scala Type System

6FDODLVDVWDWLFDOO\W\SHGODQJXDJH,WVW\SHV\VWHPLVRQHRIWKHPRVWVRSKLVWLFDWHGLQ
DQ\ SURJUDPPLQJ ODQJXDJH LQ SDUW EHFDXVH LW FRPELQHV FRPSUHKHQVLYH LGHDV IURP
IXQFWLRQDOSURJUDPPLQJDQGREMHFWRULHQWHGSURJUDPPLQJ7KHW\SHV\VWHPWULHVWR
EHORJLFDOO\FRPSUHKHQVLYHFRPSOHWHDQGFRQVLVWHQW,WH[FHHGVOLPLWDWLRQVLQ-DYD¦V
W\SHV\VWHPZKLOHFRQWDLQLQJLQQRYDWLRQVWKDWDSSHDULQ6FDODIRUWKHILUVWWLPH
+RZHYHUWKHW\SHV\VWHPFDQEHLQWLPLGDWLQJDWILUVWHVSHFLDOO\LI\RXFRPHIURPD
G\QDPLFDOO\ W\SHG ODQJXDJH OLNH 5XE\ RU 3\WKRQ )RUWXQDWHO\ W\SH LQIHUHQFH KLGHV
PRVWRIWKHFRPSOH[LWLHVDZD\0RVWRIWKHWLPH\RXGRQ¦WQHHGWRNQRZWKHSDUWLFX
ODUVVRZHHQFRXUDJH\RXQRWWRZRUU\WKDW\RXPXVWPDVWHUWKHW\SHV\VWHPLQRUGHU
WRXVH6FDODHIIHFWLYHO\<RXPLJKWFKRRVHWRVNLPWKLVFKDSWHULI\RX¦UHQHZWR6FDOD
VR\RX¦OONQRZZKHUHWRORRNZKHQW\SHUHODWHGTXHVWLRQVDULVHODWHU
6WLOOWKHPRUH\RXNQRZDERXWWKHW\SHV\VWHPWKHPRUH\RXZLOOEHDEOHWRH[SORLW
LWVIHDWXUHVLQ\RXUSURJUDPV7KLVLVHVSHFLDOO\WUXHIRUOLEUDU\ZULWHUVZKRZLOOZDQW
WRXQGHUVWDQGZKHQWRXVHSDUDPHWHUL]HGW\SHVYHUVXVDEVWUDFWW\SHVZKLFKW\SHSD
UDPHWHUVVKRXOGEHFRYDULDQWFRQWUDYDULDQWRULQYDULDQWXQGHUVXEW\SLQJDQGVRIRUWK
$OVRVRPHXQGHUVWDQGLQJRIWKHW\SHV\VWHPZLOOKHOS\RXXQGHUVWDQGDQGGHEXJWKH
RFFDVLRQDOFRPSLODWLRQIDLOXUHUHODWHGWRW\SLQJ)LQDOO\WKLVXQGHUVWDQGLQJZLOOKHOS
\RXPDNHVHQVHRIWKHW\SHLQIRUPDWLRQVKRZQLQWKHVRXUFHVDQG6FDODGRFVIRU6FDOD
OLEUDULHV
,I\RXGLGQ¦WXQGHUVWDQGVRPHRIWKHWHUPVZHXVHGLQWKHSUHFHGLQJSDUDJUDSKVGRQ¦W
ZRUU\:H¦OOH[SODLQWKHPDQGZK\WKH\DUHXVHIXO:H¦UHQRWJRLQJWRGLVFXVV6FDOD¦V
W\SHV\VWHPLQH[KDXVWLYHGHWDLO5DWKHUZHZDQW\RXWRFRPHDZD\ZLWKDSUDJPDWLF
XQGHUVWDQGLQJRIWKHW\SHV\VWHP<RXVKRXOGGHYHORSDQDZDUHQHVVRIWKHIHDWXUHV
DYDLODEOHZKDWSXUSRVHVWKH\VHUYHDQGKRZWRUHDGDQGXQGHUVWDQGW\SHGHFODUDWLRQV
:H¦OODOVRKLJKOLJKWVLPLODULWLHVZLWK-DYD¦VW\SHV\VWHPVLQFHLWPD\EHDIDPLOLDUSRLQW
RIUHIHUHQFHIRU\RX8QGHUVWDQGLQJWKHGLIIHUHQFHVLVDOVRXVHIXOIRULQWHURSHUDELOLW\
ZLWK-DYDOLEUDULHV7RIRFXVWKHGLVFXVVLRQZHZRQ¦WFRYHUWKH1(7W\SHV\VWHP
H[FHSW WR SRLQW RXW VRPH QRWDEOH GLIIHUHQFHV WKDW 1(7 SURJUDPPHUV ZLOO ZDQW WR
NQRZ

247

Download at WoweBook.Com
Reflecting on Types
6FDODVXSSRUWVWKHVDPHUHIOHFWLRQFDSDELOLWLHVWKDW-DYDDQG1(7VXSSRUW7KHV\QWD[
LVGLIIHUHQWLQVRPHFDVHV
)LUVW\RXFDQXVHWKHVDPHPHWKRGV\RXPLJKWXVHLQ-DYDRU1(7FRGH7KHIROORZLQJ
VFULSW VKRZV VRPH RI WKH UHIOHFWLRQ PHWKRGV DYDLODEOH RQ WKH -90 WKURXJK
java.lang.ObjectDQGjava.lang.Class
// code-examples/TypeSystem/reflection/jvm-script.scala

trait T[A] {
val vT: A
def mT = vT
}

class C extends T[String] {


val vT = "T"
val vC = "C"
def mC = vC

class C2
trait T2
}

val c = new C
val clazz = c.getClass // method from java.lang.Object
val clazz2 = classOf[C] // Scala method: classOf[C] ~ C.class
val methods = clazz.getMethods // method from java.lang.Class<T>
val ctors = clazz.getConstructors // ...
val fields = clazz.getFields
val annos = clazz.getAnnotations
val name = clazz.getName
val parentInterfaces = clazz.getInterfaces
val superClass = clazz.getSuperclass
val typeParams = clazz.getTypeParameters

1RWHWKDWWKHVHPHWKRGVDUHRQO\DYDLODEOHRQVXEW\SHVRIAnyRef
7KHclassOf[T]PHWKRGUHWXUQVWKHUXQWLPHUHSUHVHQWDWLRQIRUD6FDODW\SH,WLVDQDO
RJRXVWRWKH-DYDH[SUHVVLRQT.class8VLQJclassOf[T]LVFRQYHQLHQWZKHQ\RXKDYH
DW\SHWKDW\RXZDQWLQIRUPDWLRQDERXWZKLOHgetClassLVFRQYHQLHQWIRUUHWULHYLQJWKH
VDPHLQIRUPDWLRQIURPDQLQVWDQFHRIWKHW\SH
+RZHYHUclassOf[T]DQGgetClassUHWXUQVOLJKWO\GLIIHUHQWYDOXHVUHIOHFWLQJWKHHIIHFW
RIW\SHHUDVXUHRQWKH-90LQWKHFDVHRIgetClass
scala> classOf[C]
res0: java.lang.Class[C] = class C

scala> c.getClass
res1: java.lang.Class[_] = class C

248 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
$OWKRXJK1(7GRHVQRWKDYHW\SHHUDVXUHPHDQLQJLWVXSSRUWVUHLILHG
W\SHV WKH 1(7 YHUVLRQ RI 6FDOD FXUUHQWO\ IROORZV WKH -90¦V HUDVXUH
PRGHOLQRUGHUWRDYRLGLQFRPSDWLELOLWLHVWKDWZRXOGUHTXLUHD£IRUNHG¤
LPSOHPHQWDWLRQ

:H¦OOGLVFXVVDZRUNDURXQGIRUHUDVXUHFDOOHGManifestVDIWHUZHGLVFXVVSDUDPHWHU
L]HGW\SHVLQWKHQH[WVHFWLRQ
6FDODDOVRSURYLGHVPHWKRGVIRUWHVWLQJZKHWKHUDQREMHFWPDWFKHVDW\SHDQGDOVRIRU
FDVWLQJDQREMHFWWRDW\SH
x.isInstanceOf[T]ZLOOUHWXUQ trueLIWKHLQVWDQFH xLVRIW\SH T+RZHYHUWKLVWHVWLV
VXEMHFWWRW\SHHUDVXUH)RUH[DPSOHList(3.14159).isInstanceOf[List[String]]ZLOO
UHWXUQtrueEHFDXVHWKHW\SHSDUDPHWHURIListLVORVWDWWKHE\WHFRGHOHYHO+RZHYHU
\RX¦OOJHWDQ£XQFKHFNHG¤ZDUQLQJIURPWKHFRPSLOHU
x.asInstanceOf[T]ZLOOFDVW xWR TRUWKURZD ClassCastExceptionLI TDQGWKHW\SHRI
xDUHQRWFRPSDWLEOH2QFHDJDLQW\SHHUDVXUHPXVWEHFRQVLGHUHGZLWKSDUDPHWHUL]HG
W\SHV7KHH[SUHVVLRQList(3.14159).asInstanceOf[List[String]]ZLOOVXFFHHG
1RWHWKDWWKHVHWZRRSHUDWLRQVDUHPHWKRGVDQGQRWNH\ZRUGVLQWKHODQJXDJHDQG
WKHLUQDPHVDUHGHOLEHUDWHO\VRPHZKDWYHUERVH1RUPDOO\W\SHFKHFNVDQGFDVWVOLNH
WKHVH VKRXOG EH DYRLGHG )RU W\SH FKHFNV XVH SDWWHUQ PDWFKLQJ LQVWHDG )RU FDVWV
FRQVLGHUZK\DFDVWLVQHFHVVDU\DQGGHWHUPLQHLIDUHIDFWRULQJRIWKHGHVLJQFDQHOLP
LQDWHWKHUHTXLUHPHQWIRUDFDVW

$WWKHWLPHRIWKLVZULWLQJWKHUHDUHVRPHH[SHULPHQWDOIHDWXUHVWKDW
PLJKWDSSHDULQWKHILQDOYHUVLRQUHOHDVHLQWKHscala.reflectSDFN
DJH 7KHVH IHDWXUHV DUH GHVLJQHG WR PDNH UHIOHFWLYH H[DPLQDWLRQ DQG
LQYRFDWLRQRIFRGHHDVLHUWKDQXVLQJWKHFRUUHVSRQGLQJ-DYDPHWKRGV

Understanding Parameterized Types


:HLQWURGXFHGSDUDPHWHUL]HGW\SHVDQGPHWKRGVLQ&KDSWHUDQGILOOHGLQDIHZPRUH
GHWDLOVLQ£$EVWUDFW7\SHV$QG3DUDPHWHUL]HG7\SHV¤RQSDJH,I\RXFRPHIURPD
-DYDRU&EDFNJURXQG\RXSUREDEO\DOUHDG\KDYHVRPHNQRZOHGJHRISDUDPHWHUL]HG
W\SHVDQGPHWKRGV1RZZHH[SORUHWKHGHWDLOVRI6FDOD¦VVRSKLVWLFDWHGVXSSRUWIRU
SDUDPHWHUL]HGW\SHV
6FDOD¦VSDUDPHWHUL]HGW\SHVDUHVLPLODUWR-DYDDQG&JHQHULFVDQG&WHPSODWHV
7KH\SURYLGHWKHVDPHFDSDELOLWLHVDV-DYDJHQHULFVEXWZLWKVLJQLILFDQWGLIIHUHQFHVDQG
H[WHQVLRQVUHIOHFWLQJWKHVRSKLVWLFDWLRQRI6FDOD¦VW\SHV\VWHP
7RUHFDSDGHFODUDWLRQOLNHclass List[+A]PHDQVWKDWListLVSDUDPHWHUL]HGE\DVLQJOH
W\SHUHSUHVHQWHGE\A7KH+LVFDOOHGDYDULDQFHDQQRWDWLRQ:H¦OOFRPHEDFNWRLWLQ
£9DULDQFH8QGHU,QKHULWDQFH¤RQSDJH

Understanding Parameterized Types | 249

Download at WoweBook.Com
6RPHWLPHVDSDUDPHWHUL]HGW\SHOLNHListLVFDOOHGDW\SHFRQVWUXFWRUEHFDXVHLWLVXVHG
WRFUHDWHVSHFLILFW\SHV)RUH[DPSOHListLVWKHW\SHFRQVWUXFWRUIRUList[String]DQG
List[Int]ZKLFKDUHGLIIHUHQWW\SHV DOWKRXJKWKH\DUHDFWXDOO\LPSOHPHQWHGZLWKWKH
VDPHE\WHFRGHGXHWRW\SHHUDVXUH ,QIDFWLW¦VPRUHDFFXUDWHWRVD\WKDWDOOWUDLWVDQG
FODVVHV DUH W\SH FRQVWUXFWRUV 7KRVH ZLWKRXW W\SH SDUDPHWHUV DUH HIIHFWLYHO\ ]HUR
DUJXPHQWSDUDPHWHUL]HGW\SHV

,I \RX ZULWH class StringList[String] extends List[String] {...}


6FDODZLOOLQWHUSUHW StringDVWKHQDPHRIWKHW\SHSDUDPHWHUQRWWKH
FUHDWLRQ RI D W\SH EDVHG RQ DFWXDO 6WULQJV <RX ZDQW WR ZULWH class
StringList extends List[String] {...}

Manifests
7KHUHLVDQH[SHULPHQWDOIHDWXUHLQ6FDOD VLQFHYHUVLRQ FDOOHG ManifestVWKDW
FDSWXUHVW\SHLQIRUPDWLRQWKDWLVHUDVHGLQWKHE\WHFRGH7KLVIHDWXUHLVQRWGRFXPHQWHG
LQWKH6FDODGRFVEXW\RXFDQH[DPLQHWKHVRXUFHIRUWKHscala.reflect.ManifestWUDLW
>2UWL]@GLVFXVVHVManifestVDQGSURYLGHVH[DPSOHVRIWKHLUXVH
$ManifestLVGHFODUHGDVDQLPSOLFLWDUJXPHQWWRDPHWKRGRUW\SHWKDWZDQWVWRFDSWXUH
WKHHUDVHGW\SHLQIRUPDWLRQ8QOLNHPRVWLPSOLFLWDUJXPHQWVWKHXVHUGRHVQRWQHHG
WRVXSSO\DQLQVFRSH ManifestYDOXHRUPHWKRG,QVWHDGWKHFRPSLOHUJHQHUDWHVRQH
DXWRPDWLFDOO\+HUHLVDQH[DPSOHWKDWLOOXVWUDWHVVRPHRIWKHVWUHQJWKVDQGZHDNQHVVHV
RIManifestV
// code-examples/TypeSystem/manifests/manifest-script.scala

import scala.reflect.Manifest

object WhichList {
def apply[B](value: List[B])(implicit m: Manifest[B]) = m.toString match {
case "int" => println( "List[Int]" )
case "double" => println( "List[Double]" )
case "java.lang.String" => println( "List[String]" )
case _ => println( "List[???]" )
}
}

WhichList(List(1, 2, 3))
WhichList(List(1.1, 2.2, 3.3))
WhichList(List("one", "two", "three"))

List(List(1, 2, 3), List(1.1, 2.2, 3.3), List("one", "two", "three")) foreach {


WhichList(_)
}

WhichListWULHVWRGHWHUPLQHWKHW\SHRIOLVWSDVVHGLQ,WXVHVWKHYDOXHRIWKHManifest¦V
toStringPHWKRGWRGHWHUPLQHWKLVLQIRUPDWLRQ1RWLFHWKDWLWZRUNVZKHQWKHOLVWLV
FRQVWUXFWHG LQVLGH WKH FDOO WR WhichList.apply ,W GRHV QRW ZRUN ZKHQ D SUHYLRXVO\
FRQVWUXFWHGOLVWLVSDVVHGWRWhichList.apply

250 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
7KHFRPSLOHUH[SORLWVWKHW\SHLQIRUPDWLRQLWNQRZVLQWKHILUVWFDVHWRFRQVWUXFWWKH
LPSOLFLWManifestZLWKWKHFRUUHFWB+RZHYHUZKHQJLYHQSUHYLRXVO\FRQVWUXFWHGOLVWV
WKHFUXFLDOW\SHLQIRUPDWLRQLVDOUHDG\ORVW
+HQFH ManifestVFDQ¦W£UHVXUUHFW¤W\SHLQIRUPDWLRQIURPE\WHFRGHEXWWKH\FDQEH
XVHGWRFDSWXUHDQGH[SORLWW\SHLQIRUPDWLRQEHIRUHLWLVHUDVHG

Parameterized Methods
,QGLYLGXDOPHWKRGVFDQDOVREHSDUDPHWHUL]HG*RRGH[DPSOHVDUHWKHapplyPHWKRGV
LQ FRPSDQLRQ REMHFWV IRU SDUDPHWHUL]HG FODVVHV 5HFDOO WKDW FRPSDQLRQ REMHFWV DUH
VLQJOHWRQREMHFWVDVVRFLDWHGZLWKDFRPSDQLRQFODVV7KHUHLVRQO\RQHLQVWDQFHRID
VLQJOHWRQREMHFWDVLWVQDPHLPSOLHVVRW\SHSDUDPHWHUVZRXOGEHPHDQLQJOHVV
/HW¦VFRQVLGHUobject ListWKHFRPSDQLRQREMHFWIRUclass List[+A]+HUHLVWKHGHI
LQLWLRQRIWKHapplyPHWKRGLQobject List
def apply[A](xs: A*): List[A] = xs.toList

7KH applyPHWKRGVWDNHVDYDULDEOHOHQJWKOLVWRIDUJXPHQWVRIW\SH AZKLFKZLOOEH


LQIHUUHGIURPWKHDUJXPHQWVDQGUHWXUQVDOLVWFUHDWHGIURPWKHDUJXPHQWV+HUHLVDQ
H[DPSOH
val languages = List("Scala", "Java", "Ruby", "C#", "C++", "Python", ...)
val positiveInts = List(1, 2, 3, 4, 5, 6, 7, ...)

:H¦OOORRNDWRWKHUSDUDPHWHUL]HGPHWKRGVVKRUWO\

Variance Under Inheritance


$QLPSRUWDQWGLIIHUHQFHEHWZHHQ-DYDDQG6FDODJHQHULFVLVKRZYDULDQFHXQGHULQKHU
LWDQFHZRUNV)RUH[DPSOHLIDPHWKRGKDVDQDUJXPHQWRIW\SHList[AnyRef]FDQ\RX
SDVV D List[String] YDOXH" ,Q RWKHU ZRUGV VKRXOG D List[String] EH FRQVLGHUHG D
VXEW\SHRI List[AnyRef]",IVRWKLVNLQGRIYDULDQFHLVFDOOHGFRYDULDQFHEHFDXVHWKH
VXSHUW\SHVXEW\SHUHODWLRQVKLSRIWKHFRQWDLQHU WKHSDUDPHWHUL]HGW\SH £JRHVLQWKH
VDPHGLUHFWLRQ¤DVWKHUHODWLRQVKLSEHWZHHQWKHW\SHSDUDPHWHUV,QRWKHUFRQWH[WV\RX
PLJKWZDQWFRQWUDYDULDQWRULQYDULDQWEHKDYLRUZKLFKZH¦OOGHVFULEHVKRUWO\
,Q6FDODWKHYDULDQFHEHKDYLRULVGHILQHGDWWKHGHFODUDWLRQVLWHXVLQJYDULDQFHDQQRWD
WLRQV+-RUQRWKLQJ,QRWKHUZRUGVWKHW\SHGHVLJQHUGHFLGHVKRZWKHW\SHVKRXOG
YDU\XQGHULQKHULWDQFH
/HW¦VH[DPLQHWKHWKUHHNLQGVRIYDULDQFHVXPPDUL]HGLQ7DEOHDQGXQGHUVWDQG
KRZWRXVHWKHPHIIHFWLYHO\:H¦OODVVXPHWKDW TVXSLVDVXSHUW\SHRI TDQG TVXELVD
VXEW\SHRIT

Variance Under Inheritance | 251

Download at WoweBook.Com
7DEOH7\SHYDULDQFHDQQRWDWLRQVDQGWKHLUPHDQLQJV
Annotation Java equivalent Description
+ ? extends T Covariant subclassing. E.g., List[Tsub] is a subtype of List[T].
- ? super T Contravariant subclassing. E.g., X[Tsup] is a subtype of X[T].
none T Invariant subclassing. E.g., Can’t substitute Y[Tsup] or Y[Tsub] for Y[T].

7KH£-DYDHTXLYDOHQW¤FROXPQLVDELWPLVOHDGLQJZH¦OOH[SODLQZK\LQDPRPHQW
&ODVV List LV GHFODUHG List[+A] ZKLFK PHDQV WKDW List[String] LV D VXEFODVV RI
List[AnyRef]VR ListsDUHFRYDULDQWLQWKHW\SHSDUDPHWHU A :KHQDW\SHOLNH List
KDVRQO\RQHFRYDULDQWW\SHSDUDPHWHU\RX¦OORIWHQKHDUWKHVKRUWKDQGH[SUHVVLRQ£/LVWV
DUHFRYDULDQW¤DQGVLPLODUO\IRUW\SHVZLWKDVLQJOHFRQWUDYDULDQWW\SHSDUDPHWHU
7KHWUDLWVFunctionNIRUNHTXDOVWRDUHXVHGE\6FDODWRLPSOHPHQWIXQFWLRQYDOXHV
DVWUXHREMHFWV/HW¦VSLFN Function1DVDUHSUHVHQWDWLYHH[DPSOH,WLVGHFODUHG trait
Function1[-T, +R]
7KH +RLVWKHUHWXUQW\SHDQGKDVWKHFRYDULDQWDQQRWDWLRQ +7KHW\SHIRUWKHVLQJOH
DUJXPHQWKDVWKHFRQWUDYDULDQWDQQRWDWLRQ-)RUIXQFWLRQVZLWKPRUHWKDQRQHDUJX
PHQWDOOWKHDUJXPHQWW\SHVKDYHWKHFRQWUDYDULDQWDQQRWDWLRQ6RIRUH[DPSOHXVLQJ
RXUTTVXSDQGTVXEW\SHVWKHIROORZLQJGHILQLWLRQZRXOGEHOHJDO
val f: Function1[T, T] = new Function1[Tsup, Tsub] { ... }

+HQFHWKHIXQFWLRQWUDLWVDUHFRYDULDQWLQWKHUHWXUQW\SHSDUDPHWHURDQGFRQWUDYDULDQW
LQWKHDUJXPHQWSDUDPHWHUVT, T, ..., T1
6RZKDWGRHVWKLVUHDOO\PHDQ"/HW¦VORRNDWDQH[DPSOHWRXQGHUVWDQGWKHYDULDQFH
EHKDYLRU,I\RXKDYHSULRUH[SHULHQFHZLWK'HVLJQE\&RQWUDFW VHH>'HVLJQ%\&RQ
WUDFW@ LWPLJKWKHOS\RXWRUHFDOOKRZLWZRUNVZKLFKLVYHU\VLPLODU :HZLOOGLVFXVV
'HVLJQE\&RQWUDFWEULHIO\LQ£%HWWHU'HVLJQZLWK'HVLJQ%\&RQWUDFW¤RQSDJH
7KLVVFULSWGHPRQVWUDWHVYDULDQFHXQGHULQKHULWDQFH
// code-examples/TypeSystem/variances/func-script.scala
// WON'T COMPILE

class CSuper { def msuper = println("CSuper") }


class C extends CSuper { def m = println("C") }
class CSub extends C { def msub = println("CSub") }

var f: C => C = (c: C) => new C // #1


f = (c: CSuper) => new CSub // #2
f = (c: CSuper) => new C // #3
f = (c: C) => new CSub // #4
f = (c: CSub) => new CSuper // #5: ERROR!

7KLVVFULSWGRHVQ¦WSURGXFHDQ\RXWSXW,I\RXUXQLWLWZLOOIDLOWRFRPSLOHRQWKHODVW
OLQH

252 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
:H VWDUW E\ GHILQLQJ D YHU\ VLPSOH KLHUDUFK\ RI WKUHH FODVVHV C DQG LWV VXSHUFODVV
CSuperDQGLWVVXEW\SHCSub(DFKRQHGHILQHVDPHWKRGZKLFKZH¦OOH[SORLWVKRUWO\
1H[WZHGHILQHDvarQDPHGfRQWKHOLQHZLWKWKHFRPPHQW,WLVDIXQFWLRQZLWK
WKHVLJQDWXUH C => C0RUHSUHFLVHO\LWLVRIW\SH Function1(-C,+C)7REHFOHDUWKH
YDOXHDVVLJQHGWR fLVDIWHUWKHHTXDOVVLJQ (c: C) => new C:HDFWXDOO\LJQRUHWKH
LQSXWcYDOXHDQGMXVWFUHDWHDQHZC
1RZZHDVVLJQGLIIHUHQWDQRQ\PRXVIXQFWLRQYDOXHVWRf:HXVHZKLWHVSDFHWRPDNH
WKHVLPLODULWLHVDQGGLIIHUHQFHVVWDQGRXWZKHQFRPSDULQJWKHRULJLQDOGHFODUDWLRQRI
f DQG WKH VXEVHTXHQW UHDVVLJQPHQWV :H NHHS UHDVVLJQLQJ WR f EHFDXVH ZH DUH MXVW
WHVWLQJZKDWZLOODQGZRQ¦WFRPSLOHDWWKLVSRLQW6SHFLILFDOO\ZHZDQWWRNQRZZKDW
IXQFWLRQYDOXHVZHFDQOHJDOO\DVVLJQWRf: (C) => C
7KHVHFRQGDVVLJQPHQWRQOLQHDVVLJQV(x:CSuper) => new CSubDVWKHIXQFWLRQYDOXH
7KLVDOVRZRUNVEHFDXVHWKHDUJXPHQWWR Function1LVFRQWUDYDULDQWVRZHFDQVXE
VWLWXWHWKHVXSHUW\SHZKLOHWKHUHWXUQW\SHRI Function1LVFRYDULDQWVRRXUIXQFWLRQ
YDOXHFDQUHWXUQDQLQVWDQFHRIWKHVXEW\SH
7KHQH[WWZROLQHVDOVRZRUN2QOLQHZHXVHD CSuperIRUWKHDUJXPHQWZKLFK
ZRUNVDVLWGLGLQOLQH:HUHWXUQDCZKLFKDOVRZRUNVDVH[SHFWHG6LPLODUO\RQ
OLQHZHXVHCDVWKHDUJXPHQWDQGCSubDVWKHUHWXUQW\SHERWKRIZKLFKZRUNHG
ILQHLQWKHSUHYLRXVOLQHV
7KHODVWOLQHGRHVQRWFRPSLOHEHFDXVHZHDUHDWWHPSWLQJWRXVHDFRYDULDQWDUJX
PHQWLQDFRQWUDYDULDQWSRVLWLRQ:H¦UHDOVRDWWHPSWLQJWRXVHDFRQWUDYDULDQWUHWXUQ
YDOXHZKHUHRQO\FRYDULDQWYDOXHVDUHDOORZHG
:K\LVWKHEHKDYLRUFRUUHFWLQWKHVHFDVHV"+HUH¦VZKHUH'HVLJQE\&RQWUDFWWKLQNLQJ
FRPHVLQKDQG\/HW¦VVHHKRZDFOLHQWPLJKWXVHVRPHRIWKHVHGHILQLWLRQVRIf
// code-examples/TypeSystem/variances/func2-script.scala
// WON'T COMPILE

class CSuper { def msuper = println("CSuper") }


class C extends CSuper { def m = println("C") }
class CSub extends C { def msub = println("CSub") }

def useF(f: C => C) = {


val c1 = new C // #1
val c2: C = f(c1) // #2
c2.msuper // #3
c2.m // #4
}

useF((c: C) => new C) // #5


useF((c: CSuper) => new CSub) // #6
useF((c: CSub) => {println(c.msub); new CSuper}) // #7: ERROR!

7KHuseFPHWKRGWDNHVDIXQFWLRQC => CDVDQDUJXPHQW :H¦UHMXVWSDVVLQJIXQFWLRQ


OLWHUDOVQRZUDWKHUWKDQDVVLJQLQJWKHPWR f ,WFUHDWHVD C OLQH DQGSDVVHVLWWR

Variance Under Inheritance | 253

Download at WoweBook.Com
WKHLQSXWIXQFWLRQWRFUHDWHDQHZC OLQH 7KHQLWXVHVWKHIHDWXUHVRICQDPHO\LW
FDOOVWKHmsuperDQGmPHWKRGV OLQHVDQGUHVSHFWLYHO\ 
<RXFRXOGVD\WKDWWKH useFPHWKRGVSHFLILHVDFRQWUDFWRIEHKDYLRU,WH[SHFWVWREH
SDVVHGDIXQFWLRQWKDWFDQWDNHD CDQGUHWXUQD C,WZLOOFDOOWKHSDVVHGLQIXQFWLRQ
SDVVLQJDCLQVWDQFHWRLWDQGLWZLOOH[SHFWWRUHFHLYHDCEDFN
,QOLQHZHSDVVuseFDIXQFWLRQWKDWWDNHVDCDQGUHWXUQVDC7KHUHWXUQHGCZLOO
ZRUNZLWKOLQHVDQGE\GHILQLWLRQ$OOLVJRRG
)LQDOO\ZHFRPHWRWKHSRLQWRIWKLVH[DPSOH,QOLQHZHSDVVLQDIXQFWLRQWKDWLV
£ZLOOLQJ¤WRDFFHSWD CSuperDQG£SURPLVHV¤WRUHWXUQD CSub7KDWLVWKLVIXQFWLRQLV
W\SHLQIHUUHGWREH Function1[CSuper,CSub],QHIIHFWLWZLGHQVWKHDOORZHGLQVWDQFHV
E\DFFHSWLQJDVXSHUW\SH.HHSLQPLQGWKDWLWZLOOQHYHUDFWXDOO\EHSDVVHGD CSuper
E\useFRQO\DC+RZHYHUVLQFHLWFDQDFFHSWDZLGHUVHWRILQVWDQFHVLWZLOOZRUNILQH
LILWRQO\JHWVCLQVWDQFHV
6LPLODUO\E\£SURPLVLQJ¤WRUHWXUQDCSubWKLVDQRQ\PRXVIXQFWLRQQDUURZVWKHSRV
VLEOHYDOXHVUHWXUQHGWRuseF7KDW¦V2.WRREHFDXVHuseFZLOODFFHSWDQ\CLQUHWXUQ
VRLILWRQO\JHWVCSubsLWZLOOEHKDSS\/LQHVDQGZLOOVWLOOZRUN
$SSO\LQJWKHVDPHDUJXPHQWVZHFDQVHHZK\WKHODVWOLQHLQWKHVFULSWOLQHIDLOV
WRFRPSLOH1RZWKHDQRQ\PRXVIXQFWLRQFDQRQO\DFFHSWDCSubEXWuseFZLOOSDVVLW
D C7KHERG\RIWKHDQRQ\PRXVIXQFWLRQZRXOGQRZEUHDNEHFDXVHLWFDOOV c.msub
ZKLFKGRHVQ¦WH[LVWLQC6LPLODUO\UHWXUQLQJDCSuperZKHQDCLVH[SHFWHGEUHDNVOLQH
LQuseFEHFDXVHCSuperGRHVQ¦WKDYHWKHmPHWKRG
7KHVDPHDUJXPHQWVDUHXVHGWRH[SODLQKRZFRQWUDFWVFDQFKDQJHXQGHULQKHULWDQFH
LQ'HVLJQE\&RQWUDFW
1RWHWKDWYDULDQFHDQQRWDWLRQVRQO\PDNHVHQVHRQWKHW\SHSDUDPHWHUVIRUSDUDPH
WHUL]HGW\SHVQRWSDUDPHWHUL]HGPHWKRGVEHFDXVHWKHDQQRWDWLRQVDIIHFWWKHEHKDYLRU
RI VXEW\SLQJ 0HWKRGV DUHQ¦W VXEW\SHG EXW WKH W\SHV WKDW FRQWDLQ WKHP PLJKW EH
VXEW\SHG

7KH+YDULDQFHDQQRWDWLRQPHDQVWKHSDUDPHWHUL]HGW\SHLVFRYDULDQWLQ
WKHW\SHSDUDPHWHU7KH-YDULDQFHDQQRWDWLRQPHDQVWKHSDUDPHWHUL]HG
W\SH LV FRQWUDYDULDQW LQ WKH W\SH SDUDPHWHU 1R YDULDQFH DQQRWDWLRQ
PHDQVWKHSDUDPHWHUL]HGW\SHLVLQYDULDQWLQWKHW\SHSDUDPHWHU

)LQDOO\WKHFRPSLOHUFKHFNV\RXUXVHRIYDULDQFHDQQRWDWLRQVIRUSUREOHPVOLNHWKHRQH
ZHMXVWGHVFULEHGLQWKHODVWOLQHVRIWKHH[DPSOHV6XSSRVH\RXDWWHPSWHGWRGHILQH
\RXURZQIXQFWLRQW\SHWKLVZD\
trait MyFunction2[+T1, +T2, -R] {
def apply(v1:T1, v2:T2): R = { ... }
...
}

254 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
7KHFRPSLOHUZRXOGWKURZWKHIROORZLQJHUURUVIRUWKHapplyPHWKRG
... error: contravariant type R occurs in covariant position in type (T1,T2)R
def apply(v1:T1, v2:T2):R
^
... error: covariant type T1 occurs in contravariant position in type T1 ...
def apply(v1:T1, v2:T2):R
^
... error: covariant type T2 occurs in contravariant position in type T2 ...
def apply(v1:T1, v2:T2):R
^

Variance of Mutable Types


$OOWKHSDUDPHWHUL]HGW\SHVZH¦YHGLVFXVVHGVRIDUKDYHEHHQLPPXWDEOHW\SHV:KDW
DERXWWKHYDULDQFHEHKDYLRURIPXWDEOHW\SHV"7KHVKRUWDQVZHULVWKDWRQO\LQYDUL
DQFHLVDOORZHG&RQVLGHUWKLVH[DPSOH
// code-examples/TypeSystem/variances/mutable-type-variance-script.scala
// WON'T COMPILE: Mutable parameterized types can't have variance annotations

class ContainerPlus[+A](var value: A) // ERROR


class ContainerMinus[-A](var value: A) // ERROR

println( new ContainerPlus("Hello World!") )


println( new ContainerMinus("Hello World!") )

5XQQLQJWKLVVFULSWWKURZVWKHIROORZLQJHUURUV
... 4: error: covariant type A occurs in contravariant position in type A \
of parameter of setter value_=
class ContainerPlus[+A](var value: A) // ERROR
^
... 5: error: contravariant type A occurs in covariant position in type => A \
of method value
class ContainerMinus[-A](var value: A) // ERROR
^
two errors found

:HFDQPDNHVHQVHRIWKHVHHUURUVE\UHPHPEHULQJRXUGLVFXVVLRQRI FunctionNW\SH
YDULDQFHXQGHULQKHULWDQFHZKHUHWKHW\SHVRIWKHIXQFWLRQDUJXPHQWVDUHFRQWUDYDU
LDQW LH-T1 DQGWKHUHWXUQW\SHLVFRYDULDQW LH+R 
7KHSUREOHPZLWKDPXWDEOHW\SHLVWKDWDWOHDVWRQHRILWVILHOGVKDVWKHHTXLYDOHQWRI
UHDGDQGZULWHRSHUDWLRQVHLWKHUWKURXJKGLUHFWDFFHVVRUWKURXJKDFFHVVRUPHWKRGV
,QWKHILUVWHUURUZHDUHWU\LQJWRXVHDFRYDULDQWW\SHDVDQDUJXPHQWWRDVHWWHU ZULWH
PHWKRGEXWZHVDZIURPRXUGLVFXVVLRQRIIXQFWLRQW\SHVWKDWDUJXPHQWW\SHVWRD
PHWKRGPXVWEHFRQWUDYDULDQW$FRYDULDQWW\SHLVILQHIRUWKHJHWWHU UHDG PHWKRG
6LPLODUO\IRUWKHVHFRQGHUURUZHDUHWU\LQJWRXVHDFRQWUDYDULDQWW\SHDVWKHUHWXUQ
YDOXHRIDUHDGPHWKRGZKLFKPXVWEHFRYDULDQW)RUWKHZULWHPHWKRGWKHFRQWUD
YDULDQWW\SHLVILQH

Variance Under Inheritance | 255

Download at WoweBook.Com
+HQFHWKHFRPSLOHUZRQ¦WOHWXVXVHDYDULDQFHDQQRWDWLRQRQDW\SHWKDWLVXVHGIRUD
PXWDEOHILHOG)RUWKLVUHDVRQDOOWKHPXWDEOHSDUDPHWHUL]HGW\SHVLQWKH6FDODOLEUDU\
DUHLQYDULDQWLQWKHLUW\SHSDUDPHWHUV6RPHRIWKHPKDYHFRUUHVSRQGLQJLPPXWDEOH
W\SHVWKDWKDYHFRYDULDQWRUFRQWUDYDULDQWSDUDPHWHUV

Variance In Scala Versus Java


$VZHVDLGWKHYDULDQFHEHKDYLRULVGHILQHGDWWKHGHFODUDWLRQVLWHLQ6FDOD,Q-DYDLW
LVGHILQHGDWWKHFDOOVLWH7KHFOLHQWRIDW\SHGHILQHVWKHYDULDQFHEHKDYLRUGHVLUHG VHH
>1DIWDOLQ@  ,Q RWKHU ZRUGV ZKHQ \RX XVH D -DYD JHQHULF DQG VSHFLI\ WKH W\SH
SDUDPHWHU\RXDOVRVSHFLI\WKHYDULDQFHEHKDYLRU LQFOXGLQJLQYDULDQFHZKLFKLVWKH
GHIDXOW <RXFDQ¦WVSHFLI\YDULDQFHEHKDYLRUDWWKHGHILQLWLRQVLWHLQ-DYDDOWKRXJK\RX
FDQXVHH[SUHVVLRQVWKDWORRNVLPLODU7KRVHH[SUHVVLRQVGHILQH W\SHERXQGVZKLFK
ZH¦OOGLVFXVVVKRUWO\
,Q -DYD YDULDQFH VSHFLILFDWLRQV D ZLOGFDUG ? DOZD\V DSSHDUV EHIRUH WKH super RU
extendsNH\ZRUGDVVKRZQHDUOLHULQ7DEOH:KHQZHVDLGDIWHUWKHWDEOHWKDWWKH
£-DYD(TXLYDOHQW¤FROXPQLVDELWPLVOHDGLQJZHZHUHUHIHUULQJWRWKHGLIIHUHQFHVEH
WZHHQGHFODUDWLRQYHUVXVFDOOVLWHVSHFLILFDWLRQV7KHUHLVDQRWKHUZD\LQZKLFKWKH6FDOD
DQG-DYDEHKDYLRUVGLIIHUZKLFKZH¦OOFRYHULQ£([LVWHQWLDO7\SHV¤RQSDJH
$GUDZEDFNRIFDOOVLWHYDULDQFHVSHFLILFDWLRQVLVWKDWWKH\IRUFHWKHXVHUVRI-DYDJH
QHULFVWRXQGHUVWDQGWKHW\SHV\VWHPPRUHWKRURXJKO\WKDQLVQHFHVVDU\IRUXVHUVRI
6FDODSDUDPHWHUL]HGW\SHVZKRGRQ¦WQHHGWRVSHFLI\WKLVEHKDYLRUZKHQXVLQJSDUD
PHWHUL]HGW\SHV 6FDODXVHUVDOVREHQHILWJUHDWO\IURPW\SHLQIHUHQFH
/HW¦V ORRN DW D -DYD H[DPSOH D VLPSOLILHG -DYD YHUVLRQ RI 6FDOD¦V Option Some DQG
NoneW\SHV
// code-examples/TypeSystem/variances/Option.java

package variances;

abstract public class Option<T> {


abstract public boolean isEmpty();

abstract public T get();

public T getOrElse(T t) {
return isEmpty() ? t : get();
}
}
// code-examples/TypeSystem/variances/Some.java

package variances;

public class Some<T> extends Option<T> {

public Some(T value) {


this.value = value;

256 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
}

public boolean isEmpty() { return false; }

private T value;

public T get() { return value; }

public String toString() {


return "Option(" + value + ")";
}
}
// code-examples/TypeSystem/variances/None.java

package variances;

public class None<T> extends Option<T> {

public boolean isEmpty() { return true; }

public T get() { throw new java.util.NoSuchElementException(); }

public String toString() {


return "None";
}
}

+HUHLVDQH[DPSOHWKDWXVHVWKLV-DYDOptionKLHUDUFK\
// code-examples/TypeSystem/variances/OptionExample.java

package variances;
import java.io.*;
import shapes.*; // From "Introducing Scala" chapter

public class OptionExample {


static String[] shapeNames = {"Rectangle", "Circle", "Triangle", "Unknown"};
static public void main(String[] args) {

Option<? extends Shape> shapeOption =


makeShape(shapeNames[0], new Point(0.,0.), 2., 5.);
print(shapeNames[0], shapeOption);

shapeOption = makeShape(shapeNames[1], new Point(0.,0.), 2.);


print(shapeNames[1], shapeOption);

shapeOption = makeShape(shapeNames[2],
new Point(0.,0.), new Point(2.,0.), new Point(0.,2.));
print(shapeNames[2], shapeOption);

shapeOption = makeShape(shapeNames[3]);
print(shapeNames[3], shapeOption);
}

static public Option<? extends Shape> makeShape(String shapeName,

Variance Under Inheritance | 257

Download at WoweBook.Com
Object... args) {
if (shapeName == shapeNames[0])
return new Some<Rectangle>(new Rectangle((Point) args[0],
(Double) args[1], (Double) args[2]));
else if (shapeName == shapeNames[1])
return new Some<Circle>(new Circle((Point) args[0], (Double) args[1]));
else if (shapeName == shapeNames[2])
return new Some<Triangle>(new Triangle((Point) args[0],
(Point) args[1], (Point) args[2]));
else
return new None<Shape>();
}

static void print(String name, Option<? extends Shape> shapeOption) {


System.out.println(name + "? " + shapeOption);
}
}

OptionExample.mainXVHVWKH ShapeKLHUDUFK\IURP&KDSWHUEXWZHKDYHXSGDWHGLW
VOLJKWO\WRH[SORLWIHDWXUHVWKDWZH¦YHOHDUQHGVLQFHWKHQVXFKDVcaseFODVVHV
// code-examples/TypeSystem/shapes/shapes.scala

package shapes {
case class Point(x: Double, y: Double) {
override def toString() = "Point(" + x + "," + y + ")"
}

abstract class Shape() {


def draw(): Unit
}

case class Circle(center: Point, radius: Double) extends Shape {


def draw() = println("Circle.draw: " + this)
}

case class Rectangle(lowerLeft: Point, height: Double, width: Double)


extends Shape {
def draw() = println("Rectangle.draw: " + this)
}

case class Triangle(point1: Point, point2: Point, point3: Point)


extends Shape() {
def draw() = println("Triangle.draw: " + this)
}
}

5XQQLQJ OptionExample ZLWK scala -cp ... variances.OptionExample SURGXFHV WKH


IROORZLQJRXWSXW
Rectangle? Option(Rectangle(Point(0.0,0.0),2.0,5.0))
Circle? Option(Circle(Point(0.0,0.0),2.0))
Triangle? Option(Triangle(Point(0.0,0.0),Point(2.0,0.0),Point(0.0,2.0)))
Unknown? None

258 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
%\WKHZD\ZHDUHDOVRGHPRQVWUDWLQJ6FDOD-DYDLQWHURSHUDELOLW\ZKLFKZH¦OOUHYLVLW
LQ£-DYD,QWHURSHUDELOLW\¤RQSDJH
OptionExample.mainFDOOVWKHVWDWLFIDFWRU\PHWKRGmakeShapeZKRVHDUJXPHQWVDUHWKH
QDPH RI D JHRPHWULF VKDSH DQG D YDULDEOH OHQJWK OLVW RI SDUDPHWHUV WR SDVV WR WKH
ShapeFRQVWUXFWRUV
1RWH WKDW makeShape UHWXUQV Option<? extends Shape> DQG ZKHQ ZH LQVWDQWLDWH D
ShapeZHUHWXUQDSomeSDUDPHWHUL]HGZLWKWKHShapeVXEW\SHLWZUDSV,IDQXQNQRZQ
VKDSHQDPHLVSDVVHGLQWKHQZHUHWXUQDNone<Shape>:HPXVWSDUDPHWHUL]HDNone
LQVWDQFHZLWK Shape%HFDXVH6FDODGHILQHVDVXEW\SHRIDOOW\SHV Nothing6FDODFDQ
GHILQHNoneDVcase object None extends Option[Nothing]
7KH-DYDW\SHV\VWHPSURYLGHVQRZD\WRLPSOHPHQWRXU-DYD NoneLQDVLPLODUZD\
+DYLQJDVLQJOHWRQREMHFWNoneKDVDQXPEHURIDGYDQWDJHVLQFOXGLQJJUHDWHUHIILFLHQF\
EHFDXVHZHDUHQ¦WFUHDWLQJORWVRIOLWWOHREMHFWVDQGXQDPELJXRXVEHKDYLRURIequals
EHFDXVHZHGRQ¦WQHHGWRGHILQHWKHVHPDQWLFVRIHTXDOLW\EHWZHHQGLIIHUHQWW\SHLQ
VWDQWLDWLRQVRIRXU-DYDNone<?>W\SH¢IRUH[DPSOHNone<String>YHUVXVNone<Shape>
)LQDOO\ QRWH WKDW OptionExample D FOLHQW RI Option KDV WR VSHFLI\ W\SH YDULDQFH
Option<? extends Shape>LQVHYHUDOSODFHV,Q6FDODWKHFOLHQWGRHVQ¦WFDUU\WKLVEXUGHQ

Implementation Notes
7KHLPSOHPHQWDWLRQRISDUDPHWHUL]HGW\SHVDQGPHWKRGVLVZRUWKQRWLQJ7KHLPSOH
PHQWDWLRQVDUHJHQHUDWHGZKHQWKHGHILQLQJVRXUFHILOHLVFRPSLOHG)RUHDFKW\SHSD
UDPHWHUWKHLPSOHPHQWDWLRQDVVXPHVWKDW AnyVXEW\SHFRXOGEHVSHFLILHG ObjectLV
XVHGLQ-DYDJHQHULFV 7KHVHDVSHFWVKDYHSHUIRUPDQFHLPSOLFDWLRQVWKDWZHZLOOUHYLVLW
ZKHQZHGLVFXVVWKH@specializedDQQRWDWLRQLQ£$QQRWDWLRQV¤RQSDJH

Type Bounds
:KHQ GHILQLQJ D SDUDPHWHUL]HG W\SH RU PHWKRG LW PD\ EH QHFHVVDU\ WR VSHFLI\
ERXQGVRQWKHW\SH)RUH[DPSOHDSDUDPHWHUL]HGW\SHPLJKWDVVXPHWKDWDSDUWLFXODU
W\SHSDUDPHWHUFRQWDLQVFHUWDLQPHWKRGV

Upper Type Bounds


&RQVLGHUWKHRYHUORDGHGapplyPHWKRGVLQobject scala.ArrayWKDWFUHDWHQHZDUUD\V
7KHUHDUHRSWLPL]HGLPSOHPHQWDWLRQVIRUHDFKRIWKH AnyValW\SHV7KHUHLVDQRWKHU
LPSOHPHQWDWLRQ RI apply WKDW LV SDUDPHWHUL]HG IRU DQ\ W\SH WKDW LV D VXEW\SH RI
AnyRef+HUHLVWKHLPSOHPHQWDWLRQLQ6FDODYHUVLRQ
object Array {
...
def apply[A <: AnyRef](xs: A*): Array[A] = {
val array = new Array[A](xs.length)

Type Bounds | 259

Download at WoweBook.Com
var i = 0
for (x <- xs.elements) { array(i) = x; i += 1 }
array
}
...
}

7KHW\SHSDUDPHWHUA <: AnyRefPHDQV£DQ\W\SHAWKDWLVDVXEW\SHRI AnyRef¤1RWH


WKDWDW\SHLVDOZD\VDVXEW\SHDQGDVXSHUW\SHRILWVHOIVRAFRXOGDOVRHTXDOAnyRef
6RWKH<:RSHUDWRULQGLFDWHVWKDWWKHW\SHWRWKHOHIWPXVWEHGHULYHGIURPWKHW\SHWR
WKH ULJKW RU WKDW WKH\ PXVW EH WKH VDPH W\SH $V ZH VDLG LQ £5HVHUYHG
:RUGV¤RQSDJHWKLVRSHUDWRULVDFWXDOO\DUHVHUYHGZRUGLQWKHODQJXDJH
7KHVH ERXQGV DUH FDOOHG XSSHU W\SH ERXQGV IROORZLQJ WKH GH IDFWR FRQYHQWLRQ WKDW
GLDJUDPVRIW\SHKLHUDUFKLHVSXWVXEW\SHVEHORZWKHLUVXSHUW\SHV:HIROORZHGWKLV
FRQYHQWLRQLQWKHGLDJUDPVKRZQLQ£7KH6FDOD7\SH+LHUDUFK\¤RQSDJH
:LWKRXW WKH ERXQG LQ WKLV FDVH LH LI WKH VLJQDWXUH ZHUH def apply[A](xs: A*):
Array[A]WKHGHFODUDWLRQZRXOGEHDPELJXRXVZLWKWKHRWKHUapplyPHWKRGVIRUHDFK
RIWKHAnyValW\SHV

7KHW\SHVLJQDWXUHA <: BVD\VWKDWAPXVWEHDVXEW\SHRIB,Q-DYDWKLV


ZRXOGEHH[SUHVVHGDVA extends BLQDW\SHGHFODUDWLRQ7KLVLVGLIIHUHQW
IURPLQVWDQWLDWLQJDW\SHDWDFDOOVLWHZKHUHWKHV\QWD[ ? extends BLV
XVHGLQ-DYDLQGLFDWLQJWKHYDULDQFHEHKDYLRU

.HHSLQPLQGWKHGLVWLQFWLRQEHWZHHQW\SHYDULDQFHDQGW\SHERXQGV)RUDW\SHOLNH
List WKH YDULDQFH EHKDYLRU GHVFULEHV KRZ DFWXDO W\SHV LQVWDQWLDWHG IURP LW OLNH
List[AnyRef]DQG List[String]DUHUHODWHG,QWKLVFDVH List[String]LVDVXEW\SHRI
List[AnyRef]VLQFHStringLVDVXEW\SHRIAnyRef
,QFRQWUDVWORZHUDQGXSSHUW\SHERXQGVOLPLWWKHDOORZHGW\SHVWKDWFDQEHXVHGIRU
DW\SHSDUDPHWHUZKHQLQVWDQWLDWLQJDW\SHIURPDSDUDPHWHUL]HGW\SH)RUH[DPSOH
def apply[A <: AnyRef]...VD\VWKDWDQ\W\SHXVHGIRUAPXVWEHDVXEW\SHRIAnyRef

Lower Type Bounds


6LPLODUO\ WKHUH DUH FLUFXPVWDQFHV ZKHQ ZH PLJKW ZDQW WR H[SUHVV WKDW RQO\ super
typesRIDSDUWLFXODUW\SHDUHDOORZHG 5HFDOOWKDWDW\SHLVDOVRDVXSHUW\SHRILWVHOI
:HFDOOWKHVHORZHUW\SHERXQGVDJDLQEHFDXVHWKHDOORZHGW\SHZRXOGEHDERYHWKH
ERXQGDU\LQDW\SLFDOW\SHKLHUDUFK\GLDJUDP
$SDUWLFXODUO\LQWHUHVWLQJH[DPSOHLVWKH:: £FRQV¤ PHWKRGLQFODVVList[+A]5HFDOO
WKDWWKLVRSHUDWRULVXVHGWRFUHDWHDQHZOLVWE\SUHSHQGLQJDQHOHPHQWWRDOLVW
class List[+A] {
...
def ::[B >: A](x : B) : List[B] = new scala.::(x, this)

260 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
...
}

7KHQHZOLVWZLOOEHRIW\SH List[B]VSHFLILFDOO\D scala.::7KH ::FODVV DVRSSRVHG


WRWKH::PHWKRG LVGHULYHGIURPList:H¦OOFRPHEDFNWRLWLQDPRPHQW
7KH::PHWKRGFDQSUHSHQGDQREMHFWRIDGLIIHUHQWW\SHIURPAWKHW\SHRIWKHHOHPHQWV
LQWKHRULJLQDOOLVW7KHFRPSLOHUZLOOLQIHUWKHFORVHVWFRPPRQVXSHUW\SHIRUADQGWKH
SDUDPHWHUx,WZLOOXVHWKDWVXSHUW\SHDVB+HUH¦VDQH[DPSOHWKDWSUHSHQGVDGLIIHUHQW
W\SHRIREMHFWRQDOLVW
// code-examples/TypeSystem/bounds/list-ab-script.scala

val languages = List("Scala", "Java", "Ruby", "C#", "C++", "Python")


val list = 3.14 :: languages
println(list)

7KHVFULSWSULQWVWKHIROORZLQJRXWSXW
List(3.14, Scala, Java, Ruby, C#, C++, Python)

7KHQHZOLVWRIW\SH List[Any]VLQFH AnyLVWKHFORVHVWFRPPRQVXSHUW\SHRI String


DQG Double:HVWDUWHGZLWKDOLVWRI StringsVR AZDV String7KHQZHSUHSHQGHGD
DoubleVRWKHFRPSLOHULQIHUUHGBWREHAnyWKHFORVHVW DQGRQO\ FRPPRQVXSHUW\SH

7KHW\SHVLJQDWXUHB >: AVD\VWKDWBPXVWEHDVXSHUW\SHRIA7KHUHLV


QRDQDORJLQ-DYDB super ALVQRWVXSSRUWHG

A Closer Look at Lists


3XWWLQJWKHVHIHDWXUHVWRJHWKHULW¦VZRUWKORRNLQJDWWKHLPSOHPHQWDWLRQRIWKH List
FODVVLQWKH6FDODOLEUDU\,WLOOXVWUDWHVVHYHUDOXVHIXOLGLRPVIRUIXQFWLRQDOVW\OHLP
PXWDEOHGDWDVWUXFWXUHVWKDWDUHIXOO\W\SHVDIH\HWIOH[LEOH:HZRQ¦WVKRZWKHHQWLUH
LPSOHPHQWDWLRQDQGZH¦OORPLWWKHobject ListPDQ\PHWKRGVLQWKHListFODVVDQG
WKHFRPPHQWVWKDWDUHXVHGWRJHQHUDWHWKH6FDODGRFV:HHQFRXUDJH\RXWRORRNDW
WKHFRPSOHWHLPSOHPHQWDWLRQRI ListHLWKHUE\GRZQORDGLQJWKHVRXUFHGLVWULEXWLRQ
IURPWKH6FDODZHEVLWHRUE\EURZVLQJWRWKHLPSOHPHQWDWLRQWKURXJKWKH6FDODGRFV
SDJHIRU List7RDYRLGFRQIXVLRQZLWK scala.ListZH¦OOXVHRXURZQSDFNDJHDQG
QDPHAbbrevList
// code-examples/TypeSystem/bounds/abbrev-list.scala
// Adapted from scala/List.scala in the Scala version 2.7.5 distribution.

package bounds.abbrevlist

sealed abstract class AbbrevList[+A] {

def isEmpty: Boolean


def head: A

Type Bounds | 261

Download at WoweBook.Com
def tail: AbbrevList[A]

def ::[B >: A] (x: B): AbbrevList[B] = new bounds.abbrevlist.::(x, this)

final def foreach(f: A => Unit) = {


var these = this
while (!these.isEmpty) {
f(these.head)
these = these.tail
}
}
}

// The empty AbbrevList.

case object AbbrevNil extends AbbrevList[Nothing] {


override def isEmpty = true

def head: Nothing =


throw new NoSuchElementException("head of empty AbbrevList")

def tail: AbbrevList[Nothing] =


throw new NoSuchElementException("tail of empty AbbrevList")
}

// A non-empty AbbrevList characterized by a head and a tail.

final case class ::[B](private var hd: B,


private[abbrevlist] var tl: AbbrevList[B]) extends AbbrevList[B] {

override def isEmpty: Boolean = false


def head : B = hd
def tail : AbbrevList[B] = tl
}

1RWLFHWKDWZKLOHAbbrevListLVLPPXWDEOHWKHLQWHUQDOLPSOHPHQWDWLRQXVHVPXWDEOH
YDULDEOHVHJLQforEach
7KHUHDUHWKUHHW\SHVGHILQHGIRUPLQJDVHDOHGKLHUDUFK\ AbbrevList WKHDQDORJRI
List LVDQDEVWUDFWWUDLWWKDWGHFODUHVWKUHHDEVWUDFWPHWKRGVisEmptyheadDQGtail
,WGHILQHVWKH£FRQV¤RSHUDWRU :: DQGDforeachPHWKRG$OOWKHRWKHUPHWKRGVIRXQG
LQ List FRXOG EH LPSOHPHQWHG ZLWK WKHVH PHWKRGV DOWKRXJK VRPH PHWKRGV OLNH
List.length XVHGLIIHUHQWLPSOHPHQWDWLRQRSWLRQVIRUHIILFLHQF\
AbbrevNilLVWKHDQDORJRINil,WLVDFDVHREMHFWWKDWH[WHQGVAbbrevList[Nothing],W
UHWXUQV trueIURP isEmptyDQGLWWKURZVDQH[FHSWLRQIURP headDQG tail%HFDXVH
AbbrevNil DQGNil KDYHHVVHQWLDOO\QRVWDWHDQGEHKDYLRUKDYLQJDQREMHFWUDWKHUWKDQ
DFODVVHOLPLQDWHVXQQHFHVVDU\FRSLHVPDNHVequalsIDVWDQGVLPSOHHWF
7KH ::FODVVLVWKHDQDORJRI scala.::GHULYHGIURP List,WLVGHFODUHGILQDO,WVDUJX
PHQWVDUHWKHHOHPHQWWREHFRPHWKHheadRIWKHQHZOLVWDQGDQH[LVWLQJOLVWZKLFKZLOO
EHWKH tailRIWKHQHZOLVW1RWHWKDWWKHVHYDOXHVDUHVWRUHGGLUHFWO\DVILHOGV7KH

262 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
headDQGtailPHWKRGVGHILQHGLQAbbrevListDUHMXVWUHDGHUPHWKRGVIRUWKHVHILHOGV
7KHUHLVQRRWKHUGDWDVWUXFWXUHUHTXLUHGWRUHSUHVHQWWKHOLVW
7KLVLVZK\SUHSHQGLQJDQHZHOHPHQWWRFUHDWHDQHZOLVWLVDQ2  RSHUDWLRQ7KH
List FODVV DOVR KDV D GHSUHFDWHG PHWKRG + IRU FUHDWLQJ D QHZ OLVW E\ DSSHQGLQJ DQ
HOHPHQWWRWKHHQGRIDQH[LVWLQJOLVW7KDWRSHUDWLRQLV2 1 ZKHUH1LVWKHOHQJWKRI
WKHOLVW
$V\RXEXLOGXSQHZOLVWVE\SUHSHQGLQJHOHPHQWVWRRWKHUOLVWVDQHVWHGKLHUDUFK\
RI::LQVWDQFHVLVFUHDWHG%HFDXVHWKHOLVWVDUHLPPXWDEOHWKHUHDUHQRFRQFHUQVDERXW
FRUUXSWLRQLIRQHRIWKH::LVFKDQJHGLQVRPHZD\
<RXFDQVHHWKLVQHVWLQJLI\RXSULQWRXWDOLVWH[SORLWLQJWKHtoStringPHWKRGJHQHUDWHG
EHFDXVHRIWKHcaseNH\ZRUG+HUHLVDQH[DPSOHscalaVHVVLRQ
$ scala -cp ...
Welcome to Scala version 2.7.5.final ...
Type in expressions to have them evaluated.
Type :help for more information.

scala> import bounds.abbrevlist._


import bounds.abbrevlist._

scala> 1 :: 2 :: 3 :: AbbrevNil
res1: bounds.abbrevlist.AbbrevList[Int] = ::(1,::(2,::(3,AbbrevNil)))

1RWHWKHRXWSXWRQWKHODVWOLQHZKLFKVKRZVWKHQHVWLQJRI(head,tail)HOHPHQWV
)RUDQRWKHUH[DPSOHXVLQJVLPLODUDSSURDFKHVWKLVWLPHIRUGHILQLQJDVWDFNUHIHUWR
KWWSZZZVFDODODQJRUJQRGH

Views and View Bounds


:H¦YHVHHQPDQ\H[DPSOHVZKHUHDQ implicitPHWKRGZDVXVHGWRFRQYHUWRQHW\SH
WRDQRWKHU¢IRUH[DPSOHWRJLYHWKHDSSHDUDQFHRIDGGLQJQHZPHWKRGVWRDQH[LVWLQJ
W\SHWKHVRFDOOHG3LPS0\/LEUDU\SDWWHUQ:HXVHGWKLVSDWWHUQH[WHQVLYHO\LQ&KDS
WHU<RXFDQDOVRXVHIXQFWLRQYDOXHVWKDWKDYHWKH implicitNH\ZRUG:H¦OOVHH
H[DPSOHVRIERWKVKRUWO\
$YLHZLVDQLPSOLFLWYDOXHRIIXQFWLRQW\SHWKDWFRQYHUWVDW\SHAWRB7KHIXQFWLRQKDV
WKHW\SHA => BRU(=> A) => B UHFDOOWKDW(=> A)LVDE\QDPHSDUDPHWHU $QLQVFRSH
LPSOLFLWPHWKRGZLWKWKHVDPHVLJQDWXUHFDQDOVREHXVHGDVDYLHZHJDQLPSOLFLW
PHWKRGLPSRUWHGIURPDQ object7KHWHUPYLHZFRQYH\VWKHVHQVHRIKDYLQJDYLHZ
IURPRQHW\SH A WRDQRWKHUW\SH B 
$YLHZLVDSSOLHGLQWZRFLUFXPVWDQFHV
 :KHQDW\SHALVXVHGLQDFRQWH[WZKHUHDQRWKHUW\SHBLVH[SHFWHGDQGWKHUHLVD
YLHZLQVFRSHWKDWFDQFRQYHUWAWRB

Type Bounds | 263

Download at WoweBook.Com
 :KHQDQRQH[LVWHQWPHPEHUmRIDW\SHALVUHIHUHQFHGEXWWKHUHLVDQLQVFRSH
YLHZWKDWFDQFRQYHUWAWRDBWKDWKDVWKHmPHPEHU
$FRPPRQH[DPSOHRIWKHVHFRQGFLUFXPVWDQFHLVWKHx -> yLQLWLDOL]DWLRQV\QWD[IRU
MapsZKLFKWULJJHUVLQYRFDWLRQRIPredef.anyToArrowAssoc(x)DVZHGLVFXVVHGLQ£7KH
3UHGHI2EMHFW¤RQSDJH
)RUDQH[DPSOHRIWKHILUVWFLUFXPVWDQFHPredefDOVRGHILQHVPDQ\YLHZVIRUFRQYHUWLQJ
EHWZHHQ AnyVal W\SHV DQG IRU FRQYHUWLQJ DQ AnyVal W\SH WR LWV FRUUHVSRQGLQJ
java.lang W\SH )RU H[DPSOH double2Double FRQYHUWV D scala.Double WR D
java.lang.Double
$YLHZERXQGLQDW\SHGHFODUDWLRQLVLQGLFDWHGZLWKWKH <%NH\ZRUGHJ A <% B,W
DOORZVDQ\W\SHWREHXVHGIRUALILWFDQEHFRQYHUWHGWRBXVLQJDYLHZ
$PHWKRGRUFODVVFRQWDLQLQJVXFKDW\SHSDUDPHWHULVWUHDWHGDVEHLQJHTXLYDOHQWWRD
FRUUHVSRQGLQJPHWKRGRUFODVVZLWKDQH[WUDDUJXPHQWOLVWZLWKRQHHOHPHQWDYLHZ
)RUH[DPSOHFRQVLGHUWKHIROORZLQJPHWKRGGHILQLWLRQZLWKDYLHZERXQG
def m [A <% B](arglist): R = ...

,WLVHIIHFWLYHO\WKHVDPHDVWKLVPHWKRGGHILQLWLRQ
def m [A](arglist)(implicit viewAB: A => B): R = ...

7KHLPSOLFLWSDUDPHWHUviewABZRXOGEHJLYHQDXQLTXHQDPHE\WKHFRPSLOHU 1RWH
WKDWZHKDYHDQDGGLWLRQDODUJXPHQWOLVWDVRSSRVHGWRDQDGGLWLRQDODUJXPHQWLQWKH
H[LVWLQJDUJXPHQWOLVW
:K\GRHVWKLVWUDQVIRUPDWLRQZRUN":HVDLGWKDWDYDOLGAPXVWKDYHDYLHZLQVFRSH
WKDW WUDQVIRUPV LW WR D B 7KH LPSOLFLW viewAB DUJXPHQW ZLOO JHW LQYRNHG LQVLGH m WR
FRQYHUWDOOALQVWDQFHVWRBLQVWDQFHVZKHUHQHHGHG
)RUWKLVWRZRUNWKHUHPXVWEHDYLHZRIWKHFRUUHFWW\SHLQVFRSHWRVDWLVI\WKHLPSOLFLW
DUJXPHQW<RXFRXOGDOVRSDVVDIXQFWLRQZLWKWKHFRUUHFWVLJQDWXUHH[SOLFLWO\DVWKH
VHFRQGDUJXPHQWOLVWZKHQ\RXFDOOm+RZHYHUWKHUHLVRQHVLWXDWLRQZKHUHWKLVZRQ¦W
ZRUNZKLFKZH¦OOGHVFULEHDIWHURXUXSFRPLQJH[DPSOH
)RUYLHZERXQGVRQW\SHVWKHLPSOLFLWYLHZDUJXPHQWOLVWZRXOGEHDGGHGWRWKHSUL
PDU\FRQVWUXFWRU

7UDLWVFDQ¦WKDYHYLHZERXQGVIRUWKHLUW\SHSDUDPHWHUVEHFDXVHWKH\
FDQ¦WKDYHFRQVWUXFWRUDUJXPHQWOLVWV

7RPDNHWKLVPRUHFRQFUHWHOHW¦VXVHYLHZERXQGVWRLPSOHPHQWD LinkedListFODVV
WKDWXVHVNodesZKHUHHDFKNodeKDVDpayloadDQGDUHIHUHQFHWRWKHQH[WNodeLQWKH
OLVW)LUVWKHUHLVDKLHUDUFK\RINodes

264 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
// code-examples/TypeSystem/bounds/node.scala

package bounds

abstract trait Node[+A] {


def payload: A
def next: Node[A]
}

case class ::[+A](val payload: A, val next: Node[A]) extends Node[A] {


override def toString =
String.format("(%s :: %s)", payload.toString, next.toString)
}

object NilNode extends Node[Nothing] {


def payload = throw new NoSuchElementException("No payload in NilNode")
def next = throw new NoSuchElementException("No next in NilNode")

override def toString = "*"


}

7KLVW\SHKLHUDUFK\LVPRGHOHGDIWHUListDQGAbbrevListHDUOLHU7KH::W\SHUHSUHVHQWV
LQWHUPHGLDWH QRGHV DQG NilNode LV DQDORJRXV WR Nil IRU Lists :H DOVR RYHUULGH
toStringWRJLYHXVFRQYHQLHQWRXWSXWZKLFKZH¦OOH[DPLQHVKRUWO\
7KHIROORZLQJVFULSWGHILQHVDLinkedListW\SHWKDWXVHVNodes
// code-examples/TypeSystem/bounds/view-bounds-script.scala

import bounds._

implicit def any2Node[A](x: A): Node[A] = bounds.::[A](x, NilNode)

case class LinkedList[A <% Node[A]](val head: Node[A]) {

def ::[B >: A <% Node[B]](x: Node[B]) =


LinkedList(bounds.::(x.payload, head))

override def toString = head.toString


}

val list1 = LinkedList(1)


val list2 = 2 :: list1
val list3 = 3 :: list2
val list4 = "FOUR!" :: list3

println(list1)
println(list2)
println(list3)
println(list4)

,WVWDUWVZLWKDGHILQLWLRQRIDSDUDPHWHUL]HGLPSOLFLWPHWKRGany2NodeWKDWFRQYHUWV
AWRNode[A],WZLOOEHXVHGDVWKHLPSOLFLWYLHZDUJXPHQWZKHQZHZRUNZLWKLinked
Lists,WFUHDWHVD£OHDI¤QRGHXVLQJDbounds.::QRGHZLWKDUHIHUHQFHWRNilNodeDVWKH
£QH[W¤HOHPHQWLQWKHOLVW

Type Bounds | 265

Download at WoweBook.Com
$QDOWHUQDWLYHZRXOGEHDIXQFWLRQYDOXHWKDWFRQYHUWVAnyWRNode[Any]
implicit val any2Node = (a: Any) => bounds.::[Any](a, NilNode)

2WKHUZLVHWKHVFULSWZRXOGUXQWKHVDPHH[FHSWWKDWVRPHRIWKHWHPSRUDU\OLVWVZRXOG
EHXVLQJNode[Any]UDWKHUWKDQNode[Int]
/RRNDWWKHGHFODUDWLRQRILinkedList
case class LinkedList[A <% Node[A]](val head: Node[A]) { ... }

,WGHILQHVDYLHZERXQGRQADQGWDNHVDVLQJOHDUJXPHQWWKHKHDGNodeRIWKHOLVW ZKLFK
PD\EHWKHKHDGRIDFKDLQRI Nodes $VZHVHHODWHULQWKHVFULSWHYHQWKRXJKWKH
FRQVWUXFWRU H[SHFWV D Node[A] DUJXPHQW ZH FDQ SDVV LW DQ A DQG WKH LPSOLFLW YLHZ
any2NodeZLOOJHWLQYRNHG7KHEHDXW\RIWKLVDSSURDFKLVWKDWDFOLHQWQHYHUKDVWRZRUU\
DERXWSURSHUFRQVWUXFWLRQRINodes7KHPDFKLQHU\KDQGOHVWKDWSURFHVVDXWRPDWLFDOO\
7KHFODVVDOVRKDVD£FRQV¤RSHUDWRU
def ::[B >: A <% Node[B]](x: Node[B]) = ...

7KHW\SHSDUDPHWHUPHDQVCCBLVORZHUERXQGHGE\ LHLVDVXSHUW\SHRI ADQGBDOVR


KDVDYLHZERXQGRIB <% Node[B]$VZHVDZIRUListDQGAbbrevListWKHORZHUERXQG
DOORZVXVWRSUHSHQGLWHPVRIGLIIHUHQWW\SHVIURPWKHRULJLQDOAW\SH7KLVPHWKRGZLOO
KDYH LWV RZQ LPSOLFLW YLHZ DUJXPHQW EXW RXU SDUDPHWHUL]HG LPSOLFLW PHWKRG
any2NodeZLOOEHXVHGIRUWKLVDUJXPHQWWRR
:HPHQWLRQHGSUHYLRXVO\WKDWLI\RXGRQ¦WKDYHDYLHZLQVFRSH\RXFRXOGSDVVD£QRQ
LPSOLFLW¤FRQYHUWHUDVWKHVHFRQGDUJXPHQWOLVWH[SOLFLWO\7KLVDFWXDOO\ZRQ¦WZRUNLQ
RXUH[DPSOHEHFDXVHWKHFRQVWUXFWRUDQG::PHWKRGLQLinkedListWDNHNode[A]DUJX
PHQWV EXW ZH FDOO WKHP ZLWK Ints DQG Strings :H ZRXOG KDYH WR FDOO WKHP ZLWK
Node[Int]DQGNode[String]DUJXPHQWVH[SOLFLWO\:HZRXOGDOVRKDYHWRLQYRNH::LQ
DQXJO\ZD\¢val list2 = list1.::(2)(converter)IRUH[DPSOH
/HW¦VFODULI\WKHV\QWD[DELW:KHQ\RXVHHB >: A <% Node[B]LW¦VWHPSWLQJWRDVVXPH
WKDWWKH<%VKRXOGDSSO\WRALQWKLVH[SUHVVLRQ,WDFWXDOO\DSSOLHVWRB7KHJUDPPDU
IRUW\SHSDUDPHWHUVLQFOXGLQJYLHZERXQGVLVWKHIROORZLQJ VHH>6FDOD6SHF@ 
TypeParam ::= (id | â~@~X_â~@~Y) [TypeParamClause] [â~@~X>:â~@~Y Type] [â~@~X<:â~@~Y Type] [â~@~X<%â~@~Y
TypeParamClause ::= â~@~X[â~@~Y VariantTypeParam {â~@~X,â~@~Y VariantTypeParam} â~@~X]â~@~Y
VariantTypeParam ::= [â~@~X+â~@~Y | â~@~Xâ~@~Y] TypeParam

6R\HV\RXFDQKDYHVRPHYHU\FRPSOH[KLHUDUFKLFDOW\SHV,QRXU::PHWKRGWKHidLV
BWKHTypeParamClauseLVHPSW\DQGZHKDYHWKH>: ADQG<% Node[B]H[SUHVVLRQVRQ
WKHULJKW$JDLQDOOWKHERXQGVH[SUHVVLRQVDSSO\WRWKHILUVWid B RUWKHXQGHUVFRUH
_ 
7KH XQGHUVFRUH LV XVHG IRU H[LVWHQWLDO W\SHV ZKLFK ZH¦OO FRYHU LQ £([LVWHQWLDO
7\SHV¤RQSDJH
)LQDOO\ZHFUHDWHDLinkedListLQWKHVFULSWSUHSHQGVRPHYDOXHVWRFUHDWHQHZOLVWV
DQGWKHQSULQWWKHPRXW

266 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
1 :: *
2 :: 1 :: *
3 :: 2 :: 1 :: *
FOUR! :: 3 :: 2 :: 1 :: *

7RUHFDSWKHYLHZERXQGVOHWXVZRUNZLWK£SD\ORDGV¤RIIntsDQGStringsZKLOHWKH
LPSOHPHQWDWLRQKDQGOHGWKHQHFHVVDU\FRQYHUVLRQVWRNodes
9LHZERXQGVDUHQRWXVHGDVRIWHQDVXSSHUDQGORZHUERXQGVEXWWKH\SURYLGHDQ
HOHJDQWPHFKDQLVPIRUWKRVHWLPHVZKHQDXWRPDWLFFRHUFLRQIURPRQHW\SHLQWRDQRWKHU
LVXVHIXO$VDOZD\VXVHLPSOLFLWVZLWKFDXWLRQLPSOLFLWFRQYHUVLRQVDUHIDUIURPRE
YLRXVZKHQUHDGLQJFRGHDQGGHEXJJLQJP\VWHULRXVEHKDYLRU

Nothing and Null


,Q£7KH6FDOD7\SH+LHUDUFK\¤RQSDJHZHPHQWLRQHGWKDWNullLVDVXEW\SHRIDOO
AnyRefW\SHVDQGNothingLVDVXEW\SHRIDOOW\SHVLQFOXGLQJNull
NullLVGHFODUHGDVDfinal trait VRLWFDQ¦WEHVXEW\SHG DQGLWKDVRQO\RQHLQVWDQFH
null6LQFHNullLVDVXEW\SHRIDOOAnyRefW\SHV\RXFDQDOZD\VDVVLJQnullDVDQLQVWDQFH
RIDQ\RIWKRVHW\SHV-DYDLQFRQWUDVWVLPSO\WUHDWV nullDVDNH\ZRUGZLWKVSHFLDO
KDQGOLQJE\WKHFRPSLOHU+RZHYHU-DYD¦VnullDFWXDOO\EHKDYHVDVLILWZHUHDVXEW\SH
RIDOOUHIHUHQFHW\SHVMXVWOLNH6FDOD¦VNull
2QWKHRWKHUKDQGVLQFH NullLVQRWDVXEW\SHRI AnyValLWLVQRWSRVVLEOHWRDVVLJQ
nullWRDQIntIRUH[DPSOHZKLFKLVDOVRFRQVLVWHQWZLWKWKHSULPLWLYHVHPDQWLFVLQ-DYD
NothingLVDOVRD final traitEXWLWKDVQRLQVWDQFHV+RZHYHULWLVVWLOOXVHIXOIRU
GHILQLQJW\SHV7KHEHVWH[DPSOHLVNilWKHHPSW\OLVWZKLFKLVDcase object,WLVRI
W\SHList[Nothing]%HFDXVHOLVWVDUHFRYDULDQWLQ6FDODDVZHVDZHDUOLHUWKLVPDNHV
NilDQLQVWDQFHRIList[T]IRUDQ\W\SH7:HDOVRH[SORLWHGWKLVIHDWXUHLQRXUAbbrev
ListDQGLinkedListLPSOHPHQWDWLRQV

Understanding Abstract Types


%HVLGHVSDUDPHWHUL]HGW\SHVZKLFKDUHFRPPRQLQVWDWLFDOO\W\SHGREMHFWRULHQWHG
ODQJXDJHV 6FDOD DOVR VXSSRUWV DEVWUDFW W\SHV ZKLFK DUH FRPPRQ LQ IXQFWLRQDO
ODQJXDJHV :H LQWURGXFHG DEVWUDFW W\SHV LQ £$EVWUDFW 7\SHV $QG 3DUDPHWHUL]HG
7\SHV¤RQSDJH
7KHVHWZRIHDWXUHVRYHUODSVRPHZKDW7HFKQLFDOO\\RXFRXOGLPSOHPHQWDOPRVWDOO
WKHLGLRPVWKDWSDUDPHWHUL]HGW\SHVVXSSRUWXVLQJDEVWUDFWW\SHVDQGYLFHYHUVD+RZ
HYHULQSUDFWLFHHDFKIHDWXUHLVDQDWXUDOILWIRUGLIIHUHQWGHVLJQSUREOHPV
5HFDOORXUYHUVLRQRIObserverWKDWXVHVDEVWUDFWW\SHVLQ&KDSWHU
// code-examples/AdvOOP/observer/observer2.scala

package observer

Understanding Abstract Types | 267

Download at WoweBook.Com
trait AbstractSubject {
type Observer

private var observers = List[Observer]()


def addObserver(observer:Observer) = observers ::= observer
def notifyObservers = observers foreach (notify(_))

def notify(observer: Observer): Unit


}

trait SubjectForReceiveUpdateObservers extends AbstractSubject {


type Observer = { def receiveUpdate(subject: Any) }

def notify(observer: Observer): Unit = observer.receiveUpdate(this)


}

trait SubjectForFunctionalObservers extends AbstractSubject {


type Observer = (AbstractSubject) => Unit

def notify(observer: Observer): Unit = observer(this)


}

AbstractSubjectGHFODUHVDW\SHObserverZLWKQRW\SHERXQGV,WLVGHILQHGLQWKHWZR
GHULYHG WUDLWV ,Q SubjectForReceiveUpdateObservers LW LV GHILQHG WR EH D VWUXFWXUDO
W\SH,QSubjectForFunctionalObserversLWLVGHILQHGWREHDIXQFWLRQW\SH:H¦OOKDYH
PRUHWRVD\DERXWVWUXFWXUDODQGIXQFWLRQW\SHVODWHULQWKLVFKDSWHU
:HFDQDOVRXVHW\SHERXQGVZKHQZHGHFODUHRUUHILQHWKHGHFODUDWLRQRIDEVWUDFW
W\SHV:HVDZDVLPSOHH[DPSOHSUHYLRXVO\LQ£7\SH3URMHFWLRQV¤RQSDJHZKHUH
ZHKDGDGHFODUDWLRQtype t <: AnyRef7KDWLVtKDGDQXSSHUW\SHERXQG VXSHUFODVV
RIAnyRefAnyValW\SHVZHUHQ¦WDOORZHG
:HFDQDOVRKDYHORZHUW\SHERXQGV VXEFODVVHV DQGZHFDQXVHPRVWRIWKHYDOXH
W\SHV VHH£9DOXH7\SHV¤RQSDJH LQWKHERXQGVH[SUHVVLRQV+HUHLVDQH[DPSOH
LOOXVWUDWLQJWKHPRVWFRPPRQRSWLRQV
// code-examples/TypeSystem/abstracttypes/abs-type-examples-script.scala

trait exampleTrait {
type t1 // Unconstrained
type t2 >: t3 <: t1 // t2 must be a supertype of t3 and a subtype of t1
type t3 <: t1 // t3 must be a subtype of t1
type t4 // Unconstrained
type t5 = List[t4] // List of t4, whatever t4 will eventually be...

val v1: t1 // Can't initialize until t1 defined.


val v3: t3 // etc.
val v2: t2 // ...
val v4: t4 // ...
val v5: t5 // ...
}

trait T1 { val name1: String }

268 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
trait T2 extends T1 { val name2: String }
class C(val name1: String, val name2: String) extends T2

object example extends exampleTrait {


type t1 = T1
type t2 = T2
type t3 = C
type t4 = Int

val v1 = new T1 { val name1 = "T1"}


val v3 = new C("C1", "C2")
val v2 = new T2 { val name1 = "T1"; val name2 = "T2" }
val v4 = 10
val v5 = List(1,2,3,4,5)
}

7KHFRPPHQWVH[SODLQPRVWRIWKHGHWDLOV7KHUHODWLRQVKLSVEHWZHHQ t1 t2DQG t3


KDYHVRPHLQWHUHVWLQJSRLQWV)LUVWWKHGHFODUDWLRQRIt2VD\VWKDWLWPXVWEH£EHWZHHQ¤
t1DQGt3:KDWHYHUt1EHFRPHVLWPXVWEHDVXSHUFODVVRIt2 RUHTXDOWRLW DQGt3
PXVWEHDVXEFODVVRIt2 RUHTXDOWRLW 
5HPHPEHUIURP£7\SH%RXQGV¤RQSDJHWKDWZHDUHPDNLQJDGHFODUDWLRQRIWKH
ILUVW W\SH DIWHU WKH type NH\ZRUG t2 QRW WKH W\SH LQ WKH PLGGOH t3 7KH UHVW RI
WKHH[SUHVVLRQLVWHOOLQJXVWKHERXQGVRIt2
&RQVLGHUWKHQH[WOLQHWKDWGHFODUHV t3WREHDVXEW\SHRI t1,I\RXZHUHWRRPLWWKH
W\SHERXQGWKHFRPSLOHUZRXOGWKURZDQHUURUEHFDXVH t3 <: t1LVLPSOLHGE\WKH
SUHYLRXVGHFODUDWLRQRIt27KDWGRHVQ¦WPHDQWKDW\RXFDQOHDYHRXWWKHGHFODUDWLRQRI
t3,WKDVWREHWKHUHEXWLWDOVRKDVWRVKRZDFRQVLVWHQWW\SHERXQGZLWKWKHRQH
LPSOLHGLQWKHt2GHFODUDWLRQ
:KHQZHUHYLVLWWKH2EVHUYHU3DWWHUQLQ£6HOI7\SH$QQRWDWLRQVDQG$EVWUDFW7\SH
0HPEHUV¤RQSDJHZH¦OOVHHDQRWKHUH[DPSOHRIW\SHERXQGVXVHGRQDEVWUDFW
W\SHV:H¦OOVHHDSUREOHPWKH\FDQFDXVHDORQJZLWKDQHOHJDQWVROXWLRQ
)LQDOO\DEVWUDFWW\SHVGRQ¦WKDYHYDULDQFHDQQRWDWLRQV
// code-examples/TypeSystem/abstracttypes/abs-type-variances-wont-compile.scala
// WON'T COMPILE

trait T1 { val name1: String }


trait T2 extends T1 { val name2: String }
class C(val name1: String, val name2: String) extends T2

trait T {
type t: +T1 // ERROR, no +/- type variance annotations
val v
}

5HPHPEHUWKDWWKHDEVWUDFWW\SHVDUHPHPEHUVRIWKHHQFORVLQJW\SHQRWW\SHSDUDP
HWHUVDVIRUSDUDPHWHUL]HGW\SHV7KHHQFORVLQJW\SHPD\KDYHDQLQKHULWDQFHUHODWLRQ
VKLS ZLWK RWKHU W\SHV EXW PHPEHU W\SHV EHKDYH MXVW OLNH PHPEHU PHWKRGV DQG
YDULDEOHV7KH\GRQ¦WDIIHFWWKHLQKHULWDQFHUHODWLRQVKLSVRIWKHLUHQFORVLQJW\SH/LNH

Understanding Abstract Types | 269

Download at WoweBook.Com
RWKHUPHPEHUVDEVWUDFWW\SHVFDQEHGHFODUHGDEVWUDFWRUFRQFUHWH+RZHYHUWKH\FDQ
DOVREHUHILQHGLQVXEW\SHVZLWKRXWEHLQJIXOO\GHILQHGXQOLNHYDULDEOHVDQGPHWKRGV
2IFRXUVHLQVWDQFHVFDQRQO\EHFUHDWHGZKHQWKHDEVWUDFWW\SHVDUHJLYHQFRQFUHWH
GHILQLWLRQV

Parameterized Types Versus Abstract Types


:KHQVKRXOG\RXXVHSDUDPHWHUL]HGW\SHVYHUVXVDEVWUDFWW\SHV"3DUDPHWHUL]HGW\SHV
DUHWKHPRVWQDWXUDOILWIRUSDUDPHWHUL]HGFRQWDLQHUW\SHVOLNHListDQGOption&RQVLGHU
WKHGHFODUDWLRQRISomeIURPWKHVWDQGDUGOLEUDU\
case final class Some[+A](val x : A) { ... }

,IZHWULHGWRFRQYHUWWKLVWRXVHDEVWUDFWW\SHVZHPLJKWVWDUWZLWKWKHIROORZLQJ
case final class Some(val x : ???) {
type A
...
}

:KDWVKRXOGEHWKHW\SHRIWKHILHOGx":HFDQ¦WXVHAEHFDXVHLW¦VQRWLQVFRSHDWWKH
SRLQW RI WKH FRQVWUXFWRU DUJXPHQW :H FRXOGXVH Any EXW WKDW GHIHDWV WKH YDOXH RI
KDYLQJDSSURSULDWHO\W\SHGGHFODUDWLRQV
,IDW\SHZLOOKDYHFRQVWUXFWRUDUJXPHQWVGHFODUHGXVLQJD£SODFHKROGHU¤W\SHWKDWKDV
QRW\HWEHHQGHILQHGWKHQSDUDPHWHUL]HGW\SHVDUHWKHRQO\JRRGVROXWLRQ VKRUWRI
XVLQJAnyRUAnyRef 
<RXFDQXVHDEVWUDFWW\SHVDVPHWKRGDUJXPHQWVDQGUHWXUQYDOXHVZLWKLQDIXQFWLRQ
+RZHYHU WZR SUREOHPV FDQ DULVH )LUVW \RX FDQ UXQ LQWR SUREOHPV ZLWK SDWK
GHSHQGHQWW\SHV GLVFXVVHGLQ£3DWK'HSHQGHQW7\SHV¤RQSDJH ZKHUHWKHFRP
SLOHUWKLQNV\RXDUHWU\LQJWRXVHDQLQFRPSDWLEOHW\SHLQDSDUWLFXODUFRQWH[WZKHQLQ
IDFWWKH\DUHSDWKVWRFRPSDWLEOHW\SHV6HFRQGLW¦VDZNZDUGWRH[SUHVVPHWKRGVOLNH
List.:: £FRQV¤ XVLQJDEVWUDFWW\SHVZKHUHW\SHFKDQJHV H[SDQVLRQLQWKLVFDVH FDQ
RFFXU
class List[+A] {
...
def ::[B >: A](x : B) : List[B] = new scala.::(x, this)
...
}

$OVRLI\RXZDQWWRH[SUHVVYDULDQFHXQGHULQKHULWDQFHWKDWLVWLHGWRWKHW\SHDEVWUDF
WLRQVWKHQSDUDPHWHUL]HGW\SHVZLWKYDULDQFHDQQRWDWLRQVPDNHWKHVHEHKDYLRUVREYL
RXVDQGH[SOLFLW
7KHVHOLPLWDWLRQVRIDEVWUDFWW\SHVUHDOO\UHIOHFWWKHWHQVLRQEHWZHHQREMHFWRULHQWHG
LQKHULWDQFH DQG WKH RULJLQ RI DEVWUDFW W\SHV LQ SXUH IXQFWLRQDO SURJUDPPLQJ W\SH
V\VWHPVZKLFKGRQ¦WKDYHLQKHULWDQFH3DUDPHWHUL]HGW\SHVDUHPRUHSRSXODULQREMHFW
RULHQWHG ODQJXDJHV EHFDXVH WKH\ KDQGOH LQKHULWDQFH PRUH QDWXUDOO\ LQ PRVW
FLUFXPVWDQFHV

270 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
2QWKHRWKHUKDQGVRPHWLPHVLW¦VXVHIXOWRUHIHUWRDW\SHDEVWUDFWLRQDVDPHPEHURI
DQRWKHUW\SHDVRSSRVHGWRDSDUDPHWHUXVHGWRFRQVWUXFWQHZW\SHVIURPDSDUDPH
WHUL]HGW\SH5HILQLQJDQDEVWUDFWW\SHGHFODUDWLRQWKURXJKDVHULHVRIHQFORVLQJW\SH
UHILQHPHQWVFDQEHTXLWHHOHJDQW
trait T1 {
type t
val v: t
}
trait T2 extends T1 {
type t <: SomeType1
}
trait T3 extends T2 {
type t <: SomeType2 // where SomeType2 <: SomeType1
}
class C extends T3 {
type t = Concrete // where Concrete <: SomeType2
val v = new Concrete(...)
}
...

7KLVH[DPSOHDOVRVKRZVWKDWDEVWUDFWW\SHVDUHRIWHQXVHGWRGHFODUHDEVWUDFWYDULDEOHV
RIWKHVDPHW\SH/HVVIUHTXHQWO\WKH\DUHXVHGIRUPHWKRGGHFODUDWLRQV
:KHQWKHDEVWUDFWYDULDEOHVDUHHYHQWXDOO\PDGHFRQFUHWHWKH\FDQHLWKHUEHGHILQHG
LQVLGHWKHW\SHERG\PXFKDVWKH\ZHUHRULJLQDOO\GHFODUHGRUWKH\FDQEHLQLWLDOL]HG
WKURXJKFRQVWUXFWRUDUJXPHQWV8VLQJFRQVWUXFWRUDUJXPHQWVOHWVWKHXVHUGHFLGHRQ
WKHDFWXDOYDOXHVZKLOHLQLWLDOL]LQJWKHPLQWKHERG\OHWVWKHW\SHGHVLJQHUGHFLGHRQ
WKHDSSURSULDWHYDOXH
:H XVHG FRQVWUXFWRU DUJXPHQWV LQ WKH EULHI BulkReader H[DPSOH ZH SUHVHQWHG LQ
£$EVWUDFW7\SHV$QG3DUDPHWHUL]HG7\SHV¤RQSDJH
// code-examples/TypeLessDoMore/abstract-types-script.scala

import java.io._

abstract class BulkReader {


type In
val source: In
def read: String
}

class StringBulkReader(val source: String) extends BulkReader {


type In = String
def read = source
}

class FileBulkReader(val source: File) extends BulkReader {


type In = File
def read = {
val in = new BufferedInputStream(new FileInputStream(source))
val numBytes = in.available()
val bytes = new Array[Byte](numBytes)

Understanding Abstract Types | 271

Download at WoweBook.Com
in.read(bytes, 0, numBytes)
new String(bytes)
}
}

println( new StringBulkReader("Hello Scala!").read )


println( new FileBulkReader(new File("abstract-types-script.scala")).read )

,I\RXFRPHIURPDQREMHFWRULHQWHGEDFNJURXQG\RXZLOOQDWXUDOO\WHQGWRXVHSDUD
PHWHUL]HGW\SHVPRUHRIWHQWKDQDEVWUDFWW\SHV7KH6FDODVWDQGDUGOLEUDU\WHQGVWR
HPSKDVL]HSDUDPHWHUL]HGW\SHVWRR6WLOO\RXVKRXOGOHDUQWKHPHULWVRIDEVWUDFWW\SHV
DQGXVHWKHPZKHQWKH\PDNHVHQVH

Path-Dependent Types
/DQJXDJHVWKDWOHW\RXQHVWW\SHVSURYLGHZD\VWRUHIHUWRWKRVHW\SHSDWKV6FDODSUR
YLGHVDULFKV\QWD[IRUSDWKGHSHQGHQWW\SHV$OWKRXJK\RXZLOOSUREDEO\XVHWKHP
UDUHO\LW¦VXVHIXOWRXQGHUVWDQGWKHEDVLFVDVFRPSLOHUHUURUVRIWHQFRQWDLQW\SHSDWKV
&RQVLGHUWKHIROORZLQJH[DPSOH
// code-examples/TypeSystem/typepaths/type-path-wont-compile.scala
// ERROR: Won't compile

trait Service {
trait Logger {
def log(message: String): Unit
}
val logger: Logger

def run = {
logger.log("Starting " + getClass.getSimpleName + ":")
doRun
}

protected def doRun: Boolean


}

object MyService1 extends Service {


class MyService1Logger extends Logger {
def log(message: String) = println("1: "+message)
}
override val logger = new MyService1Logger
def doRun = true // do some real work...
}

object MyService2 extends Service {


override val logger = MyService1.logger // ERROR
def doRun = true // do some real work...
}

272 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
,I\RXFRPSLOHWKLVILOH\RXJHWWKHIROORZLQJHUURU
...:27: error: error overriding value logger in trait Service of type \
MyService2.Logger;
value logger has incompatible type MyService1.MyService1Logger
override val logger = MyService1.logger // ERROR
^
one error found

7KH HUURU VD\V WKDW WKH logger YDOXH LQ MyService2 RQ OLQH  KDV W\SH MySer
vice2.LoggerHYHQWKRXJKLW¦VGHFODUHGWREHRIW\SHLoggerLQWKHSDUHQWServiceWUDLW
$OVRZH¦UHWU\LQJWRDVVLJQLWDYDOXHRIW\SHMyService1.MyService1Logger
7KHVHWKUHHW\SHVDUHGLIIHUHQWLQ6FDODLoggerLVQHVWHGLQServiceZKLFKLVWKHSDUHQW
RIMyService1DQGMyService2,Q6FDODWKDWPHDQVWKDWWKHQHVWHGLoggerW\SHLVXQLTXH
IRUHDFKRIWKHVHUYLFHW\SHV7KHDFWXDOW\SHLVSDWKGHSHQGHQW
,Q WKLV FDVH WKH HDVLHVW VROXWLRQ LV WR PRYH WKH GHFODUDWLRQ RI Logger RXWVLGH RI
ServiceWKHUHE\UHPRYLQJWKHSDWKGHSHQGHQF\,QRWKHUFDVHVLW¦VSRVVLEOHWRTXDOLI\
WKHW\SHVRWKDWLWUHVROYHVWRZKDW\RXZDQW
7KHUHDUHVHYHUDONLQGVRIW\SHSDWKV

C.this
)RUDFODVVC\RXFDQXVHC.thisRUthisLQVLGHWKHERG\WRUHIHUWRWKHFXUUHQWLQVWDQFH
class C1 {
var x = "1"
def setX1(x:String) = this.x = x
def setX2(x:String) = C1.this.x = x
}

%RWKsetX1DQGsetX2KDYHWKHVDPHHIIHFWEHFDXVHC1.thisLVHTXLYDOHQWWRthis
,QVLGHDW\SHERG\DQGRXWVLGHDPHWKRGGHILQLWLRQthisUHIHUVWRWKHW\SHLWVHOI
trait T1 {
class C
val c1 = new C
val c2 = new this.C
}

7KHYDOXHV c1DQG c2KDYHWKHVDPHW\SH7KH thisLQWKHH[SUHVVLRQ this.CUHIHUVWR


WKHWUDLWT1

C.super
<RXFDQUHIHUVSHFLILFDOO\WRWKHSDUHQWRIDW\SHZLWKsuper
class C2 extends C1
class C3 extends C2 {
def setX3(x:String) = super.setX1(x)
def setX4(x:String) = C3.super.setX1(x)

Path-Dependent Types | 273

Download at WoweBook.Com
def setX5(x:String) = C3.super[C2].setX1(x)
}

C3.superLVHTXLYDOHQWWRsuperLQWKLVH[DPSOH,I\RXZDQWWRUHIHUVSHFLILFDOO\WRRQH
RIWKHSDUHQWVRIDW\SH\RXFDQTXDOLI\superZLWKWKHW\SHDVVKRZQLQsetX57KLVLV
SDUWLFXODUO\XVHIXOIRUWKHFDVHZKHUHDW\SHPL[HVLQVHYHUDOWUDLWVHDFKRIZKLFKRYHU
ULGHVWKHVDPHPHWKRG,I\RXQHHGDFFHVVWRRQHRIWKHPHWKRGVLQDVSHFLILFWUDLW\RX
FDQTXDOLI\super+RZHYHUWKLVTXDOLILFDWLRQFDQ¦WUHIHUWR£JUDQGSDUHQW¤W\SHV
:KDWLI\RXDUHFDOOLQJsuperLQDFODVVZLWKVHYHUDOPL[LQVDQGLWH[WHQGVDQRWKHUW\SH"
7RZKLFKW\SHGRHV superELQG":LWKRXWWKHTXDOLILFDWLRQWKHUXOHVRIOLQHDUL]DWLRQ
GHWHUPLQH WKH WDUJHW RI super VHH £/LQHDUL]DWLRQ RI DQ 2EMHFW¦V +LHUDU
FK\¤RQSDJH 
-XVWDVIRUthis\RXFDQXVHsuperWRUHIHUWRWKHSDUHQWW\SHLQDW\SHERG\RXWVLGHD
PHWKRG
class C4 {
class C5
}
class C6 extends C4 {
val c5a = new C5
val c5b = new super.C5
}

%RWKc5aDQGc5bKDYHWKHVDPHW\SH

path.x
<RXFDQUHDFKDQHVWHGW\SHZLWKDSHULRGGHOLPLWHGSDWKH[SUHVVLRQ
package P1 {
object O1 {
object O2 {
val name = "name"
}
}
}
class C7 {
val name = P1.O1.O2.name
}

C7.name XVHV D SDWK WR WKH name YDOXH LQ O2 7KH HOHPHQWV RI D W\SH SDWK PXVW EH
VWDEOHZKLFKURXJKO\PHDQVWKDWDOOHOHPHQWVLQWKHSDWKPXVWEHSDFNDJHVVLQJOHWRQ
REMHFWVRUW\SHGHFODUDWLRQVWKDWDOLDVWKHVDPH7KHODVWHOHPHQWLQWKHSDWKFDQEHD
FODVVRUWUDLW6HH>6FDOD6SHF@IRUWKHGHWDLOV
object O3 {
object O4 {
type t = java.io.File
class C
trait T
}

274 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
class C2 {
type t = Int
}
}
class C8 {
type t1 = O3.O4.t
type t2 = O3.O4.C
type t3 = O3.O4.T
// type t4 = O3.C2.t // ERROR: C2 is not a "value" in O3
}

Value Types
%HFDXVH6FDODLVVWURQJO\DQGVWDWLFDOO\W\SHGHYHU\YDOXHKDVDW\SH7KHWHUPYDOXH
W\SHVUHIHUVWRDOOWKHGLIIHUHQWIRUPVWKHVHW\SHVWDNHVRLWHQFRPSDVVHVPDQ\IRUPV
WKDWDUHQRZIDPLOLDUWRXVSOXVDIHZQHZRQHVZHKDYHQ¦WHQFRXQWHUHGXQWLOQRZ

:HDUHXVLQJWKHWHUPYDOXHW\SHKHUHLQWKHVDPHZD\WKHWHUPLVXVHG
E\>6FDOD6SHF@+RZHYHUHOVHZKHUHLQWKHERRNZHDOVRIROORZWKH
VSHFLILFDWLRQ¦V RYHUORDGHG XVH RI WKH WHUP WR UHIHU WR DOO VXEW\SHV RI
AnyVal

Type Designators
7KHFRQYHQWLRQDOW\SH,'VZHFRPPRQO\XVHDUHFDOOHGW\SHGHVLJQDWRUV
class Person // "Person" is a type designator
object O { type t } // "O" and "t" are type designators
...

7KH\DUHDFWXDOO\DVKRUWKDQGV\QWD[IRUW\SHSURMHFWLRQVZKLFKZHFRYHUODWHU

Tuples
$YDOXHRIWKHIRUP(x, ... x1)LVDWXSOHYDOXHW\SH

Parameterized Types
:KHQZHFUHDWHDW\SHIURPDSDUDPHWHUL]HGW\SHHJ List[Int]DQG List[String]
IURPList[A]WKHW\SHVList[Int]DQGList[String]DUHYDOXHW\SHVEHFDXVHWKH\DUH
DVVRFLDWHGZLWKGHFODUHGYDOXHVHJval names = List[String]()

Annotated Types
:KHQZHDQQRWDWHDW\SHHJ@serializable @cloneable class C(val x:String)WKH
DFWXDOW\SHLQFOXGHVWKHDQQRWDWLRQV

Value Types | 275

Download at WoweBook.Com
Compound Types
$GHFODUDWLRQRIWKHIRUPT extends T with T { R }ZKHUHRLVWKHUHILQHPHQW ERG\ 
GHFODUHVDFRPSRXQGW\SH$Q\GHFODUDWLRQVLQWKHUHILQHPHQWDUHSDUWRIWKHFRPSRXQG
W\SHGHILQLWLRQ7KHQRWLRQRIFRPSRXQGW\SHVDFFRXQWVIRUWKHIDFWWKDWQRWDOOW\SHV
DUHQDPHGVLQFHZHFDQKDYHDQRQ\PRXVW\SHVVXFKDVWKLVH[DPSOHscalaVHVVLRQ
scala> val x = new T1 with T2 {
type z = String
val v: z = "Z"
}
x: java.lang.Object with T1 with T2{type z = String; def zv: this.z} = \
$anon$1@9d9347d

1RWHWKDWSDWKGHSHQGHQWW\SHthis.zLQWKHRXWSXW
$ SDUWLFXODUO\ LQWHUHVWLQJ FDVH LV D GHFODUDWLRQ RI WKH IRUP val x = new { R } LH
ZLWKRXWDQ\W\SH,'V7KLVLVHTXLYDOHQWWRval x = new AnyRef { R }

Infix Types
6RPHSDUDPHWHUL]HGW\SHVWDNHWZRW\SHDUJXPHQWVHJ scala.Either[+A,+B]6FDOD
DOORZV\RXWRGHFODUHLQVWDQFHVRIWKHVHW\SHVXVLQJDQLQIL[QRWDWLRQHJ a Either
b&RQVLGHUWKHIROORZLQJVFULSWWKDWXVHVEither
// code-examples/TypeSystem/valuetypes/infix-types-script.scala

def attempt(operation: => Boolean): Throwable Either Boolean = try {


Right(operation)
} catch {
case t: Throwable => Left(t)
}

println(attempt { throw new RuntimeException("Boo!") })


println(attempt { true })
println(attempt { false })

7KHattemptPHWKRGZLOOHYDOXDWHWKHFDOOE\QDPHSDUDPHWHUoperationDQGUHWXUQLWV
Boolean UHVXOW ZUDSSHG LQ D Right RU DQ\ Throwable WKDW LV FDXJKW ZUDSSHG LQ D
Left7KHVFULSWSURGXFHVWKLVRXWSXW
Left(java.lang.RuntimeException: Boo!)
Right(true)
Right(false)

1RWLFH WKH GHFODUHG UHWXUQ YDOXH Throwable Either Boolean ,W LV LGHQWLFDO WR
Either[Throwable, Boolean]5HFDOOIURP£7KH6FDOD7\SH+LHUDUFK\¤RQSDJHWKDW
ZKHQXVLQJWKLVH[FHSWLRQKDQGOLQJLGLRPZLWK EitherLWLVFRQYHQWLRQDOWRXVH Left
IRUWKHH[FHSWLRQDQGRightIRUWKHQRUPDOUHWXUQYDOXH

276 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
Function Types
7KHIXQFWLRQVZHKDYHEHHQZULWLQJDUHDOVRW\SHG(T, T, ... T1) => RLVWKHW\SH
IRUDOOIXQFWLRQVWKDWWDNHNDUJXPHQWVDQGUHWXUQDYDOXHRIW\SHR
:KHQWKHUHLVRQO\RQHDUJXPHQW\RXFDQGURSWKHSDUHQWKHVHV T => R$IXQFWLRQ
WKDWWDNHVDFDOOE\QDPHSDUDPHWHU DVGLVFXVVHGLQ&KDSWHU KDVWKHW\SH (=>T) =>
R:HXVHGDFDOOE\QDPHDUJXPHQWLQRXUattemptH[DPSOHLQWKHSUHYLRXVVHFWLRQ
5HFDOOWKDWHYHU\WKLQJLQ6FDODLVDQREMHFWHYHQIXQFWLRQV7KH6FDODOLEUDU\GHILQHV
WUDLWVIRUHDFKFunctionNIRUNIURP0WR22LQFOXVLYH+HUHIRUH[DPSOHLVWKHYHUVLRQ
VRXUFHIRUscala.Function3RPLWWLQJPRVWFRPPHQWVDQGDIHZRWKHUGHWDLOVWKDW
GRQ¦WFRQFHUQXVQRZ
// From Scala version 2.7.5: scala.Function3 (excerpt).
package scala

trait Function3[-T1, -T2, -T3, +R] extends AnyRef {


def apply(v1:T1, v2:T2, v3:T3): R
override def toString() = "<function>"

/** f(x1,x2,x3) == (f.curry)(x1)(x2)(x3)


*/
def curry: T1 => T2 => T3 => R = {
(x1: T1) => (x2: T2) => (x3: T3) => apply(x1,x2,x3)
}
}

$VZHGLVFXVVHGLQ£9DULDQFH8QGHU,QKHULWDQFH¤RQSDJHWKHFunctionNWUDLWVDUH
FRQWUDYDULDQWLQWKHW\SHSDUDPHWHUVIRUWKHDUJXPHQWVDQGFRYDULDQWLQWKHUHWXUQW\SH
SDUDPHWHU
5HFDOOWKDWZKHQ\RXUHIHUHQFHDQ\REMHFWIROORZHGE\DQDUJXPHQWOLVW6FDODFDOOVWKH
applyPHWKRGRQWKHREMHFW,QWKLVZD\DQ\REMHFWZLWKDQapplyPHWKRGFDQDOVREH
FRQVLGHUHGDIXQFWLRQSURYLGLQJDQLFHV\PPHWU\ZLWKWKHREMHFWRULHQWHGQDWXUHRI
6FDOD
:KHQ \RX GHILQH D IXQFWLRQ YDOXH WKH FRPSLOHU LQVWDQWLDWHV WKH DSSURSULDWH
FunctionNREMHFWDQGXVHV\RXUGHILQLWLRQRIWKHIXQFWLRQDVWKHERG\RIapply
// code-examples/TypeSystem/valuetypes/function-types-script.scala

val capitalizer = (s: String) => s.toUpperCase

val capitalizer2 = new Function1[String,String] {


def apply(s: String) = s.toUpperCase
}

println( List("Programming", "Scala") map capitalizer)


println( List("Programming", "Scala") map capitalizer2)

7KHcapitalizerDQGcapitalizer2IXQFWLRQYDOXHVDUHHIIHFWLYHO\WKHVDPHZKHUHWKH
ODWWHUPLPLFVWKHFRPSLOHU¦VRXWSXW

Value Types | 277

Download at WoweBook.Com
:HGLVFXVVHGWKHcurryPHWKRGSUHYLRXVO\LQ£&XUU\LQJ¤RQSDJH,WUHWXUQVDQHZ
IXQFWLRQZLWK NDUJXPHQWOLVWVHDFKRIZKLFKKDVDVLQJOHDUJXPHQWWDNHQIURPWKH
RULJLQDODUJXPHQWOLVWRINDUJXPHQWV1RWHWKDWWKHVDPHapplyPHWKRGLVLQYRNHG
// code-examples/TypeSystem/valuetypes/curried-function-script.scala

val f = (x: Double, y: Double, z: Double) => x * y / z


val fc = f.curry

val answer1 = f(2., 5., 4.)


val answer2 = fc(2.)(5.)(4.)
println( answer1 + " == " + answer2 + "? " + (answer1 == answer2))

val fc1 = fc(2.)


val fc2 = fc1(5.)
val answer3 = fc2(4.)
println( answer3 + " == " + answer2 + "? " + (answer3 == answer2))

7KLVVFULSWSURGXFHVWKHIROORZLQJRXWSXW
2.5 == 2.5? true
2.5 == 2.5? true

,QWKHILUVWSDUWRIWKHVFULSWZHGHILQHDFunction3YDOXHfWKDWGRHVDoubleDULWKPHWLF
:HFUHDWHDQHZIXQFWLRQYDOXHfcE\FXUU\LQJf7KHQZHFDOOERWKIXQFWLRQVZLWKWKH
VDPHDUJXPHQWVDQGSULQWRXWWKHUHVXOWV$VH[SHFWHGWKH\ERWKSURGXFHWKHVDPH
RXWSXW 7KHUHDUHQRFRQFHUQVDERXWURXQGLQJHUURUVLQWKHFRPSDULVRQKHUHUHFDOO
WKDWERWKIXQFWLRQVFDOOWKHVDPHapplyPHWKRGVRWKH\PXVWUHWXUQWKHVDPHYDOXH
,QWKHVHFRQGSDUWRIWKHVFULSWZHH[SORLWWKHIHDWXUHRIFXUULHGIXQFWLRQVWKDWZHFDQ
SDUWLDOO\DSSO\DUJXPHQWVFUHDWLQJQHZIXQFWLRQVXQWLOZHDSSO\DOOWKHDUJXPHQWV
7KHH[DPSOHDOVRKHOSVXVPDNHVHQVHRIWKHGHFODUDWLRQRIcurryLQFunction3
)XQFWLRQVDUHULJKWDVVRFLDWLYHVRDW\SH T1 => T2 => T3 => RLVHTXLYDOHQWWR T1 =>
(T2 => (T3 => R)):HVHHWKLVLQWKHVFULSW,QWKHVWDWHPHQW val fc1 = fc(2.)ZH
FDOOfcZLWKMXVWWKHILUVWDUJXPHQWOLVW FRUUHVSRQGLQJWRT1HTXDOVDouble ,WUHWXUQVD
QHZIXQFWLRQRIW\SHT2 => (T3 => R)RUDouble => (Double => Double)LQRXUFDVH
1H[W LQ val fc2 = fc1(5.) ZH VXSSO\ WKH VHFRQG T2  DUJXPHQW UHWXUQLQJ D QHZ
IXQFWLRQRIW\SHT3 => RWKDWLVDouble => Double)LQDOO\LQval answer3 = fc2(4.)
ZHVXSSO\WKHODVWDUJXPHQWWRFRPSXWHWKHYDOXHRIW\SHRWKDWLVDouble

$W\SHT1 => T2 => T3 => RLVHTXLYDOHQWWRT1 => (T2 => (T3 => R))
:KHQZHFDOODIXQFWLRQRIWKLVW\SHZLWKDYDOXHIRUT1LWUHWXUQVDQHZ
IXQFWLRQRIW\SHT2 => (T3 => R)DQGVRIRUWK

)LQDOO\VLQFHIXQFWLRQVDUHLQVWDQFHVRIWUDLWV\RXFDQXVHWKHWUDLWVDVSDUHQWVRIRWKHU
W\SHV,QWKH6FDODOLEUDU\Seq[+A]LVDVXEFODVVRIPartialFunction[Int,A]ZKLFKLVD
VXEFODVVRI(Int) => ALHFunction1[Int,A]

278 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
Type Projections
7\SHSURMHFWLRQVDUHDZD\WRUHIHUWRDW\SHGHFODUDWLRQQHVWHGLQDQRWKHUW\SH
// code-examples/TypeSystem/valuetypes/type-projection-script.scala

trait T {
type t <: AnyRef
}
class C1 extends T {
type t = String
}
class C2 extends C1

val ic1: C1#t = "C1"


val ic2: C2#t = "C2"
println(ic1)
println(ic2)

%RWK C1#tDQG C2#tDUH String<RXFDQDOVRUHIHUHQFHWKHDEVWUDFWW\SH T#tEXW\RX


FDQ¦WXVHLWLQDGHFODUDWLRQEHFDXVHLWLVDEVWUDFW

Singleton Types
,I\RXKDYHDYDOXH vRIDVXEW\SHRI AnyRefLQFOXGLQJ null\RXFDQJHWLWVVLQJOHWRQ
W\SHXVLQJWKHH[SUHVVLRQv.type7KHVHH[SUHVVLRQVFDQEHXVHGDVW\SHVLQGHFODUDWLRQV
7KLVIHDWXUHLVXVHIXORQUDUHRFFDVLRQVWRZRUNDURXQGWKHIDFWWKDWW\SHVDUHSDWK
GHSHQGHQWZKLFKZHGLVFXVVHGLQ£3DWK'HSHQGHQW7\SHV¤RQSDJH,QWKHVHFDVHV
DQREMHFWPD\KDYHDSDWKGHSHQGHQWW\SHWKDWDSSHDUVWREHLQFRPSDWLEOHZLWKDQRWKHU
SDWKGHSHQGHQWW\SHZKHQLQIDFWWKH\DUHFRPSDWLEOH8VLQJWKH v.typeH[SUHVVLRQ
UHWULHYHVWKHVLQJOHWRQW\SHD£XQLTXH¤W\SHWKDWHOLPLQDWHVWKHSDWKGHSHQGHQF\7ZR
YDOXHVv1DQGv2PD\KDYHGLIIHUHQWSDWKGHSHQGHQWW\SHVEXWWKH\FRXOGKDYHWKHVDPH
VLQJOHWRQW\SH
7KLVH[DPSOHXVHVWKHVLQJOHWRQW\SHIRURQHYDOXHLQDGHFODUDWLRQRIDQRWKHU
class C {
val x = "Cx"
}
val c = new C
val x: c.x.type = c.x

Self-Type Annotations
<RXFDQXVHthisLQDPHWKRGWRUHIHUWRWKHHQFORVLQJW\SHZKLFKLVXVHIXOIRUUHIHU
HQFLQJDPHPEHURIWKHW\SH8VLQJthisLVQRWXVXDOO\QHFHVVDU\IRUWKLVSXUSRVHEXW
LW¦VXVHIXORFFDVLRQDOO\IRUGLVDPELJXDWLQJDUHIHUHQFHZKHQVHYHUDOYDOXHVDUHLQVFRSH
ZLWKWKHVDPHQDPH%\GHIDXOWWKHW\SHRIthisLVWKHVDPHDVWKHHQFORVLQJW\SHEXW
WKLVLVQRWUHDOO\HVVHQWLDO

Self-Type Annotations | 279

Download at WoweBook.Com
6HOIW\SHDQQRWDWLRQVOHW\RXVSHFLI\DGGLWLRQDOW\SHH[SHFWDWLRQVIRUthisDQGWKH\FDQ
EHXVHGWRFUHDWHDOLDVHVIRUthis/HW¦VFRQVLGHUWKHODWWHUFDVHILUVW
// code-examples/TypeSystem/selftype/this-alias-script.scala

class C1 { self =>


def talk(message: String) = println("C1.talk: " + message)
class C2 {
class C3 {
def talk(message: String) = self.talk("C3.talk: " + message)
}
val c3 = new C3
}
val c2 = new C2
}
val c1 = new C1
c1.talk("Hello")
c1.c2.c3.talk("World")

,WSULQWVWKHIROORZLQJ
C1.talk: Hello
C1.talk: C3.talk: World

:HJLYHWKHRXWHUVFRSH C1 thisWKHDOLDVselfVRZHFDQHDVLO\UHIHUWRLWLQ C3:H


FRXOGXVHselfZLWKLQDQ\PHWKRGLQVLGHWKHERG\RIC1RULWVQHVWHGW\SHV1RWHWKDW
WKHQDPHselfLVDUELWUDU\EXWLWLVVRPHZKDWFRQYHQWLRQDO,QIDFW\RXFRXOGVD\this
=>EXWLWZRXOGEHFRPSOHWHO\UHGXQGDQW
,I WKH VHOIW\SH DQQRWDWLRQ KDV W\SHV LQ WKH DQQRWDWLRQ ZH JHW VRPH YHU\ GLIIHUHQW
EHQHILWV
// code-examples/TypeSystem/selftype/selftype-script.scala

trait Persistence {
def startPersistence: Unit
}

trait Midtier {
def startMidtier: Unit
}

trait UI {
def startUI: Unit
}

trait Database extends Persistence {


def startPersistence = println("Starting Database")
}

trait ComputeCluster extends Midtier {


def startMidtier = println("Starting ComputeCluster")
}

trait WebUI extends UI {


def startUI = println("Starting WebUI")

280 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
}

trait App {
self: Persistence with Midtier with UI =>

def run = {
startPersistence
startMidtier
startUI
}
}

object MyApp extends App with Database with ComputeCluster with WebUI

MyApp.run

7KLVVFULSWVKRZVDVFKHPDWLFOD\RXWIRUDQApp DSSOLFDWLRQ LQIUDVWUXFWXUHVXSSRUWLQJ


VHYHUDOWLHUVFRPSRQHQWVSHUVLVWHQWVWRUDJHPLGWLHUDQG8,:H¦OOH[SORUHWKLVDS
SURDFKWRFRPSRQHQWGHVLJQLQPRUHGHWDLOLQ&KDSWHU
)RUQRZZHMXVWFDUHDERXWWKHUROHRIVHOIW\SHV(DFKDEVWUDFWWUDLWGHFODUHVD£VWDUW¤
PHWKRGWKDWGRHVWKHZRUNRILQLWLDOL]LQJWKHWLHU :H¦UHLJQRULQJLVVXHVOLNHVXFFHVV
YHUVXVIDLOXUHRIVWDUWXSHWF (DFKDEVWUDFWWLHULVLPSOHPHQWHGE\DFRUUHVSRQGLQJ
FRQFUHWHWUDLW QRWDFODVVVRZHFDQXVHWKHPDVPL[LQV :HKDYHWUDLWVIRUGDWDEDVH
SHUVLVWHQFHVRPHVRUWRIFRPSXWDWLRQFOXVWHUWRGRWKHKHDY\OLIWLQJIRUWKHEXVLQHVV
ORJLFDQGDZHEEDVHG8,
7KHAppWUDLWZLUHVWKHWLHUVWRJHWKHU)RUH[DPSOHLWGRHVWKHZRUNRIVWDUWLQJWKHWLHUV
LQWKHrunPHWKRG
1RWHWKHVHOIW\SHDQQRWDWLRQself: Persistence with Midtier with UI =>,WKDVWZR
SUDFWLFDOHIIHFWV
 7KHERG\RIWKHWUDLWFDQDVVXPHLWLVDQLQVWDQFHRIPersistenceMidtierDQGUI
VR LW FDQ FDOO PHWKRGV GHILQHG LQ WKRVH W\SHV ZKHWKHU RU QRW WKH\ DUH DFWXDOO\
GHILQHGDWWKLVSRLQW:H¦UHGRLQJMXVWWKDWLQrun
 7KHFRQFUHWHW\SHWKDWPL[HVLQWKLVWUDLWPXVWDOVRPL[LQWKHVHWKUHHRWKHUWUDLWV
RUGHVFHQGDQWVRIWKHP
,QRWKHUZRUGVWKHVHOIW\SHLQAppVSHFLILHVGHSHQGHQFLHVRQRWKHUFRPSRQHQWV7KHVH
GHSHQGHQFLHVDUHVDWLVILHGLQMyAppZKLFKPL[HVLQWKHFRQFUHWHWUDLWVIRUWKHWKUHHWLHUV
:HFRXOGKDYHGHFODUHGAppXVLQJLQKHULWDQFHLQVWHDG
trait App with Persistence with Midtier with UI {

def run = { ... }


}

7KLVLVHIIHFWLYHO\WKHVDPH$VZHVDLGWKHVHOIW\SHDQQRWDWLRQOHWVWKHAppDVVXPHLW
LVRIW\SHPersistenceHWF7KDW¦VH[DFWO\ZKDWKDSSHQVZKHQ\RXPL[LQDWUDLWWRR

Self-Type Annotations | 281

Download at WoweBook.Com
:K\WKHQDUHVHOIW\SHVXVHIXOLIWKH\DSSHDUWREHHTXLYDOHQWWRLQKHULWDQFH"7KHUH
DUHVRPHWKHRUHWLFDOUHDVRQVDQGDIHZVSHFLDOFDVHVZKHUHVHOIW\SHDQQRWDWLRQVRIIHU
XQLTXHEHQHILWV,QSUDFWLFH\RXFRXOGXVHLQKHULWDQFHIRUDOPRVWDOOFDVHV%\FRQYHQ
WLRQSHRSOHXVHLQKHULWDQFHZKHQWKH\ZDQWWRLPSO\WKDWDW\SHEHKDYHVDV LQKHULWV
IURP DQRWKHUW\SHDQGWKH\XVHVHOIW\SHDQQRWDWLRQVZKHQWKH\ZDQWWRH[SUHVVD
GHSHQGHQF\EHWZHHQDW\SHDQGRWKHUW\SHV VHH>0F,YHU@ 
,QRXUFDVHZHGRQ¦WUHDOO\WKLQNRIDQAppDVEHLQJD8,GDWDEDVHHWF:HWKLQNRIDQ
AppDVEHLQJFRPSRVHGRIWKRVHWKLQJV1RWHWKDWLQPRVWREMHFWRULHQWHGODQJXDJHV
\RXZRXOGH[SUHVVWKLVFRPSRVLWLRQDOGHSHQGHQF\ZLWKPHPEHUILHOGVHVSHFLDOO\LI
\RXUODQJXDJHGRHVQ¦WVXSSRUWPL[LQFRPSRVLWLRQOLNH-DYD)RUH[DPSOH\RXPLJKW
ZULWHAppLQ-DYDWKLVZD\
// code-examples/TypeSystem/selftype/JavaApp.java

package selftype;

public abstract class JavaApp {


public interface Persistence {
public void startPersistence();
}

public interface Midtier {


public void startMidtier();
}

public interface UI {
public void startUI();
}

private Persistence persistence;


private Midtier midtier;
private UI ui;

public JavaApp(Persistence persistence, Midtier midtier, UI ui) {


this.persistence = persistence;
this.midtier = midtier;
this.ui = ui;
}

public void run() {


persistence.startPersistence();
midtier.startMidtier();
ui.startUI();
}
}

:HQHVWHGWKHFRPSRQHQWLQWHUIDFHVLQVLGHJavaAppWRDYRLGFUHDWLQJVHSDUDWHILOHVIRU
HDFKRQH <RXFDQFHUWDLQO\ZULWHDSSOLFDWLRQVWKLVZD\LQ6FDOD+RZHYHUWKHVHOI
W\SHDSSURDFKWXUQVSURJUDPPDWLFGHSHQGHQF\UHVROXWLRQLHSDVVLQJGHSHQGHQFLHV
WRFRQVWUXFWRUVRUVHWWHUPHWKRGVDWUXQWLPHLQWRGHFODUDWLYHGHSHQGHQF\UHVROXWLRQ
DW FRPSLOH WLPH ZKLFK FDWFKHV HUURUV HDUOLHU 'HFODUDWLYH SURJUDPPLQJ ZKLFK LV D

282 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
KDOOPDUN RI IXQFWLRQDO SURJUDPPLQJ LV JHQHUDOO\ PRUH UREXVW VXFFLQFW DQG FOHDU
FRPSDUHGWRLPSHUDWLYHSURJUDPPLQJ
:HZLOOUHWXUQWRVHOIW\SHDQQRWDWLRQVDVDFRPSRQHQWFRPSRVLWLRQPRGHOLQ&KDS
WHU  6HH £6HOI7\SH $QQRWDWLRQV DQG $EVWUDFW 7\SH 0HPEHUV¤ RQ SDJH  DQG
£'HSHQGHQF\,QMHFWLRQLQ6FDOD7KH&DNH3DWWHUQ¤RQSDJH

Structural Types
<RXFDQWKLQNRIVWUXFWXUDOW\SHVDVDW\SHVDIHDSSURDFKWRGXFNW\SLQJWKHSRSXODU
QDPHIRUWKHZD\PHWKRGUHVROXWLRQZRUNVLQG\QDPLFDOO\W\SHGODQJXDJHV,Q5XE\
IRU H[DPSOH ZKHQ \RX ZULWH starFighter.shootWeapons WKH UXQWLPH ORRNV IRU D
shootWeaponsPHWKRGRQWKHREMHFWUHIHUHQFHGE\starFighter7KDWPHWKRGLIIRXQG
PLJKWKDYHEHHQGHILQHGLQWKHFODVVXVHGWRLQVWDQWLDWHstarFighterRURQHRILWVSDUHQWV
RU£LQFOXGHG¤PRGXOHV7KHPHWKRGPLJKWDOVRKDYHEHHQDGGHGWRWKHREMHFWXVLQJ
WKHPHWDSURJUDPPLQJIDFLOLW\RI5XE\)LQDOO\WKHREMHFWPLJKWRYHUULGHWKHFDWFKDOO
method_missing PHWKRG DQG GR VRPHWKLQJ UHDVRQDEOH ZKHQ WKH REMHFW UHFHLYHV WKH
shootWeapons£PHVVDJH¤
6FDOD GRHVQ¦W VXSSRUW WKLV NLQG RI PHWKRG UHVROXWLRQ ,QVWHDG 6FDOD DOORZV \RX WR
VSHFLI\WKDWDQREMHFWPXVWDGKHUHWRDFHUWDLQVWUXFWXUHWKDWLWFRQWDLQVFHUWDLQW\SHV
ILHOGVRUPHWKRGVZLWKRXWFRQFHUQIRUWKHDFWXDOW\SHRIWKHREMHFW:HILUVWHQFRXQ
WHUHGVWUXFWXUDOW\SHVQHDUWKHEHJLQQLQJRI&KDSWHU+HUHLVWKHH[DPSOHZHVDZ
WKHQDYDULDWLRQRIWKH2EVHUYHU3DWWHUQ
// code-examples/Traits/observer/observer.scala

package observer

trait Subject {
type Observer = { def receiveUpdate(subject: Any) }

private var observers = List[Observer]()


def addObserver(observer:Observer) = observers ::= observer
def notifyObservers = observers foreach (_.receiveUpdate(this))
}

7KHGHFODUDWLRQtype Observer = { def receiveUpdate(subject: Any) }VD\VWKDWDQ\


YDOLGREVHUYHUPXVWKDYHWKHreceiveUpdatePHWKRG,WGRHVQ¦WPDWWHUZKDWWKHDFWXDO
W\SHLVIRUDSDUWLFXODUREVHUYHU
6WUXFWXUDOW\SHVKDYHWKHYLUWXHRIPLQLPL]LQJWKHLQWHUIDFHEHWZHHQWZRWKLQJV,QWKLV
FDVHWKHFRXSOLQJFRQVLVWVRIRQO\DVLQJOHPHWKRGVLJQDWXUHUDWKHUWKDQDW\SHVXFK
DVDVKDUHGWUDLW$GUDZEDFNRIDVWUXFWXUDOW\SHLVWKDWZHVWLOOFRXSOHWRDSDUWLFXODU
QDPH,IDQDPHLVDUELWUDU\ZHGRQ¦WUHDOO\FDUHDERXWLWVQDPHVRPXFKDVLWVLQWHQW
,QRXUH[DPSOHRIDVLQJOHPHWKRGZHFDQDYRLGFRXSOLQJWRWKHQDPHXVLQJDIXQFWLRQ
REMHFWLQVWHDG,QIDFWZHGLGWKLVLQ£2YHUULGLQJ$EVWUDFW7\SHV¤RQSDJH

Structural Types | 283

Download at WoweBook.Com
2QWKHRWKHUKDQGLIWKHQDPHLVDXQLYHUVDOFRQYHQWLRQLQVRPHVHQVHWKHQFRXSOLQJ
WRLWKDVPRUHPHULW)RUH[DPSOH foreachLVYHU\FRPPRQQDPHLQWKH6FDODOLEUDU\
ZLWKDSDUWLFXODUPHDQLQJVRGHILQLQJDVWUXFWXUDOW\SHEDVHGRQforeachPLJKWEHEHWWHU
IRUFRQYH\LQJLQWHQWWRWKHXVHUUDWKHUWKDQXVLQJDQDQRQ\PRXVIXQFWLRQRIVRPHNLQG

Existential Types
([LVWHQWLDOW\SHVDUHDZD\RIDEVWUDFWLQJRYHUW\SHV7KH\OHW\RX£DFNQRZOHGJH¤WKDW
WKHUHLVDW\SHLQYROYHGZLWKRXWVSHFLI\LQJH[DFWO\ZKDWLWLVXVXDOO\EHFDXVH\RXGRQ¦W
NQRZZKDWLWLVDQG\RXGRQ¦WQHHGWKDWNQRZOHGJHLQWKHFXUUHQWFRQWH[W
([LVWHQWLDOW\SHVDUHSDUWLFXODUO\XVHIXOIRULQWHUIDFLQJWR-DYD¦VW\SHV\VWHPIRUWKUHH
FDVHV
‡ 7KHW\SHSDUDPHWHUVRIJHQHULFVDUH£HUDVHG¤DWWKHE\WHFRGHOHYHO FDOOHGW\SH
HUDVXUH )RUH[DPSOHZKHQDList[Int]LVFUHDWHGWKHIntW\SHLVQRWDYDLODEOHLQ
WKHE\WHFRGH
‡ <RXPLJKWHQFRXQWHU£UDZ¤W\SHVVXFKDVSUH-DYDOLEUDULHVZKHUHFROOHFWLRQV
KDGQRW\SHSDUDPHWHUV $OOW\SHSDUDPHWHUVDUHHIIHFWLYHO\Object
‡ :KHQ-DYDXVHVZLOGFDUGVLQJHQHULFVWRH[SUHVVYDULDQFHEHKDYLRUZKHQWKHJH
QHULFVDUHXVHGWKHDFWXDOW\SHLVXQNQRZQ :HGLVFXVVHGWKLVHDUOLHULQ£9DULDQFH
8QGHU,QKHULWDQFH¤RQSDJH
&RQVLGHUWKHFDVHRISDWWHUQPDWFKLQJRQList[A]REMHFWV<RXPLJKWOLNHWRZULWHFRGH
OLNHWKHIROORZLQJ
// code-examples/TypeSystem/existentials/type-erasure-wont-work.scala
// WARNINGS: Does not work as you might expect.

object ProcessList {
def apply[B](list: List[B]) = list match {
case lInt: List[Int] => // do something
case lDouble: List[Double] => // do something
case lString: List[String] => // do something
case _ => // default behavior
}
}

,I\RXFRPSLOHWKLVZLWKWKH -uncheckedIODJRQWKH-90\RX¦OOJHWZDUQLQJVWKDWWKH
W\SHSDUDPHWHUVOLNHIntDUHXQFKHFNHGEHFDXVHRIW\SHHUDVXUH+HQFHZHFDQ¦WGLV
WLQJXLVKEHWZHHQDQ\RIWKHOLVWW\SHVVKRZQ
7KHManifestVWKDWZHGLVFXVVHGSUHYLRXVO\ZRQ¦WZRUNHLWKHUEHFDXVHWKH\FDQ¦WUH
FRYHUWKHHUDVHGW\SHRIB
:H¦YHDOUHDG\OHDUQHGWKDWWKHEHVWZHFDQGRLQSDWWHUQPDWFKLQJLVWRIRFXVRQWKH
IDFWWKDWZHKDYHDOLVWDQGQRWWU\WRGHWHUPLQHWKH£ORVW¤W\SHSDUDPHWHUIRUWKHOLVW
LQVWDQFH)RUW\SHVDIHW\ZHKDYHWRVSHFLI\WKDWDOLVWKDVDSDUDPHWHUEXWVLQFHZH
GRQ¦WNQRZZKDWLWLVZHXVHWKHZLOGFDUG_FKDUDFWHUIRUWKHW\SHSDUDPHWHUHJ

284 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
case l: List[_] => // do something "generic" with the list

:KHQXVHGLQDW\SHFRQWH[WOLNHWKLVWKH List[_]LVDFWXDOO\VKRUWKDQGIRUWKHH[LV
WHQWLDOW\SHList[T] forSome { type T }7KLVLVWKHPRVWJHQHUDOFDVH:H¦UHVD\LQJ
WKHW\SHSDUDPHWHUIRUWKHOLVWFRXOGEHDQ\W\SH7DEOHOLVWVVRPHRWKHUH[DPSOHV
WKDWGHPRQVWUDWHWKHXVHRIW\SHERXQGV
7DEOH([LVWHQWLDOW\SHH[DPSOHV
Shorthand Full Description
List[_] List[T] forSome { type T } T can be any subtype of Any.
List[_ <: List[T] forSome { type T <: T can be any subtype of
scala.actors.AbstractActor] scala.actors.AbstractActor } AbstractActor.
List[_ >: MyFancyActor <: List[T] forSome { type T >: T can be any subtype of
scala.actors.AbstractActor] MyFancyActor <: AbstractActor up to and
scala.actors.AbstractActor } including the subtype
MyFancyActor.

,I\RXWKLQNDERXWKRZ6FDODV\QWD[IRUJHQHULFVLVPDSSHGWR-DYDV\QWD[\RXPLJKW
KDYH QRWLFHG WKDW DQ H[SUHVVLRQ OLNH java.util.List[_ <: scala.actors.Abstrac
tActor]LVVWUXFWXUDOO\VLPLODUWRWKH-DYDYDULDQFHH[SUHVVLRQjava.util.List<? extends
scala.actors.AbstractActor>,QIDFWWKH\DUHWKHVDPHGHFODUDWLRQV$OWKRXJKZHVDLG
WKDWYDULDQFHEHKDYLRULQ6FDODLVGHILQHGDWWKHGHFODUDWLRQVLWH\RXFDQXVHH[LVWHQWLDO
W\SHH[SUHVVLRQVLQ6FDODWRGHILQHFDOOVLWHYDULDQFHEHKDYLRU,WLVQRWUHFRPPHQGHG
IRUWKHUHDVRQVGLVFXVVHGSUHYLRXVO\EXW\RXKDYHWKDWRSWLRQ
<RXZRQ¦WVHHWKH forSomeH[LVWHQWLDOW\SHV\QWD[YHU\RIWHQLQ6FDODFRGHEHFDXVH
H[LVWHQWLDOW\SHVH[LVWSULPDULO\WRVXSSRUW-DYDJHQHULFVZKLOHSUHVHUYLQJFRUUHFWQHVV
LQ6FDOD¦VW\SHV\VWHP7\SHLQIHUHQFHKLGHVWKHGHWDLOVIURPXVLQPRVWFRQWH[WV:KHQ
ZRUNLQJZLWK6FDODW\SHVWKHRWKHUW\SHFRQVWUXFWVZHKDYHGLVFXVVHGLQWKLVFKDSWHU
DUHSUHIHUUHGWRH[LVWHQWLDOW\SHV

Infinite Data Structures and Laziness


:HGHVFULEHGOD]\YDOXHVLQ&KDSWHU,QIXQFWLRQDOODQJXDJHVWKDWDUHOD]\E\GHIDXOW
OLNH+DVNHOOOD]LQHVVPDNHVLWHDV\WRVXSSRUWLQILQLWHGDWDVWUXFWXUHV
)RUH[DPSOHFRQVLGHUWKHIROORZLQJ6FDODPHWKRG fibWKDWFDOFXODWHVWKH)LERQDFFL
QXPEHUIRUnLQWKHLQILQLWH)LERQDFFLVHTXHQFH
def fib(n: Int): Int = n match {
case 0 | 1 => n
case _ => fib(n-1) + fib(n-2)
}

,I6FDODZHUHSXUHO\OD]\ZHFRXOGLPDJLQHDGHILQLWLRQRIWKH)LERQDFFLVHTXHQFHOLNH
WKHIROORZLQJDQGLWZRXOGQ¦WFUHDWHDQLQILQLWHORRS

Infinite Data Structures and Laziness | 285

Download at WoweBook.Com
fibonacci_sequence = for (i <- 0 to infinity) yield fib(i)

6FDODLVQ¦WOD]\E\GHIDXOW DQGWKHUHLVQRinfinityYDOXHRUNH\ZRUGš EXWWKHOLEUDU\


FRQWDLQVDStreamFODVVWKDWVXSSRUWVOD]\HYDOXDWLRQDQGKHQFHLWFDQVXSSRUWLQILQLWH
GDWDVWUXFWXUHV:H¦OOVKRZDQLPSOHPHQWDWLRQRIWKH)LERQDFFLVHTXHQFHLQDPRPHQW
)LUVWKHUHLVDVLPSOHUH[DPSOHWKDWXVHVVWUHDPVWRUHSUHVHQWDOOSRVLWLYHLQWHJHUVDOO
SRVLWLYHRGGLQWHJHUVDQGDOOSRVLWLYHHYHQLQWHJHUV
// code-examples/TypeSystem/lazy/lazy-ints-script.scala

def from(n: Int): Stream[Int] = Stream.cons(n, from(n+1))

lazy val ints = from(0)


lazy val odds = ints.filter(_ % 2 == 1)
lazy val evens = ints.filter(_ % 2 == 0)

odds.take(10).print
evens.take(10).print

,WSURGXFHVWKLVRXWSXW
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, Stream.empty
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, Stream.empty

7KH fromPHWKRGLVUHFXUVLYHDQGQHYHUWHUPLQDWHV:HXVHLWWRGHILQHWKH intsE\


FDOOLQJ from(0) Streams.consLVDQREMHFWZLWKDQ applyPHWKRGWKDWLVDQDORJRXVWR
WKH:: £FRQV¤ PHWKRGRQList,WUHWXUQVDQHZVWUHDPZLWKWKHILUVWDUJXPHQWDVWKH
KHDGDQGWKHVHFRQGDUJXPHQWDQRWKHUVWUHDPDVWKHWDLO7KHoddsDQGevensLQILQLWH
VWUHDPVDUHFRPSXWHGE\ILOWHULQJints
2QFHZHKDYHGHILQHGWKHVWUHDPVWKHtakePHWKRGUHWXUQVDQHZVWUHDPRIWKHIL[HG
VL]HVSHFLILHGLQWKLVFDVH:KHQZHSULQWWKLVVWUHDPZLWKWKH printPHWKRGLW
SULQWVWKHHOHPHQWVIROORZHGE\Stream.emptyZKHQLWKLWVWKHHQGRIWKHVWUHDP
5HWXUQLQJWRWKH)LERQDFFLVHTXHQFHWKHUHLVDIDPRXVGHILQLWLRQXVLQJLQILQLWHOD]\
VHTXHQFHVWKDWH[SORLWVWKHzipRSHUDWLRQ VHHHJ>$EHOVRQ@ 2XUGLVFXVVLRQIRU
6FDODLVDGDSWHGIURP>2UWL]@
// code-examples/TypeSystem/lazy/lazy-fibonacci-script.scala

lazy val fib: Stream[Int] =


Stream.cons(0, Stream.cons(1, fib.zip(fib.tail).map(p => p._1 + p._2)))

fib.take(10).print

,WSURGXFHVWKLVRXWSXW
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, Stream.empty

+RZGRHVWKLVZRUN"/LNHRXULWHUDWLYHGHILQLWLRQDWWKHVWDUWRIWKLVVHFWLRQZHH[SOLFLWO\
VSHFLI\WKHILUVWWZRYDOXHVDQG7KHUHVWRIWKHQXPEHUVDUHFRPSXWHGXVLQJzip
H[SORLWLQJWKHIDFWWKDWfib(n) = fib(n-1) + fib(n-2)IRUn > 1

286 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
7KHFDOOfib.zip(fib.tail)FUHDWHVDQHZVWUHDPRIWXSOHVZLWKWKHHOHPHQWVRIfibLQ
WKHILUVWSRVLWLRQRIWKHWXSOHDQGWKHHOHPHQWVRI fib.tailLQWKHVHFRQGSRVLWLRQRI
WKHWXSOH7RJHWEDFNWRDVLQJOHLQWHJHUIRUHDFKSRVLWLRQLQWKHVWUHDPZHPDSWKH
VWUHDPRIWXSOHVWRDVWUHDPRIIntsE\DGGLQJWKHWXSOHHOHPHQWV+HUHDUHWKHWXSOHV
FDOFXODWHG
(0,1), (1,1), (1,2), (2,3), (3,5), (5,8), (8,13), (13, 21), (21, 34), ...

1RWHWKDWHDFKVHFRQGHOHPHQWLVWKHQH[WQXPEHULQWKH)LERQDFFLVHTXHQFHDIWHUWKH
ILUVWHOHPHQWLQWKHWXSOH$GGLQJWKHPZHJHWWKHIROORZLQJ
1, 2, 3, 5, 8, 13, 21, 34, 55, ...

6LQFHZHFRQFDWHQDWHWKLVVWUHDPDIWHUDQGZHJHWWKH)LERQDFFLVHTXHQFH
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...

$QRWKHUOD]\6FDODW\SHDOEHLWDILQLWHRQHLVRange7\SLFDOO\\RXZULWHOLWHUDOUDQJHV
VXFKDV1 to 1000RangeLVOD]\VRYHU\ODUJHUDQJHVGRQ¦WFRQVXPHWRRPDQ\UHVRXUFHV
+RZHYHUWKLVIHDWXUHFDQOHDGWRVXEWOHSUREOHPVXQOHVV\RXDUHFDUHIXODVGRFXPHQWHG
E\>6PLWKE@DQGFRPPHQWHUV8VLQJWKHH[DPSOHGHVFULEHGWKHUHFRQVLGHUWKLV
IXQFWLRQIRUUHWXUQLQJDSeqRIWKUHHUDQGRPLQWHJHUV
// code-examples/TypeSystem/lazy/lazy-range-danger-script.scala

def mkRandomInts() = {
val randInts = for {
i <- 1 to 3
val rand = i + (new scala.util.Random).nextInt
} yield rand
randInts
}
val ints1 = mkRandomInts

println("Calling first on ints1 Seq:")


for (i <- 1 to 3) {
println( ints1.first)
}

val ints2 = ints1.toList


println("Calling first on List created from ints1 Seq:")
for (i <- 1 to 3) {
println( ints2.first)
}

+HUHLVWKHRXWSXWIURPRQHUXQ7KHDFWXDOYDOXHVZLOOYDU\IURPUXQWRUXQ
Calling first on ints1 Seq:
-1532554511
-1532939260
-1532939260
Calling first on List created from ints1 Seq:
-1537171498
-1537171498
-1537171498

Infinite Data Structures and Laziness | 287

Download at WoweBook.Com
&DOOLQJ firstRQWKHVHTXHQFHGRHVQRWDOZD\VUHWXUQWKHVDPHYDOXH7KHUHDVRQLV
WKDWWKHUDQJHDWWKHEHJLQQLQJRIWKH forFRPSUHKHQVLRQHIIHFWLYHO\IRUFHVWKHZKROH
VHTXHQFHWREHOD]\+HQFHLWLVUHHYDOXDWHGZLWKHDFKFDOOWRfirstDQGWKHILUVWYDOXH
LQWKHVHTXHQFHDFWXDOO\FKDQJHVVLQFHRandomUHWXUQVDGLIIHUHQWQXPEHUHDFKWLPH DW
OHDVWLWZLOOLIWKHUHLVDVXIILFLHQWWLPHGHOWDEHWZHHQFDOOV 
+RZHYHUFDOOLQJtoListRQWKHVHTXHQFHIRUFHVLWWRHYDOXDWHWKHZKROHUDQJHDQGFUHDWH
DVWULFWOLVW

$YRLGXVLQJUDQJHVLQ for (...) yield xFRQVWUXFWVZKLOH for (...)


{...}DOWHUQDWLYHVDUHILQH

)LQDOO\6FDODYHUVLRQZLOOLQFOXGHDforcePHWKRGRQDOOFROOHFWLRQVWKDWZLOOIRUFH
WKHPWREHVWULFW

Recap and What’s Next


,W¦VLPSRUWDQWWRUHPHPEHUWKDW\RXGRQ¦WKDYHWRPDVWHUWKHLQWULFDFLHVRI6FDOD¦VULFK
W\SHV\VWHPWRXVH6FDODHIIHFWLYHO\$V\RXXVH6FDODPRUHDQGPRUHPDVWHULQJWKH
W\SHV\VWHPZLOOKHOS\RXFUHDWHSRZHUIXOVRSKLVWLFDWHGOLEUDULHVWKDWDFFHOHUDWH\RXU
SURGXFWLYLW\
7KH>6FDOD6SHF@GHVFULEHVWKHW\SHV\VWHPLQIRUPDOGHWDLO/LNHDQ\VSHFLILFDWLRQ
LWFDQEHGLIILFXOWUHDGLQJ7KHHIIRUWLVZRUWKZKLOHLI\RXZDQWDGHHSXQGHUVWDQGLQJ
RIWKHW\SHV\VWHP7KHUHDUHDOVRDPXOWLWXGHRISDSHUVRQ6FDOD¦VW\SHV\VWHP<RX
FDQILQGOLQNVWRPDQ\RIWKHPRQWKHRIILFLDOKWWSVFDODODQJRUJZHEVLWH
7KHQH[WWZRFKDSWHUVFRYHUWKHSUDJPDWLFVRIDSSOLFDWLRQGHVLJQDQG6FDOD¦VGHYHO
RSPHQWWRROVDQGOLEUDULHV

288 | Chapter 12:—The Scala Type System

Download at WoweBook.Com
CHAPTER 13
Application Design

,QWKLVFKDSWHUZHWDNHDSUDJPDWLFORRNDWGHYHORSLQJDSSOLFDWLRQVLQ6FDOD:HGLVFXVV
D IHZODQJXDJH DQG $3, IHDWXUHV WKDW ZH KDYHQ¦WFRYHUHG EHIRUH H[DPLQH FRPPRQ
GHVLJQSDWWHUQVDQGLGLRPVDQGUHYLVLWWUDLWVZLWKDQH\HWRZDUGVWUXFWXULQJRXUFRGH
HIIHFWLYHO\

Annotations
/LNH-DYDDQG1(76FDODVXSSRUWVDQQRWDWLRQVIRUDGGLQJPHWDGDWDWRGHFODUDWLRQV
$QQRWDWLRQVDUHXVHGE\DYDULHW\RIWRROVLQW\SLFDOHQWHUSULVHDQG,QWHUQHWDSSOLFDWLRQV
)RUH[DPSOHWKHUHDUHDQQRWDWLRQVWKDWSURYLGHGLUHFWLYHVWRWKHFRPSLOHUDQGVRPH
2EMHFW5HODWLRQDO 0DSSLQJ 250  IUDPHZRUNV XVH DQQRWDWLRQV RQ W\SHV DQG W\SH
PHPEHUVWRLQGLFDWHSHUVLVWHQFHPDSSLQJLQIRUPDWLRQ:KLOHVRPHXVHVIRUDQQRWD
WLRQVLQWKH-DYDDQG1(7ZRUOGVFDQEHDFFRPSOLVKHGWKURXJKRWKHUPHDQVLQ6FDOD
DQQRWDWLRQVFDQEHHVVHQWLDOIRULQWHURSHUDWLQJZLWK-DYDDQG1(7OLEUDULHVWKDWUHO\
KHDYLO\RQWKHP)RUWXQDWHO\-DYDDQG1(7DQQRWDWLRQVFDQEHXVHGLQ6FDODFRGH
7KHLQWHUSUHWDWLRQRI6FDODDQQRWDWLRQVGHSHQGVRQWKHUXQWLPHHQYLURQPHQW,QWKLV
VHFWLRQZHZLOOIRFXVRQWKH-'.HQYLURQPHQW
,Q-DYDDQQRWDWLRQVDUHGHFODUHGXVLQJVSHFLDOFRQYHQWLRQVHJGHFODULQJDQQRWDWLRQV
ZLWKWKH @interfaceNH\ZRUGLQVWHDGRIWKH classRU interfaceNH\ZRUG+HUHLVWKH
GHFODUDWLRQRIDQDQQRWDWLRQWDNHQIURPDWRRONLWFDOOHG&RQWUDFW- VHH>&RQWUDFW-@
WKDWXVHVDQQRWDWLRQVWRVXSSRUW'HVLJQE\&RQWUDFWSURJUDPPLQJLQ-DYD VHHDOVR
£%HWWHU'HVLJQZLWK'HVLJQ%\&RQWUDFW¤RQSDJH 6RPHRIWKHFRPPHQWVKDYH
EHHQUHPRYHGIRUFODULW\
// code-examples/AppDesign/annotations/Pre.java

package org.contract4j5.contract;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

289

Download at WoweBook.Com
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.CONSTRUCTOR})
public @interface Pre {
/**
* The "value" is the test expression, which must evaluate to true or false.
* It must be a valid expression in the scripting language you are using.
*/
String value() default "";

/**
* An optional message to print with the standard message when the contract
* fails.
*/
String message() default "";
}

7KH @PreDQQRWDWLRQLVXVHGWRVSHFLI\£SUHFRQGLWLRQV¤WKDWPXVWEHVDWLVILHGZKHQ
HQWHULQJDPHWKRGRUFRQVWUXFWRURUEHIRUHXVLQJDSDUDPHWHUSDVVHGWRDPHWKRGRU
FRQVWUXFWRU7KHFRQGLWLRQVDUHVSHFLILHGDVDVWULQJWKDWLVDFWXDOO\DVQLSSHWRIVRXUFH
FRGHWKDWHYDOXDWHVWRtrueRUfalse7KHVRXUFHODQJXDJHVVXSSRUWHGIRUWKHVHVQLSSHWV
DUHVFULSWLQJODQJXDJHVOLNH*URRY\DQG-5XE\7KHQDPHRIWKHYDULDEOHIRUWKLVVWULQJ
valueLVDFRQYHQWLRQDOQDPHIRUWKHPRVWLPSRUWDQWILHOGLQWKHDQQRWDWLRQ
7KHRWKHUILHOGLVDQRSWLRQDOmessageWRXVHZKHQUHSRUWLQJIDLOXUHV
7KHGHFODUDWLRQKDVRWKHUDQQRWDWLRQVDSSOLHGWRLW¢IRUH[DPSOHWKH@RetentionDQ
QRWDWLRQ ZLWK WKH YDOXH RetentionPolicy.RUNTIME PHDQV WKDW ZKHQ @Pre LV XVHG LWV
LQIRUPDWLRQZLOOEHUHWDLQHGLQWKHFODVVILOHIRUUXQWLPHXVH
+HUHLVD6FDODH[DPSOHWKDWXVHV@PreDQGVKRZVVHYHUDOZD\VWRVSHFLI\WKHvalueDQG
messageSDUDPHWHUV
// code-examples/AppDesign/annotations/pre-example.scala

import org.contract4j5.contract._

class Person(
@Pre( "name != null && name.length() > 0" )
val name: String,
@Pre{ val value = "age > 0", val message = "You're too young!" }
val age: Int,
@Pre( "ssn != null" )
val ssn: SSN)

class SSN(
@Pre( "valid(ssn)" ) { val message = "Format must be NNN-NN-NNNN." }
val ssn: String) {

private def valid(value: String) =


value.matches("""^\s*\d{3}-\d{2}-\d{4}\s*$""")
}

290 | Chapter 13:—Application Design

Download at WoweBook.Com
,Q WKH Person FODVV WKH @Pre DQQRWDWLRQ RQ name KDV D VLPSOH VWULQJ DUJXPHQW WKH
£SUHFRQGLWLRQ¤WKDWXVHUVPXVWVDWLVI\ZKHQSDVVLQJLQDQDPH7KLVYDOXHFDQ¦WEH
null DQG LW FDQ¦W EH RI ]HUR OHQJWK $V LQ -DYD LI D VLQJOH DUJXPHQW LV JLYHQ WR WKH
DQQRWDWLRQLWLVDVVLJQHGWRWKHvalueILHOG
$VLPLODU@PreDQQRWDWLRQLVXVHGIRUWKHWKLUGDUJXPHQWWKHssn 6RFLDO6HFXULW\QXP
EHU ,QERWKFDVHVWKHmessageGHIDXOWVWRWKHHPSW\VWULQJVSHFLILHGLQWKHGHILQLWLRQ
RIPre
7KH @PreDQQRWDWLRQIRUWKHDJHVKRZVRQHZD\WRVSHFLI\YDOXHVIRUPRUHWKDQRQH
ILHOG,QVWHDGRISDUHQWKHVHVFXUO\EUDFHVDUHXVHG7KHV\QWD[IRUHDFKILHOGORRNVOLNH
DvalGHFODUDWLRQZLWKRXWDQ\W\SHLQIRUPDWLRQVLQFHWKHW\SHVFDQDOZD\VEHLQIHUUHG
7KLVV\QWD[DOORZV\RXWRXVHWKHVKRUWKDQGV\QWD[IRUWKHvalueDQGVWLOOVSHFLI\YDOXHV
IRURWKHUILHOGV

,IPersonZHUHD-DYDFODVVWKLVDQQRWDWLRQH[SUHVVLRQZRXOGORRNLGHQ
WLFDOH[FHSWWKHUHZRXOGEHQRvalNH\ZRUGVDQGSDUHQWKHVHVZRXOGEH
XVHG

7KH @Pre DQQRWDWLRQ RQ WKH FRQVWUXFWRU SDUDPHWHU IRU WKH SSN FODVV VKRZV WKH DO
WHUQDWLYHV\QWD[IRUVSHFLI\LQJYDOXHVIRUPRUHWKDQRQHILHOG7KHvalueILHOGLVVSHFLILHG
DVEHIRUHZLWKDRQHHOHPHQWSDUDPHWHUOLVW7KH messageLVLQLWLDOL]HGLQDIROORZRQ
EORFNLQFXUO\EUDFHV
7HVWLQJWKLVFRGHZRXOGUHTXLUHWKH&RQWUDFW-OLEUDU\EXLOGVHWXSHWF:HZRQ¦WFRYHU
WKRVHVWHSVKHUH5HIHUWR>&RQWUDFW-@IRUPRUHLQIRUPDWLRQ
6FDODDQQRWDWLRQVGRQ¦WXVHDVSHFLDOGHFODUDWLRQV\QWD[7KH\DUHGHFODUHGDVQRUPDO
FODVVHV7KLVDSSURDFKHOLPLQDWHVD£VSHFLDOFDVH¤LQWKHODQJXDJHEXWLWDOVRPHDQV
WKDWVRPHRIWKHIHDWXUHVSURYLGHGE\-DYDDQQRWDWLRQVDUHQ¦WVXSSRUWHGDVZHZLOOVHH
+HUHLVDQH[DPSOHDQQRWDWLRQIURPWKH6FDODOLEUDU\SerialVersionUID DJDLQZLWKWKH
FRPPHQWVUHPRYHGIRUFODULW\ 
package scala

class SerialVersionUID(uid: Long) extends StaticAnnotation

7KH@SerialVersionUIDDQQRWDWLRQLVDSSOLHGWRDFODVVWRGHILQHDJOREDOO\XQLTXH,'
DVDLong:KHQWKHDQQRWDWLRQLVXVHGWKH,'LVVSHFLILHGDVDFRQVWUXFWRUDUJXPHQW
7KLVDQQRWDWLRQVHUYHVWKHVDPHSXUSRVHDVDstaticILHOGQDPHGserialVersionUIDLQ
D-DYDFODVV7KLVLVRQHH[DPSOHRID6FDODDQQRWDWLRQWKDWPDSVWRD£QRQDQQRWDWLRQ¤
FRQVWUXFWLQ-DYD
7KHSDUHQWRI SerialVersionUIDLVWKHWUDLW scala.StaticAnnotationZKLFKLVXVHGDV
WKHSDUHQWIRUDOODQQRWDWLRQVWKDWVKRXOGEHYLVLEOHWRWKHW\SHFKHFNHUHYHQDFURVV
FRPSLODWLRQ XQLWV 7KH SDUHQW FODVV RI scala.StaticAnnotation LV scala.Annotation
ZKLFKLVWKHSDUHQWRIDOO6FDODDQQRWDWLRQV

Annotations | 291

Download at WoweBook.Com
'LG\RXQRWLFHWKDWWKHUHLVQRvalRQuid":K\LVQ¦WuidDILHOG"7KHUHDVRQLVWKDWWKH
DQQRWDWLRQ¦VGDWDLVQRWLQWHQGHGIRUXVHE\WKHSURJUDP5HFDOOWKDWLWLVPHWDGDWD
GHVLJQHGIRUH[WHUQDOWRROVWRXVHVXFKDVscalac7KLVDOVRPHDQVWKDW6FDODDQQRWD
WLRQVKDYHQRZD\WRGHILQHGHIDXOWYDOXHVLQYHUVLRQ;DVLPSOLFLWDUJXPHQWVGRQ¦W
ZRUN+RZHYHUWKHQHZGHIDXOWDUJXPHQWVIHDWXUHLQYHUVLRQPD\ZRUN ,WLV
QRW\HWLPSOHPHQWHGDWWKHWLPHRIWKLVZULWLQJ
/LNH-DYD DQG1(7 DQQRWDWLRQVD6FDODDQQRWDWLRQFODXVHDSSOLHVWRWKHGHILQLWLRQ
LWSUHFHGHV<RXFDQKDYHDVPDQ\DQQRWDWLRQFODXVHVDV\RXZDQWDQGWKHRUGHULQ
ZKLFKWKH\DSSHDULVQRWVLJQLILFDQW
/LNH -DYD DQQRWDWLRQV 6FDOD DQQRWDWLRQ FODXVHV DUH ZULWWHQ XVLQJ WKH V\QWD[
@MyAnnotation LI WKH DQQRWDWLRQ FRQVWUXFWRU WDNHV QR SDUDPHWHUV RU @MyAnnota
tion(arg1, .., argN)LIWKHFRQVWUXFWRUWDNHVSDUDPHWHUV7KHDQQRWDWLRQPXVWEHD
VXEFODVVRIscala.Annotation
$OOWKHFRQVWUXFWRUSDUDPHWHUVPXVWEHFRQVWDQWH[SUHVVLRQVLQFOXGLQJVWULQJVFODVV
OLWHUDOV-DYDHQXPHUDWLRQVQXPHULFDOH[SUHVVLRQVDQGRQHGLPHQVLRQDODUUD\VRIWKH
VDPH+RZHYHUWKHFRPSLOHUDOVRDOORZVDQQRWDWLRQFODXVHVZLWKRWKHUDUJXPHQWV
VXFKDVERROHDQYDOXHVDQGPDSVDVVKRZQLQWKLVH[DPSOH
// code-examples/AppDesign/annotations/anno-example.scala

import scala.StaticAnnotation

class Persist(tableName: String, params: Map[String,Any])


extends StaticAnnotation

// Doesn't compile:
//@Persist("ACCOUNTS", Map("dbms" -> "MySql", "writeAutomatically" -> true))
@Persist("ACCOUNTS", Map(("dbms", "MySql"), ("writeAutomatically", true)))
class Account(val balance: Double)

&XULRXVO\LI\RXDWWHPSWWRXVHWKHVWDQGDUG MapOLWHUDOV\QWD[WKDWLVVKRZQLQWKH
FRPPHQWV\RXJHWDFRPSLODWLRQHUURUWKDWWKH->PHWKRGGRHVQ¦WH[LVWIRUString7KH
LPSOLFLW FRQYHUVLRQ WR ArrowAssoc WKDW ZH GLVFXVVHG LQ £7KH 3UHGHI 2E
MHFW¤ RQ SDJH  LVQ¦W LQYRNHG ,QVWHDG \RX KDYH WR XVH D OLVW RI Tuples ZKLFK
Map.applyDFWXDOO\H[SHFWV
$QRWKHUFKLOGRIscala.AnnotationWKDWLVLQWHQGHGWREHDSDUHQWRIRWKHUDQQRWDWLRQV
LVWKHWUDLW scala.ClassfileAnnotation,WLVVXSSRVHGWREHXVHGIRUDQQRWDWLRQVWKDW
VKRXOGKDYHUXQWLPHUHWHQWLRQLHWKHDQQRWDWLRQVVKRXOGEHYLVLEOHLQWKHFODVVILOH
VRWKH\DUHDYDLODEOHDWUXQWLPH+RZHYHUDFWXDOO\XVLQJLWZLWKWKH-'.YHUVLRQRI
6FDODUHVXOWVLQFRPSLOHUHUURUVOLNHWKHIROORZLQJ
...: warning: implementation restriction: subclassing Classfile does not
make your annotation visible at runtime. If that is what
you want, you must write the annotation class in Java.
...

292 | Chapter 13:—Application Design

Download at WoweBook.Com
+HQFHLI\RXZDQWUXQWLPHYLVLELOLW\\RXKDYHWRLPSOHPHQWWKHDQQRWDWLRQLQ-DYD
7KLVZRUNVILQHVLQFH\RXFDQXVHDQ\-DYDDQQRWDWLRQLQ6FDODFRGH7KH6FDODOLEUDU\
FXUUHQWO\GHILQHVQRDQQRWDWLRQVGHULYHGIURPClassfileAnnotationSHUKDSVIRUREYL
RXVUHDVRQV

$YRLG ClassfileAnnotation,PSOHPHQWDQQRWDWLRQVWKDWUHTXLUHUXQ
WLPHUHWHQWLRQLQ-DYDLQVWHDG

)RU6FDODYHUVLRQ;DQRWKHULPSRUWDQWOLPLWDWLRQWRNHHSLQPLQGLVWKDWDQQRWD
WLRQVFDQ¦WEHQHVWHG7KLVFDXVHVSUREOHPVZKHQXVLQJ-3$DQQRWDWLRQVLQ6FDODFRGH
IRU H[DPSOH DV GLVFXVVHG LQ >-3$6FDOD@ +RZHYHU 6FDOD YHUVLRQ  UHPRYHV WKLV
OLPLWDWLRQ

$QQRWDWLRQVFDQRQO\EHQHVWHGLQ6FDODYHUVLRQ

7DEOHVDQGGHVFULEHDOOWKHDQQRWDWLRQVGHILQHGLQWKH6FDODOLEUDU\ DGDSWHG
DQGH[SDQGHGIURPKWWSZZZVFDODODQJRUJQRGH :HVWDUWZLWKWKHGLUHFWFKLO
GUHQRIAnnotationIROORZHGE\WKHFKLOGUHQRIStaticAnnotation
7DEOH6FDODDQQRWDWLRQVGHULYHGIURP$QQRWDWLRQ
Name Java equivalent Description
ClassfileAnnotation Annotate with @Retention The parent trait for annotations that should be retained
(RetentionPolicy.RUNTIME) in the class file for runtime access, but it doesn’t actually
work on the JDK!
BeanDescription BeanDescriptor (class) An annotation for JavaBean types or members that
associates a short description (provided as the anno-
tation argument) that will be included when gener-
ating bean information.
BeanDisplayName BeanDescriptor (class) An annotation for JavaBean types or members that
associates a name (provided as the annotation argu-
ment) that will be included when generating bean
information.
BeanInfo BeanInfo (class) A marker that indicates that a BeanInfo class should
be generated for the marked Scala class. A val
becomes a read-only property. A var becomes a read-
write property. A def becomes a method.
BeanInfoSkip N.A. A marker that indicates that bean information should
not be generated for the annotated member.
StaticAnnotation Static fields, The parent trait of annotations that should be visible
@Target(ElementType.TYPE) across compilation units and define “static” metadata.

Annotations | 293

Download at WoweBook.Com
Name Java equivalent Description
TypeConstraint N.A. An annotation trait that can be applied to other an-
notations that define constraints on a type, relying
only on information defined within the type itself, as
opposed to external context information where the
type is defined or used. The compiler can exploit this
restriction to rewrite the constraint. There are currently
no library annotations that use this trait.
unchecked N.A. A marker annotation for the selector in a match state-
ment (e.g., the x in x match {...}) that sup-
presses a compiler warning if the case clauses are not
“exhaustive.” You can still have a runtime MatchEr
ror occur if a value of x fails to match any of the
case clauses. See the upcoming example.
unsealed N.A. Deprecated, use @unchecked instead.

7DEOH6FDODDQQRWDWLRQVGHULYHGIURP6WDWLF$QQRWDWLRQ
Name Java equivalent Description
BeanProperty JavaBean convention A marker for a field (including a constructor argument with
the val or var keyword) that tells the compiler to generate
a JavaBean-style “getter” and “setter” method. The setter is
only generated for var declarations. See the discussion in
“JavaBean Properties” on page 374.
cloneable java.lang.Cloneable A class marker indicating that a class can be cloned.
(interface)
cps N.A. (version 2.8) Generate byte code using continuation passing
style.
deprecated java.lang.Deprecated A marker for any definition indicating that the defined “item”
is obsolete. The compiler will issue a warning when the item
is used.
inline N.A. A method marker telling the compiler that it should try
“especially hard” to inline the method.
native native (keyword) A method marker indicating the method is implemented as
“native” code. The method body will not be generated by the
compiler, but usage of the method will be type checked.
noinline N.A. A method marker that prevents the compiler from inlining the
method, even when it appears to be safe to do so.
remote java.rmi.Remote A class marker indicating that the class can be invoked from a
(interface) remote JVM.
serializable java.io.Serializable A class marker indicating that the class can be serialized.
(interface)
SerialVersionUID serialVersionUID static Defines a globally unique ID for serialization purposes. The
field in a class annotation’s constructor takes a Long argument for the UID.

294 | Chapter 13:—Application Design

Download at WoweBook.Com
Name Java equivalent Description
switch N.A. (version 2.8) An annotation to be applied to a match expression,
e.g., (x: @switch) match {...}. When present, the
compiler will verify that the match has been compiled to a
table-based or lookup-based switch statement. If not, it will
issue an error if it instead compiles into a series of conditional
expressions, which are less efficient.
specialized N.A. (version 2.8) An annotation applied to type parameters in par-
ameterized types and methods. It tells the compiler to generate
optimized versions of the type or method for the AnyVal types
corresponding to platform primitive types. Optionally, you can
limit the AnyVal types for which specialized implementations
will be generated. See the upcoming discussion.
tailRec N.A. (version 2.8) A method annotation that tells the compiler to
verify that the method will be compiled with tail-call optimi-
zation. If it is present, the compiler will issue an error if the
method cannot be optimized into a loop. This happens, for
example, when the method is not private or final, when
it could be overridden, and when recursive invocations are not
true tail calls.
throws throws (keyword) Indicates which exceptions are thrown by the annotated
method. See the upcoming discussion.
transient transient (keyword) Marks a method as “transient.”
uncheckedStable N.A. A marker for a value that is assumed to be stable even though
its type is volatile (i.e., annotated with @volatile).
uncheckedVariance N.A. A marker for a type argument that is volatile, when it is used
in a parameterized type, to suppress variance checking.
volatile volatile (keyword, A marker for an individual field or a whole type, which affects
for fields only) all fields, indicating that the field may be modified by a separate
thread.

7KHDQQRWDWLRQVPDUNHGZLWK£ YHUVLRQ ¤DUHRQO\DYDLODEOHLQ6FDODYHUVLRQRU


ODWHU&RQVLGHU@tailrecDVXVHGLQWKHIROORZLQJH[DPSOH
import scala.annotation.tailrec

@tailrec
def fib(i: Int): Int = i match {
case _ if i <= 1 => i
case _ => fib(i-1) + fib(i-2)
}
println(fib(5))

1RWHWKDW fibZKLFKFDOFXODWHV)LERQDFFLQXPEHUVLVUHFXUVLYHEXWLWLVQ¦WWDLOFDOO
UHFXUVLYHEHFDXVHWKHFDOOWRLWVHOILVQRWWKHYHU\ODVWWKLQJWKDWKDSSHQVLQWKHVHFRQG
FDVHFODXVH5DWKHUDIWHUFDOOLQJLWVHOIWZLFHLWGRHVDQDGGLWLRQ+HQFHDWDLOFDOORS
WLPL]DWLRQFDQ¦WEHSHUIRUPHGRQWKLVPHWKRG:KHQWKHFRPSLOHUVHHVWKH @tailrec

Annotations | 295

Download at WoweBook.Com
DQQRWDWLRQLWWKURZVDQHUURULILWFDQ¦WDSSO\WKHWDLOFDOORSWLPL]DWLRQ$WWHPSWLQJWR
UXQWKLVVFULSWSURGXFHVWKHIROORZLQJHUURU
... 4: error: could not optimize @tailrec annotated method
def fib(i: Int): Int = i match {
^
one error found

:HFDQDOVRXVHWKHVDPHPHWKRGWRGHPRQVWUDWHWKHQHZ@switchDQQRWDWLRQDYDLODEOH
LQYHUVLRQ
import scala.annotation.switch

def fib(i: Int): Int = (i: @switch) match {


case _ if i <= 1 => i
case _ => fib(i-1) + fib(i-2)
}
println(fib(5))

7KLVWLPHZHDQQRWDWHWKHiLQWKHmatchVWDWHPHQW7KLVDQQRWDWLRQFDXVHVWKHFRPSLOHU
WRUDLVHDQHUURULILWFDQ¦WJHQHUDWHDVZLWFKFRQVWUXFWLQE\WHFRGHIURPWKHFDVHVLQWKH
PDWFKVWDWHPHQW6ZLWFKHVDUHJHQHUDOO\PRUHHIILFLHQWWKDQFRQGLWLRQDOORJLF5XQQLQJ
WKLVVFULSWSURGXFHVWKLVRXWSXW
... 3: error: could not emit switch for @switch annotated match
def fib(i: Int): Int = (i: @switch) match {
^
one error found

&RQGLWLRQDOEORFNVKDYHWREHJHQHUDWHGLQVWHDG7KHUHDVRQDVZLWFKFDQ¦WEHJHQHUDWHG
LVEHFDXVHRIWKHFRQGLWLRQJXDUGFODXVHZHSXWLQWKHILUVWFDVHFODXVHif i <= 1
/HW¦VORRNDWDQH[DPSOHRI @uncheckedLQXVH DGDSWHGIURPWKH6FDODGRFHQWU\IRU
@unchecked &RQVLGHUWKHIROORZLQJFRGHIUDJPHQW
...
def process(x: Option[int]) = x match {
case Some(value) => ...
}
...

,I\RXFRPSLOHLW\RXZLOOJHWWKHIROORZLQJZDUQLQJ
...: warning: does not cover case {object None}
def f(x: Option[int]) = x match {
^
one warning found

1RUPDOO\\RXZRXOGZDQWWRDGGDFDVHIRU None+RZHYHULI\RXZDQWWRVXSSUHVV
WKHZDUQLQJPHVVDJHLQVLWXDWLRQVOLNHWKLVFKDQJHWKHPHWKRGDVIROORZV
...
def process(x: Option[int]) = (x: @unchecked) match {
case Some(value) => ...
}
...

296 | Chapter 13:—Application Design

Download at WoweBook.Com
:LWKWKH@uncheckedDQQRWDWLRQDSSOLHGWRxDVVKRZQWKHZDUQLQJZLOOEHVXSSUHVVHG
+RZHYHULIxLVHYHUNoneWKHQDMatchErrorZLOOEHWKURZQ
7KH @specialized DQQRWDWLRQ LV DQRWKHU RSWLPL]DWLRQUHODWHG DQQRWDWLRQ DGGHG LQ
YHUVLRQ,WLVDSUDJPDWLFVROXWLRQWRDWUDGHRIIEHWZHHQVSDFHHIILFLHQF\DQGSHU
IRUPDQFH,Q-DYDDQG6FDODWKHLPSOHPHQWDWLRQRIDSDUDPHWHUL]HGW\SHRUPHWKRGLV
JHQHUDWHGDWWKHSRLQWRIWKHGHFODUDWLRQ DVZHGLVFXVVHGLQ£8QGHUVWDQGLQJ3DUDPH
WHUL]HG7\SHV¤RQSDJH ,QFRQWUDVWLQ&DWHPSODWHLVXVHGWRJHQHUDWHDQ
LPSOHPHQWDWLRQIRUWKHDFWXDOW\SHSDUDPHWHUVZKHUHWKHWHPSODWHLVXVHG7KH&
DSSURDFKKDVWKHDGYDQWDJHRIDOORZLQJRSWLPL]HGLPSOHPHQWDWLRQVWREHJHQHUDWHG
IRUSULPLWLYHW\SHVZKLOHLWKDVWKHGLVDGYDQWDJHRIUHVXOWLQJLQFRGHEORDWIURPDOOWKH
LQVWDQWLDWLRQVRIWHPSODWHV
,Q-90UHODWHGODQJXDJHVWKH£RQGHPDQG¤JHQHUDWLRQRILPSOHPHQWDWLRQVLVQ¦WVXLW
DEOHSULPDULO\EHFDXVHWKHUHLVQR£OLQN¤VWHSDVLQFRPSLOHGODQJXDJHVZKHUHHYHU\
UHTXLUHGLQVWDQWLDWLRQRIDWHPSODWHFDQEHGHWHUPLQHG7KLVFUHDWHVDGLOHPPD%\
GHIDXOWD6FDODSDUDPHWHUL]HGW\SHRUPHWKRGZLOOEHWUDQVODWHGWRDVLQJOHLPSOHPHQ
WDWLRQDVVXPLQJAnyIRUWKHW\SHSDUDPHWHUV LQSDUWGXHWRW\SHHUDVXUHDWWKHE\WHFRGH
OHYHO -DYDJHQHULFVZRUNWKHVDPHZD\+RZHYHULIDSDUWLFXODUXVHRIWKHW\SHRU
PHWKRGXVHVRQHRIWKH AnyValW\SHVVD\ IntWKHQZHJHWLQHIILFLHQWER[LQJDQGXQ
ER[LQJRSHUDWLRQVLQWKHLPSOHPHQWDWLRQ
7KHDOWHUQDWLYHZRXOGEHWRJHQHUDWHDVHSDUDWHLPSOHPHQWDWLRQIRUHYHU\AnyValFRU
UHVSRQGLQJWRDSULPLWLYHW\SHEXWWKLVZRXOGOHDGWRFRGHEORDWHVSHFLDOO\VLQFHLW
ZRXOGEHUDUHWKDWDQDSSOLFDWLRQZRXOGXVHDOOWKRVHLPSOHPHQWDWLRQV6RZHDUHIDFHG
ZLWKDGLOHPPD
7KH@specializedDQQRWDWLRQLVDSUDJPDWLFFRPSURPLVH,WOHWVWKHXVHUWHOOWKHFRP
SLOHUWKDWUXQWLPHHIILFLHQF\LVPRUHLPSRUWDQWWKDQVSDFHHIILFLHQF\VRWKHFRPSLOHU
ZLOO JHQHUDWH WKH VHSDUDWH LPSOHPHQWDWLRQV IRU HDFK SULPLWLYH FRUUHVSRQGLQJ WR DQ
AnyVal+HUHLVDQH[DPSOHRIKRZWKHDQQRWDWLRQLVXVHG
class SpecialCollection[@specialized +T](...) {
...
}

$WWKHWLPHRIWKLVZULWLQJWKHLPSOHPHQWDWLRQLQWKHYHUVLRQ£QLJKWO\¤EXLOGRQO\
VXSSRUWVJHQHUDWLRQRIVSHFLDOL]HGLPSOHPHQWDWLRQVIRU IntDQG Double)RUWKHILQDO
YHUVLRQOLEUDU\LWLVSODQQHGWKDWWKHRWKHU AnyValW\SHVZLOOEHVXSSRUWHG7KHUH
DUHDOVRSODQVWRDOORZWKHXVHUWRVSHFLI\WKHW\SHVIRUZKLFKRSWLPL]HGLPSOHPHQWD
WLRQVDUHJHQHUDWHGVRWKDWXQXVHGLPSOHPHQWDWLRQVIRUWKHRWKHUAnyValsDUHDYRLGHG
6HHWKHILQDO6FDODGRFVIRUGHWDLOVRQWKHILQDOIHDWXUHVHW
$QRWKHUSODQQHGYHUVLRQDQQRWDWLRQLV@cpsZKLFKVWDQGVIRUFRQWLQXDWLRQSDVVLQJ
VW\OH,WZLOOEHDGLUHFWLYHLQWHUSUHWHGE\DFRPSLOHUSOXJLQWKDWZLOOWULJJHUJHQHUDWLRQ
RIFRQWLQXDWLRQEDVHGE\WHFRGHIRUPHWKRGLQYRFDWLRQUDWKHUWKDQWKHGHIDXOWVWDFN
IUDPHE\WHFRGH7KHDQQRWDWLRQZLOOKDYHQRHIIHFWXQOHVVWKHFRUUHVSRQGLQJ scalac

Annotations | 297

Download at WoweBook.Com
SOXJLQLVXVHG&RQVXOWWKHUHOHDVHGRFXPHQWDWLRQIRUPRUHLQIRUPDWLRQRQWKLVIHDWXUH
ZKHQLWEHFRPHVDYDLODEOH
7RXQGHUVWDQGWKH@throwsDQQRWDWLRQLW¦VLPSRUWDQWWRUHPHPEHUWKDW6FDODGRHVQRW
KDYHFKHFNHGH[FHSWLRQVLQFRQWUDVWZLWK-DYD7KHUHLVDOVRQRthrowsFODXVHDYDLODEOH
IRU 6FDOD PHWKRG GHFODUDWLRQV 7KLV LV QRW D SUREOHP LI D 6FDOD PHWKRG FDOOV D -DYD
PHWKRG WKDW LV GHFODUHG WR WKURZ D FKHFNHG H[FHSWLRQ 7KH H[FHSWLRQ LV WUHDWHG DV
XQFKHFNHGLQ6FDOD+RZHYHUVXSSRVHWKH6FDODPHWKRGLQTXHVWLRQGRHVQ¦WFDWFKWKH
H[FHSWLRQEXWOHWVLWSDVVWKURXJK:KDWLIWKLV6FDODPHWKRGLVFDOOHGE\RWKHU-DYD
FRGH"
/HW¦VORRNDWDQH[DPSOHLQYROYLQJjava.io.IOExceptionZKLFKLVDFKHFNHGH[FHSWLRQ
7KHIROORZLQJ6FDODFODVVSULQWVRXWWKHFRQWHQWVRIDjava.io.File
// code-examples/AppDesign/annotations/file-printer.scala

import java.io._

class FilePrinter(val file: File) {

@throws(classOf[IOException])
def print() = {
var reader: LineNumberReader = null
try {
reader = new LineNumberReader(new FileReader(file))
loop(reader)
} finally {
if (reader != null)
reader.close
}
}

private def loop(reader: LineNumberReader): Unit = {


val line = reader.readLine()
if (line != null) {
format("%3d: %s\n", reader.getLineNumber, line)
loop(reader)
}
}
}

1RWHWKH@throwsDQQRWDWLRQDSSOLHGWRWKHprintPHWKRG7KHDUJXPHQWWRWKHDQQR
WDWLRQFRQVWUXFWRULVDVLQJOHjava.lang.Class[Any]REMHFWLQWKLVFDVHclassOf[IOExcep
tion]7KH-DYD,2$3,PHWKRGVXVHGE\ printDQGWKHSULYDWHPHWKRG loopPLJKW
WKURZWKLVH[FHSWLRQ
%\WKHZD\QRWLFHWKDWloopXVHVIXQFWLRQDOVW\OHWDLOUHFXUVLRQUDWKHUWKDQDORRS1R
YDULDEOHVZHUHPXWDWHGGXULQJWKHSURGXFWLRQRIWKLVRXWSXW :HOOZHGRQ¦WDFWXDOO\
NQRZZKDW¦VKDSSHQLQJLQVLGHWKH-DYD,2FODVVHV

298 | Chapter 13:—Application Design

Download at WoweBook.Com
+HUHLVD-DYDFODVVWKDWXVHVFilePrinter,WSURYLGHVWKHmainURXWLQH
// code-examples/AppDesign/annotations/FilePrinterMain.java

import java.io.*;

public class FilePrinterMain {


public static void main(String[] args) {
for (String fileName: args) {
try {
File file = new File(fileName);
new FilePrinter(file).print();
} catch (IOException ioe) {
System.err.println("IOException for file " + fileName);
System.err.println(ioe.getMessage());
}
}
}
}

7KHVHFODVVHVFRPSLOHZLWKRXWHUURU<RXFDQWU\WKHPRXWZLWKWKHIROORZLQJFRPPDQG
ZKLFK DVVXPHV WKDW FilePrinterMain.java LV LQ WKH DQQRWDWLRQV GLUHFWRU\ DV LQ WKH
H[DPSOHFRGHGLVWULEXWLRQ 
scala -cp build FilePrinterMain annotations/FilePrinterMain.java

<RXVKRXOGJHWWKHIROORZLQJRXWSXW
1: import java.io.*;
2:
3: public class FilePrinterMain {
4: public static void main(String[] args) {
5: for (String fileName: args) {
6: try {
7: File file = new File(fileName);
8: new FilePrinter(file).print();
9: } catch (IOException ioe) {
10: System.err.println("IOException for file " + fileName);
11: System.err.println(ioe.getMessage());
12: }
13: }
14: }
15: }

1RZUHWXUQLQJWRWKHFilePrinterFODVVVXSSRVH\RXFRPPHQWRXWWKH@throwsOLQH
7KLVILOHZLOOFRQWLQXHWRFRPSLOHEXWZKHQ\RXFRPSLOH FilePrinterMain.java\RX
ZLOOJHWWKHIROORZLQJHUURU
annotations/FilePrinterMain.java:9: exception java.io.IOException is never
thrown in body of corresponding try statement
} catch (IOException ioe) {
^
1 error

Annotations | 299

Download at WoweBook.Com
(YHQWKRXJK java.io.IOExceptionPD\JHWWKURZQE\ FilePrinterWKDWLQIRUPDWLRQ
LVQ¦WLQWKHE\WHFRGHJHQHUDWHGE\ scalacVRWKHDQDO\VLVGRQHE\ javacPLVWDNHQO\
FRQFOXGHVWKDWIOExceptionLVQHYHUWKURZQ
6RWKHSXUSRVHRI@throwsLVWRLQVHUWWKHLQIRUPDWLRQRQWKURZQFKHFNHGH[FHSWLRQV
LQWRWKHE\WHFRGHWKDWjavacZLOOUHDG

,Q D PL[HG -DYD6FDOD HQYLURQPHQW FRQVLGHU DGGLQJ WKH @throws


DQQRWDWLRQIRUDOO\RXU6FDODPHWKRGVWKDWFDQWKURZ-DYDFKHFNHGH[
FHSWLRQV (YHQWXDOO\ VRPH -DYD FRGH ZLOO SUREDEO\ FDOO RQH RI WKRVH
PHWKRGV

Enumerations Versus Pattern Matching


(QXPHUDWLRQVDUHDZD\RIGHILQLQJDILQLWHVHWRIFRQVWDQWYDOXHV7KH\DUHDOLJKWZHLJKW
DOWHUQDWLYHWRFDVHFODVVHV<RXFDQUHIHUHQFHWKHYDOXHVGLUHFWO\LWHUDWHWKURXJKWKHP
LQGH[LQWRWKHPZLWKLQWHJHULQGLFHVHWF
-XVWDVIRUDQQRWDWLRQV6FDOD¦VIRUPRIHQXPHUDWLRQVDUHFODVVEDVHGZLWKDSDUWLFXODU
VHWRILGLRPVUDWKHUWKDQUHO\LQJRQVSHFLDONH\ZRUGVIRUGHILQLQJWKHPDVLVXVHGIRU
HQXPHUDWLRQVLQ-DYDDQG1(7+RZHYHU\RXFDQDOVRXVHHQXPHUDWLRQVGHILQHGLQ
WKRVHODQJXDJHV
6FDODHQXPHUDWLRQVDUHGHILQHGE\VXEFODVVLQJWKHDEVWUDFW scala.EnumerationFODVV
7KHUHDUHVHYHUDOZD\VWRFRQVWUXFWDQGXVHDQHQXPHUDWLRQ:H¦OOGHPRQVWUDWHRQH
LGLRPWKDWPRVWFORVHO\PDWFKHVWKH-DYDDQG1(7IRUPV\RXPD\DOUHDG\NQRZ
5HFDOO WKH +773 PHWKRGV VFULSWV WKDW ZH ZURWH LQ £6HDOHG &ODVV +LHUDU
FKLHV¤RQSDJH:HGHILQHGWKHVHWRI+773PHWKRGVXVLQJDVHDOHGFDVHFODVV
KLHUDUFK\
// code-examples/ObjectSystem/sealed/http-script.scala

sealed abstract class HttpMethod()


case class Connect(body: String) extends HttpMethod
case class Delete (body: String) extends HttpMethod
case class Get (body: String) extends HttpMethod
case class Head (body: String) extends HttpMethod
case class Options(body: String) extends HttpMethod
case class Post (body: String) extends HttpMethod
case class Put (body: String) extends HttpMethod
case class Trace (body: String) extends HttpMethod

def handle (method: HttpMethod) = method match {


case Connect (body) => println("connect: " + body)
case Delete (body) => println("delete: " + body)
case Get (body) => println("get: " + body)
case Head (body) => println("head: " + body)
case Options (body) => println("options: " + body)
case Post (body) => println("post: " + body)

300 | Chapter 13:—Application Design

Download at WoweBook.Com
case Put (body) => println("put: " + body)
case Trace (body) => println("trace: " + body)
}

val methods = List(


Connect("connect body..."),
Delete ("delete body..."),
Get ("get body..."),
Head ("head body..."),
Options("options body..."),
Post ("post body..."),
Put ("put body..."),
Trace ("trace body..."))

methods.foreach { method => handle(method) }

,QWKDWH[DPSOHHDFKPHWKRGKDGDbodyDWWULEXWHIRUWKHPHVVDJHERG\:H¦OODVVXPH
KHUHWKDWWKHERG\LVKDQGOHGWKURXJKRWKHUPHDQVDQGZHRQO\FDUHDERXWLGHQWLI\LQJ
WKH NLQG RI +773 PHWKRG 6R KHUH LV D 6FDOD Enumeration FODVV IRU WKH +773 
PHWKRGV
// code-examples/AppDesign/enumerations/http-enum-script.scala

object HttpMethod extends Enumeration {


type Method = Value
val Connect, Delete, Get, Head, Options, Post, Put, Trace = Value
}

import HttpMethod._

def handle (method: HttpMethod.Method) = method match {


case Connect => println("Connect: " + method.id)
case Delete => println("Delete: " + method.id)
case Get => println("Get: " + method.id)
case Head => println("Head: " + method.id)
case Options => println("Options: " + method.id)
case Post => println("Post: " + method.id)
case Put => println("Put: " + method.id)
case Trace => println("Trace: " + method.id)
}

HttpMethod foreach { method => handle(method) }


println( HttpMethod )

7KLVVFULSWSURGXFHVWKHIROORZLQJRXWSXW
Connect: 0
Delete: 1
Get: 2
Head: 3
Options: 4
Post: 5
Put: 6
Trace: 7
{Main$$anon$1$HttpMethod(0), Main$$anon$1$HttpMethod(1),
Main$$anon$1$HttpMethod(2), Main$$anon$1$HttpMethod(3),

Enumerations Versus Pattern Matching | 301

Download at WoweBook.Com
Main$$anon$1$HttpMethod(4), Main$$anon$1$HttpMethod(5),
Main$$anon$1$HttpMethod(6), Main$$anon$1$HttpMethod(7)}

:H ZUDSSHG WKH OLQHV IRU WKH RXWSXW EHWZHHQ WKH {...}  7KHUH DUH WZR XVHV RI
ValueLQWKHGHILQLWLRQRIHttpMethod7KHILUVWXVDJHLVDFWXDOO\DUHIHUHQFHWRDQDEVWUDFW
FODVVEnumeration.ValueZKLFKHQFDSVXODWHVVRPHXVHIXORSHUDWLRQVIRUWKH£YDOXHV¤
LQ WKH HQXPHUDWLRQ :H GHILQH D QHZ type Method WKDW IXQFWLRQV DV DQ DOLDV IRU
Value:HVHHLWXVHGLQWKHW\SHRIWKHDUJXPHQWSDVVHGWRWKHhandlePHWKRGZKLFK
GHPRQVWUDWHVHttpMethodLQXVHHttpMethod.MethodLVDPRUHPHDQLQJIXOQDPHWRWKH
UHDGHU WKDQ WKH JHQHULF HttpMethod.Value 1RWH WKDW RQH RI WKH ILHOGV LQ Enumera
tion.ValueLVidZKLFKZHDOVRXVHLQhandle
7KHVHFRQGXVHRIValueLVDFWXDOO\DFDOOWRDPHWKRG7KHUHLVQRQDPHVSDFHFROOLVLRQ
EHWZHHQWKHVHWZRQDPHV7KHOLQHval Connect, Delete, Get, Head, Options, Post,
Put, Trace = ValueGHILQHVWKHVHWRIYDOXHVIRUWKHHQXPHUDWLRQ7KHValuePHWKRGLV
FDOOHGIRUHDFKRQH,WFUHDWHVDQHZEnumeration.ValueIRUHDFKRQHDQGDGGVLWWRWKH
PDQDJHGVHWRIYDOXHV
,QWKHFRGHEHORZWKHGHILQLWLRQZHLPSRUWWKHGHILQLWLRQVLQHttpMethodDQGZHGHILQH
DhandlePHWKRGWKDWSDWWHUQPDWFKHVRQHttpMethod.MethodREMHFWV,WVLPSO\SULQWVD
PHVVDJHIRUHDFKYDOXHDORQJZLWKLWVid1RWHWKDWZKLOHWKHH[DPSOHKDVQR£GHIDXOW¤
FDVHFODXVH HJ case _ º... QRQHLVUHTXLUHGLQWKLVFDVH+RZHYHUWKHFRPSLOHU
GRHVQ¦WDFWXDOO\NQRZWKDWDOOWKHSRVVLEOHYDOXHVDUHFRYHUHGLQFRQWUDVWWRDVHDOHG
FDVHFODVVKLHUDUFK\,I\RXFRPPHQWRXWRQHRIWKHFDVHVWDWHPHQWVLQhandle\RXZLOO
JHWQRZDUQLQJVEXW\RXZLOOJHWDMatchError

:KHQSDWWHUQPDWFKLQJRQHQXPHUDWLRQYDOXHVWKHFRPSLOHUFDQ¦WWHOO
LIWKHPDWFKLV£H[KDXVWLYH¤

<RXPLJKWZRQGHUZK\ZHKDUGFRGHGVWULQJVOLNH£&RQQHFW¤LQWKHprintlnVWDWHPHQWV
LQWKHFDVHFODXVHV&DQ¦WZHJHWWKHQDPHIURPWKH HttpMethod.MethodREMHFWLWVHOI"
$QGZK\GLGQ¦WWKHRXWSXWRIprintln(HttpMethod)LQFOXGHWKRVHQDPHVLQVWHDGRIWKH
XJO\LQWHUQDOREMHFWQDPHV"
<RXDUHSUREDEO\DFFXVWRPHGWRXVLQJVXFKQDPHVZLWK-DYDRU1(7HQXPHUDWLRQV
8QIRUWXQDWHO\ZHFDQ¦WJHWWKRVHQDPHVIURPWKHYDOXHVLQWKH6FDODHQXPHUDWLRQDW
OHDVWJLYHQWKHZD\WKDWZHGHFODUHGHttpMethod+RZHYHUWKHUHDUHWZRZD\VZHFDQ
FKDQJHWKHLPSOHPHQWDWLRQWRJHWQDPHVWULQJV,QWKHILUVWDSSURDFKZHSDVVWKHQDPH
WRValueZKHQFUHDWLQJWKHILHOGV
// code-examples/AppDesign/enumerations/http-enum2-script.scala

object HttpMethod extends Enumeration {


type Method = Value
val Connect = Value("Connect")
val Delete = Value("Delete")
val Get = Value("Get")

302 | Chapter 13:—Application Design

Download at WoweBook.Com
val Head = Value("Head")
val Options = Value("Options")
val Post = Value("Post")
val Put = Value("Put")
val Trace = Value("Trace")
}

import HttpMethod._

def handle (method: HttpMethod.Method) = method match {


case Connect => println(method + ": " + method.id)
case Delete => println(method + ": " + method.id)
case Get => println(method + ": " + method.id)
case Head => println(method + ": " + method.id)
case Options => println(method + ": " + method.id)
case Post => println(method + ": " + method.id)
case Put => println(method + ": " + method.id)
case Trace => println(method + ": " + method.id)
}

HttpMethod foreach { method => handle(method) }


println( HttpMethod )

,WLVDELWUHGXQGDQWWRKDYHWRXVHWKHVDPHZRUGWZLFHLQGHFODUDWLRQVOLNHval Connect
= Value("Connect")
5XQQLQJWKLVVFULSWSURGXFHVWKHIROORZLQJQLFHURXWSXW
Connect: 0
Delete: 1
Get: 2
Head: 3
Options: 4
Post: 5
Put: 6
Trace: 7
{Connect, Delete, Get, Head, Options, Post, Put, Trace}

,QWKHVHFRQGDSSURDFKZHSDVVWKHOLVWRIQDPHVWRWKHEnumerationFRQVWUXFWRU
// code-examples/AppDesign/enumerations/http-enum3-script.scala

object HttpMethod extends Enumeration(


"Connect", "Delete", "Get", "Head", "Options", "Post", "Put", "Trace") {
type Method = Value
val Connect, Delete, Get, Head, Options, Post, Put, Trace = Value
}

import HttpMethod._

def handle (method: HttpMethod.Method) = method match {


case Connect => println(method + ": " + method.id)
case Delete => println(method + ": " + method.id)
case Get => println(method + ": " + method.id)
case Head => println(method + ": " + method.id)
case Options => println(method + ": " + method.id)

Enumerations Versus Pattern Matching | 303

Download at WoweBook.Com
case Post => println(method + ": " + method.id)
case Put => println(method + ": " + method.id)
case Trace => println(method + ": " + method.id)
}

HttpMethod foreach { method => handle(method) }


println( HttpMethod )

7KLVVFULSWSURGXFHVLGHQWLFDORXWSXW1RWHWKDWZHKDYHDUHGXQGDQWOLVWRIQDPHVWULQJV
DQGQDPHVRIWKHvals,WLVXSWR\RXWRNHHSWKHLWHPVLQWKHOLVWDQGWKHLURUGHUFRQVLVWHQW
ZLWKWKHGHFODUHGYDOXHV7KLVYHUVLRQKDVIHZHUFKDUDFWHUVEXWLWLVPRUHHUURUSURQH
,QWHUQDOO\EnumerationSDLUVWKHVWULQJVZLWKWKHFRUUHVSRQGLQJValueLQVWDQFHVDVWKH\
DUHFUHDWHG
7KHRXWSXWZKHQSULQWLQJWKHZKROH HttpMethodREMHFWLVEHWWHUIRUHLWKHUDOWHUQDWLYH
LPSOHPHQWDWLRQ:KHQWKHYDOXHVKDYHQDPHVWKHLUtoStringUHWXUQVWKHQDPH,QIDFW
RXU ILQDO WZR H[DPSOHV KDYH EHFRPH TXLWH DUWLILFLDO EHFDXVH ZH QRZ KDYH LGHQWLFDO
VWDWHPHQWVIRUHDFKFDVHFODXVH2IFRXUVHLQDUHDOLPSOHPHQWDWLRQ\RXZRXOGKDQGOH
WKHGLIIHUHQW+773PHWKRGVGLIIHUHQWO\

Thoughts On Annotations and Enumerations


)RUERWKDQQRWDWLRQVDQGHQXPHUDWLRQVWKHUHDUHDGYDQWDJHVDQGGLVDGYDQWDJHVWRWKH
6FDODDSSURDFKZKHUHZHXVHUHJXODUFODVVEDVHGPHFKDQLVPVUDWKHUWKDQLQYHQWLQJ
FXVWRPNH\ZRUGVDQGV\QWD[7KHDGYDQWDJHVLQFOXGHIHZHUVSHFLDOFDVHVLQWKHODQ
JXDJH &ODVVHV DQG WUDLWV DUH XVHG LQ PRUH RU OHVV WKH VDPH ZD\V WKH\ DUH XVHG IRU
£QRUPDO¤ FRGH 7KH GLVDGYDQWDJHV LQFOXGH WKH QHHG WR XQGHUVWDQG DQG XVH DG KRF
FRQYHQWLRQVWKDWDUHQRWDOZD\VDVFRQYHQLHQWWRXVHDVWKHFXVWRPV\QWD[PHFKDQLVPV
UHTXLUHGLQ-DYDDQG1(7$OVR6FDOD¦VLPSOHPHQWDWLRQVDUHQRWDVIXOOIHDWXUHG
6RVKRXOGWKH6FDODFRPPXQLW\UHOHQWDQGLPSOHPHQWDGKRFEXWPRUHIXOOIHDWXUHG
PHFKDQLVPVIRUDQQRWDWLRQVDQGHQXPHUDWLRQV"0D\EHQRW6FDODLVDPRUHIOH[LEOH
ODQJXDJHWKDQPRVWODQJXDJHV0DQ\RIWKHIHDWXUHVSURYLGHGE\-DYDDQG1(7DQ
QRWDWLRQVDQGHQXPHUDWLRQVFDQEHLPSOHPHQWHGLQ6FDODE\RWKHUPHDQV
6RPHXVHFDVHVIRUWKHPRUHDGYDQFHGIHDWXUHVRI-DYDDQQRWDWLRQVFDQEHLPSOHPHQWHG
PRUH HOHJDQWO\ ZLWK £QRUPDO¤ 6FDOD FRGH DV ZH ZLOO GLVFXVV LQ £'HVLJQ 3DW
WHUQV¤RQSDJH)RUHQXPHUDWLRQVVHDOHGFDVHFODVVHVDQGSDWWHUQPDWFKLQJSUR
YLGHDPRUHIOH[LEOHVROXWLRQLQPDQ\FDVHV

Enumerations Versus Case Classes and Pattern Matching


/HW¦VUHYLVLWWKH+773PHWKRGVFULSWZKLFKXVHVDVHDOHGFDVHFODVVKLHUDUFK\YHUVXV
WKHYHUVLRQZHZURWHSUHYLRXVO\WKDWXVHVDQEnumeration6LQFHWKHHQXPHUDWLRQYHU
VLRQGRHVQ¦WKDQGOHWKHPHVVDJHERG\OHW¦VZULWHDPRGLILHGYHUVLRQRIWKHVHDOHGFDVH
FODVV YHUVLRQ WKDW LV FORVHU WR WKH HQXPHUDWLRQ YHUVLRQ LH LW DOVR GRHVQ¦W KROG WKH
PHVVDJHERG\DQGLWKDVnameDQGidPHWKRGV

304 | Chapter 13:—Application Design

Download at WoweBook.Com
// code-examples/AppDesign/enumerations/http-case-script.scala

sealed abstract class HttpMethod(val id: Int) {


def name = getClass getSimpleName
override def toString = name
}

case object Connect extends HttpMethod(0)


case object Delete extends HttpMethod(1)
case object Get extends HttpMethod(2)
case object Head extends HttpMethod(3)
case object Options extends HttpMethod(4)
case object Post extends HttpMethod(5)
case object Put extends HttpMethod(6)
case object Trace extends HttpMethod(7)

def handle (method: HttpMethod) = method match {


case Connect => println(method + ": " + method.id)
case Delete => println(method + ": " + method.id)
case Get => println(method + ": " + method.id)
case Head => println(method + ": " + method.id)
case Options => println(method + ": " + method.id)
case Post => println(method + ": " + method.id)
case Put => println(method + ": " + method.id)
case Trace => println(method + ": " + method.id)
}

List(Connect, Delete, Get, Head, Options, Post, Put, Trace) foreach {


method => handle(method)
}

1RWHWKDWZHXVHG case objectIRUDOOWKHFRQFUHWHVXEFODVVHVWRKDYHDWUXHVHWRI


FRQVWDQWV7RPLPLFWKHHQXPHUDWLRQ idZHDGGHGDILHOGH[SOLFLWO\EXWQRZLW¦VXS
WRXVWRSDVVLQYDOLGXQLTXHYDOXHV7KHhandlePHWKRGVLQWKHWZRLPSOHPHQWDWLRQV
DUHQHDUO\LGHQWLFDO
7KLVVFULSWRXWSXWVWKHIROORZLQJ
Main$$anon$1$Connect$: 0
Main$$anon$1$Delete$: 1
Main$$anon$1$Get$: 2
Main$$anon$1$Head$: 3
Main$$anon$1$Options$: 4
Main$$anon$1$Post$: 5
Main$$anon$1$Put$: 6
Main$$anon$1$Trace$: 7

7KHREMHFWQDPHVDUHXJO\EXWZHFRXOGSDUVHWKHVWULQJDQGUHPRYHWKHVXEVWULQJZH
UHDOO\FDUHDERXW
%RWKDSSURDFKHVVXSSRUWWKHFRQFHSWRIDILQLWHDQGIL[HGVHWRIYDOXHVDVORQJDVWKH
FDVHFODVVKLHUDUFK\LVVHDOHG$QDGGLWLRQDODGYDQWDJHRIDVHDOHGFDVHFODVVKLHUDUFK\
LV WKH IDFW WKDW WKH FRPSLOHU ZLOO ZDUQ \RX LI SDWWHUQ PDWFKLQJ VWDWHPHQWV DUHQ¦W

Thoughts On Annotations and Enumerations | 305

Download at WoweBook.Com
H[KDXVWLYH7U\UHPRYLQJRQHRIWKHFDVHFODXVHVDQG\RX¦OOJHWWKHXVXDOZDUQLQJ7KH
FRPSLOHUFDQ¦WGRWKLVZLWKHQXPHUDWLRQVDVZHVDZ
7KHHQXPHUDWLRQIRUPDWLVPRUHVXFFLQFWGHVSLWHWKHQDPHGXSOLFDWLRQZHKDGWRXVH
DQGLWDOVRVXSSRUWVWKHDELOLW\WRLWHUDWHWKURXJKWKHYDOXHV:HKDGWRGRWKDWPDQXDOO\
LQWKHFDVHFODXVHLPSOHPHQWDWLRQ
7KHFDVHFODVVLPSOHPHQWDWLRQQDWXUDOO\DFFRPPRGDWHVRWKHUILHOGVHJWKHbodyDV
LQWKHRULJLQDOLPSOHPHQWDWLRQZKLOHHQXPHUDWLRQVFDQRQO\DFFRPPRGDWHFRQVWDQW
ValuesZLWKDVVRFLDWHGQDPHVDQG,'V

)RUFDVHVZKHUH\RXQHHGRQO\DVLPSOHOLVWRIFRQVWDQWVE\QDPHRU,'
QXPEHUXVHHQXPHUDWLRQV%HFDUHIXOWRIROORZWKHXVDJHLGLRPV)RU
IL[HGVHWVRIPRUHFRPSOH[FRQVWDQWREMHFWVXVHVHDOHGFDVHREMHFWV

Using Nulls Versus Options


:KHQ ZH LQWURGXFHG Option LQ £2SWLRQ 6RPH DQG 1RQH $YRLGLQJ
QXOOV¤RQSDJHZHEULHIO\GLVFXVVHGKRZLWHQFRXUDJHVDYRLGLQJnullUHIHUHQFHVLQ
\RXUFRGHZKLFK7RQ\+RDUHZKRLQWURGXFHGWKHFRQFHSWRInullLQFDOOHGKLV
£ELOOLRQGROODUPLVWDNH¤ VHH>+RDUH@ 
6FDODKDVWRVXSSRUWnullEHFDXVHnullLVVXSSRUWHGRQERWKWKH-90DQG1(7DQG
RWKHUOLEUDULHVXVHnull,QIDFWnullLVXVHGE\VRPH6FDODOLEUDULHV
:KDWLI nullZHUHQRWDYDLODEOH"+RZZRXOGWKDWFKDQJH\RXUGHVLJQV"7KH Map$3,
RIIHUVVRPHXVHIXOH[DPSOHV&RQVLGHUWKHVHWZRMapPHWKRGV
trait Map[A,+B] {
...
def get(key: A) : Option[B]
def getOrElse [B2 >: B](key : A, default : => B2) : B2 = ...
...
}

$PDSPD\QRWKDYHDYDOXHIRUDSDUWLFXODUNH\%RWKRIWKHVHPHWKRGVDYRLGUHWXUQLQJ
nullLQWKDWFDVH&RQFUHWHLPSOHPHQWDWLRQVRI getLQVXEFODVVHVUHWXUQD NoneLIQR
YDOXHH[LVWVIRUWKHNH\2WKHUZLVHWKH\UHWXUQDSomeZUDSSLQJWKHYDOXH7KHPHWKRG
VLJQDWXUHWHOOV\RXWKDWDYDOXHPLJKWQRWH[LVWDQGLWIRUFHV\RXWRKDQGOHWKDWVLWXDWLRQ
JUDFHIXOO\
val stateCapitals = Map("Alabama" -> "Montgomery", ...)
...

stateCapitals.get("North Hinterlandia") match {


case None => println ("No such state!")
case Some(x) => println(x)
}

306 | Chapter 13:—Application Design

Download at WoweBook.Com
6LPLODUO\getOrElseIRUFHV\RXWRGHVLJQGHIHQVLYHO\<RXKDYHWRVSHFLI\DGHIDXOWYDOXH
IRUZKHQDNH\LVQ¦WLQWKHPDS1RWHWKDWWKHGHIDXOWYDOXHFDQDFWXDOO\EHDQLQVWDQFH
RIDVXSHUW\SHUHODWLYHWRWKHPDS¦VYDOXHW\SH
println(stateCapitals.getOrElse("North Hinterlandia", "No such state!"))

$ORWRI-DYDDQG1(7$3,VDOORZnullPHWKRGDUJXPHQWVDQGFDQUHWXUQnullYDOXHV
<RXFDQZULWH6FDODZUDSSHUVDURXQGWKHPWRLPSOHPHQWDQDSSURSULDWHVWUDWHJ\IRU
KDQGOLQJnulls
)RU H[DPSOH OHW¦V UHYLVLW RXU SUHYLRXV ILOH SULQWLQJ H[DPSOH IURP £$QQRWD
WLRQV¤ RQ SDJH  :H¦OO UHIDFWRU RXU FilePrinter FODVV DQG WKH -DYD GULYHU LQWR D
FRPELQHGVFULSW:H¦OODGGUHVVWZRLVVXHV ZUDSLineNumberReader.readLineZLWKD
PHWKRGWKDWUHWXUQVDQ OptionLQVWHDGRI nullDQG ZUDSFKHFNHG IOExceptionsLQ
RXURZQXQFKHFNHGH[FHSWLRQFDOOHGScalaIOException
// code-examples/AppDesign/options-nulls/file-printer-refactored-script.scala

import java.io._

class ScalaIOException(cause: Throwable) extends RuntimeException(cause)

class ScalaLineNumberReader(in: Reader) extends LineNumberReader(in) {


def inputLine() = readLine() match {
case null => None
case line => Some(line)
}
}

object ScalaLineNumberReader {
def apply(file: File) = try {
new ScalaLineNumberReader(new FileReader(file))
} catch {
case ex: IOException => throw new ScalaIOException(ex)
}
}

class FilePrinter(val file: File) {


def print() = {
val reader = ScalaLineNumberReader(file)
try {
loop(reader)
} finally {
if (reader != null)
reader.close
}
}

private def loop(reader: ScalaLineNumberReader): Unit = {


reader.inputLine() match {
case None =>
case Some(line) => {
format("%3d: %s\n", reader.getLineNumber, line)
loop(reader)

Using Nulls Versus Options | 307

Download at WoweBook.Com
}
}
}
}

// Process the command-line arguments (file names):


args.foreach { fileName =>
new FilePrinter(new File(fileName)).print();
}

7KH ScalaLineNumberReader FODVV GHILQHV D QHZ PHWKRG inputLine WKDW FDOOV


LineNumberReader.readLine DQG SDWWHUQ PDWFKHV WKH UHVXOW ,I null WKHQ None LV UH
WXUQHG2WKHUZLVHWKHOLQHLVUHWXUQHGZUDSSHGLQDSome[String]
ScalaIOExceptionLVDVXEFODVVRI RuntimeExceptionVRLWLVXQFKHFNHG:HXVHLWWR
ZUDSDQ\IOExceptionsWKURZQLQScalaLineNumberReader.apply
7KH UHIDFWRUHG FilePrinter FODVV XVHV ScalaLineNumberReader.apply LQ LWV print
PHWKRG,WXVHVScalaLineNumberReader.inputLineLQLWVloopPHWKRG:KLOHWKHRULJ
LQDOYHUVLRQSURSHUO\KDQGOHGWKHFDVHRI LineNumberReader.readLineUHWXUQLQJ null
QRZWKHXVHURIScalaLineNumberReaderKDVQRFKRLFHEXWWRKDQGOHDNoneUHWXUQYDOXH
7KHVFULSWHQGVZLWKDORRSRYHUWKHLQSXWDUJXPHQWVZKLFKDUHVWRUHGDXWRPDWLFDOO\
LQWKHargsYDULDEOH(DFKDUJXPHQWLVWUHDWHGDVDILOHQDPHWREHSULQWHG7KHVFULSW
ZLOOSULQWLWVHOIZLWKWKHIROORZLQJFRPPDQG
scala file-printer-refactored-script.scala file-printer-refactored-script.scala

Options and for Comprehensions


7KHUH LV RQH RWKHU EHQHILW RI XVLQJ Options ZLWK for FRPSUHKHQVLRQV DXWRPDWLF
UHPRYDORINoneHOHPHQWVIURPFRPSUHKHQVLRQVXQGHUPRVWFRQGLWLRQV UHIHUWR>3RO
ODN@ DQG >6SLHZDNF@  &RQVLGHU WKLV ILUVW YHUVLRQ RI D VFULSW WKDW XVHV
OptionsLQDforFRPSUHKHQVLRQ
// code-examples/AppDesign/options-nulls/option-for-comp-v1-script.scala

case class User(userName: String, name: String, email: String, bio: String)

val newUserProfiles = List(


Map("userName" -> "twitspam", "name" -> "Twit Spam"),
Map("userName" -> "bucktrends", "name" -> "Buck Trends",
"email" -> "thebuck@stops.he.re", "bio" -> "World's greatest bloviator"),
Map("userName" -> "lonelygurl", "name" -> "Lonely Gurl",
"bio" -> "Obviously fake..."),
Map("userName" -> "deanwampler", "name" -> "Dean Wampler",
"email" -> "dean@....com", "bio" -> "Scala passionista"),
Map("userName" -> "al3x", "name" -> "Alex Payne",
"email" -> "al3x@....com", "bio" -> "Twitter API genius"))

// Version #1

var validUsers = for {

308 | Chapter 13:—Application Design

Download at WoweBook.Com
user <- newUserProfiles
if (user.contains("userName") && user.contains("name") && // #1
user.contains("email") && user.contains("bio")) // #1
userName <- user get "userName"
name <- user get "name"
email <- user get "email"
bio <- user get "bio" }
yield User(userName, name, email, bio)

validUsers.foreach (user => println(user))

,PDJLQHWKLVFRGHLVXVHGLQVRPHVRUWRIVRFLDOQHWZRUNLQJVLWH1HZXVHUVVXEPLW
SURILOHGDWDZKLFKLVSDVVHGWRWKLVVHUYLFHLQEXONIRUSURFHVVLQJ)RUH[DPSOHZH
KDUGFRGHGDOLVWRIVXEPLWWHGSURILOHVZKHUHHDFKSURILOHGDWDVHWLVDPDS7KHPDS
PLJKWKDYHEHHQFRSLHGIURPDQ+773VHVVLRQ
7KHVHUYLFHILOWHUVRXWLQFRPSOHWHSURILOHV PLVVLQJILHOGV VKRZQZLWKWKHFRP
PHQWVDQGFUHDWHVQHZXVHUREMHFWVIURPWKHFRPSOHWHSURILOHV
5XQQLQJWKHVFULSWSULQWVRXWWKUHHQHZXVHUVIURPWKHILYHVXEPLWWHGSURILOHV
User(bucktrends,Buck Trends,thebuck@stops.he.re,World's greatest bloviator)
User(deanwampler,Dean Wampler,dean@....com,Scala passionista)
User(al3x,Alex Payne,al3x@....com,Twitter API genius)

1RZGHOHWHWKHWZROLQHVZLWKWKHFRPPHQW
...
var validUsers = for {
user <- newUserProfiles
userName <- user get "userName"
name <- user get "name"
email <- user get "email"
bio <- user get "bio" }
yield User(userName, name, email, bio)

validUsers.foreach (user => println(user))

%HIRUH\RXUHUXQWKHVFULSWZKDWGR\RXH[SHFWWRKDSSHQ":LOOLWSULQWILYHOLQHVZLWK
VRPHILHOGVHPSW\ RUFRQWDLQLQJRWKHUNLQGVRIYDOXHV "
,WSULQWVWKHVDPHWKLQJ+RZGLGLWGRWKHILOWHULQJZHZDQWHGZLWKRXWWKHH[SOLFLW
FRQGLWLRQDO"
7KHDQVZHUOLHVLQWKHZD\WKDWforFRPSUHKHQVLRQVDUHLPSOHPHQWHG+HUHDUHDFRXSOH
RI VLPSOH IRU FRPSUHKHQVLRQV IROORZHG E\ WKHLU WUDQVODWLRQV VHH >6FDOD6SHF@ 
)LUVWZH¦OOORRNDWDVLQJOHJHQHUDWRUZLWKDyield
for (p1 <- e1) yield e2 // for comprehension

e1 map ( case p1 => e2 ) // translation

+HUH¦VWKHWUDQVODWLRQRIDVLQJOHJHQHUDWRUIROORZHGE\DQDUELWUDU\H[SUHVVLRQ ZKLFK
FRXOGEHVHYHUDOH[SUHVVLRQVLQEUDFHVHWF 

Using Nulls Versus Options | 309

Download at WoweBook.Com
for (p1 <- e1) e2 // for comprehension

e1 foreach ( case p1 => e2 ) // translation

:LWKPRUHWKDQRQHJHQHUDWRUmapLVUHSODFHGZLWKflatMapLQWKHyieldH[SUHVVLRQV
EXWforeachLVXQFKDQJHG
for (p1 <- e1; p2 <- e2 ...) yield eN // for comprehension

e1 flatMap ( case p1 => for (p2 <- e2 ...) yield eN ) // translation


for (p1 <- e1; p2 <- e2 ...) eN // for comprehension

e1 foreach ( case p1 => for (p2 <- e2 ...) eN ) // translation

1RWHWKDWWKHVHFRQGWKURXJKWKH1WKJHQHUDWRUVEHFRPHQHVWHGIRUFRPSUHKHQVLRQV
WKDWQHHGWUDQVODWLQJ
7KHUH DUH VLPLODU WUDQVODWLRQV IRU FRQGLWLRQDO VWDWHPHQWV ZKLFK EHFRPH FDOOV WR
filter DQGvalDVVLJQPHQWV:HZRQ¦WVKRZWKHPKHUHVLQFHRXUSULPDU\SXUSRVHLV
WR GHVFULEH MXVW HQRXJK RI WKH LPSOHPHQWDWLRQ GHWDLOV VR \RX FDQ XQGHUVWDQG KRZ
OptionsDQG forFRPSUHKHQVLRQVZRUNWRJHWKHU7KHDGGLWLRQDOGHWDLOVDUHGHVFULEHG
LQ>6FDOD6SHF@ZLWKH[DPSOHV
,I\RXIROORZWKLVWUDQVODWLRQSURFHVVRQRXUH[DPSOH\RXJHWWKHIROORZLQJH[SDQVLRQ
var validUsers = newUserProfiles flatMap {
case user => user.get("userName") flatMap {
case userName => user.get("name") flatMap {
case name => user.get("email") flatMap {
case email => user.get("bio") map {
case bio => User(name, userName, email, bio) // #1
}
}
}
}
}

1RWH WKDW ZH KDYH flatMap FDOOV XQWLO WKH PRVW QHVWHG FDVH ZKHUH map LV XVHG
flatMapDQGmapEHKDYHHTXLYDOHQWO\LQWKLVFDVH 
1RZZHFDQXQGHUVWDQGZK\WKHELJFRQGLWLRQDOZDVXQQHFHVVDU\5HFDOOWKDWuserLV
DMapDQGuser.get("...")UHWXUQVDQOptionHLWKHUNoneRUSome(value)7KHNH\LVWKH
EHKDYLRURIflatMapGHILQHGRQOptionZKLFKOHWVXVWUHDWOptionsOLNHRWKHUFROOHFWLRQV
+HUHLVWKHGHILQLWLRQRIflatMap
def flatMap[B](f: A => Option[B]): Option[B] =
if (isEmpty) None else f(this.get)

,Iuser.get("...")UHWXUQVNoneWKHQflatMapVLPSO\UHWXUQVNoneDQGQHYHUHYDOXDWHV
WKHIXQFWLRQOLWHUDO+HQFHWKHQHVWHGLWHUDWLRQVVLPSO\VWRSDQGQHYHUJHWWRWKHOLQH
PDUNHGZLWKWKHFRPPHQWZKHUHWKHUserLVFUHDWHG
7KH RXWHUPRVW flatMap LV RQ WKH LQSXW List newUserProfiles 2Q D PXOWLHOHPHQW
FROOHFWLRQOLNHWKLVWKHEHKDYLRURI flatMapLVVLPLODUWR mapEXWLWIODWWHQVWKHQHZ

310 | Chapter 13:—Application Design

Download at WoweBook.Com
FROOHFWLRQDQGGRHVQ¦WUHTXLUHWKHUHVXOWLQJPDSWRKDYHWKHVDPHQXPEHURIHOHPHQWV
DVWKHRULJLQDOFROOHFWLRQOLNHmapGRHV
)LQDOO\ UHFDOO IURP £3DUWLDO )XQFWLRQV¤ RQ SDJH  WKDW WKH case user => ...
VWDWHPHQWVIRUH[DPSOHFDXVHWKHFRPSLOHUWRJHQHUDWHD PartialFunctionWRSDVVWR
flatMapDQGmapVRQRFRUUHVSRQGLQJfoo match {...}VW\OHZUDSSHUVDUHQHFHVVDU\

8VLQJ Options ZLWK for FRPSUHKHQVLRQV HOLPLQDWH WKH QHHG IRU PRVW
£QXOOHPSW\¤FKHFNV

Exceptions and the Alternatives


,InullsDUHWKH£ELOOLRQGROODUPLVWDNH¤DVZHGLVFXVVHGLQ£2SWLRQ6RPHDQG1RQH
$YRLGLQJQXOOV¤RQSDJHWKHQZKDWDERXWH[FHSWLRQV"<RXFDQDUJXHWKDW nulls
VKRXOGQHYHURFFXUDQG\RXFDQGHVLJQDODQJXDJHDQGOLEUDULHVWKDWQHYHUXVHWKHP
+RZHYHUH[FHSWLRQVKDYHDOHJLWLPDWHSODFHEHFDXVHWKH\VHSDUDWHWKHFRQFHUQVRIQRU
PDOSURJUDPIORZIURP£H[FHSWLRQDO¤SURJUDPIORZ7KHGLYLGHLVQ¦WDOZD\VFOHDUFXW
)RUH[DPSOHLIDXVHUPLVW\SHVKLVXVHUQDPHLVWKDWQRUPDORUH[FHSWLRQDO"
$QRWKHUTXHVWLRQLVZKHUHVKRXOGWKHH[FHSWLRQEHFDXJKWDQGKDQGOHG"-DYD¦VFKHFNHG
H[FHSWLRQV ZHUH GHVLJQHG WR GRFXPHQW IRU WKH $3, XVHU ZKDW H[FHSWLRQV PLJKW EH
WKURZQE\DPHWKRG7KHIODZZDVWKDWLWHQFRXUDJHGKDQGOLQJRIWKHH[FHSWLRQLQZD\V
WKDW DUH RIWHQ VXERSWLPDO ,I RQH PHWKRG FDOOV DQRWKHU PHWKRG WKDW PLJKW WKURZ D
FKHFNHGH[FHSWLRQWKHFDOOLQJPHWKRGLVIRUFHGWRHLWKHUKDQGOHWKHH[FHSWLRQRUGH
FODUHWKDWLWDOVRWKURZVWKHH[FHSWLRQ0RUHRIWHQWKDQQRWWKHFDOOLQJPHWKRGLVWKH
ZURQJSODFHWRKDQGOHWKHH[FHSWLRQ,WLVWRRFRPPRQIRUPHWKRGVWRVLPSO\£HDW¤DQ
H[FHSWLRQWKDWVKRXOGUHDOO\EHSDVVHGXSWKHVWDFNDQGKDQGOHGLQDPRUHDSSURSULDWH
FRQWH[W2WKHUZLVHthrowsGHFODUDWLRQVDUHUHTXLUHGXSWKHVWDFNRIPHWKRGFDOOV7KLV
LVQRWRQO\WHGLRXVEXWLWSROOXWHVWKHLQWHUPHGLDWHFRQWH[WVZLWKH[FHSWLRQQDPHVWKDW
RIWHQKDYHQRFRQQHFWLRQWRWKHORFDOFRQWH[W
$VZHKDYHVHHQ6FDODGRHVQ¦WKDYHFKHFNHGH[FHSWLRQV$Q\H[FHSWLRQFDQSURSDJDWH
WRWKHSRLQWZKHUHLWLVPRVWDSSURSULDWHWRKDQGOHLW+RZHYHUGHVLJQGLVFLSOLQHLV
UHTXLUHGWRLPSOHPHQWKDQGOHUVLQWKHDSSURSULDWHSODFHVIRUDOOH[FHSWLRQVIRUZKLFK
UHFRYHU\LVSRVVLEOH
(YHU\QRZDQGWKHQDQDUJXPHQWHUXSWVDPRQJGHYHORSHUVLQDSDUWLFXODUODQJXDJH
FRPPXQLW\DERXWZKHWKHURUQRWLW¦V2.WRXVHH[FHSWLRQVDVDFRQWUROIORZPHFKDQLVP
IRUQRUPDOSURFHVVLQJ6RPHWLPHVWKLVXVHRIH[FHSWLRQVLVVHHQDVDXVHIXOlongjumpRU
QRQORFDO gotoPHFKDQLVPIRUH[LWLQJRXWRIDGHHSO\QHVWHGVFRSH2QHUHDVRQWKLV
GHEDWHSRSVXSLVWKDWWKLVXVHRIH[FHSWLRQVLVVRPHWLPHVPRUHHIILFLHQWWKDQDPRUH
£FRQYHQWLRQDO¤LPSOHPHQWDWLRQ

Exceptions and the Alternatives | 311

Download at WoweBook.Com
)RUH[DPSOH\RXPLJKWLPSOHPHQW Iterable.foreachWREOLQGO\WUDYHUVHDFROOHFWLRQ
DQG VWRS ZKHQ LW FDWFKHV ZKDWHYHU H[FHSWLRQ LQGLFDWHV LW ZHQW SDVW WKH HQG RI WKH
FROOHFWLRQ
:KHQLWFRPHVWRDSSOLFDWLRQGHVLJQFRPPXQLFDWLQJLQWHQWLVYHU\LPSRUWDQW8VLQJ
H[FHSWLRQVDVDgotoPHFKDQLVPEUHDNVWKHSULQFLSOHRIOHDVWVXUSULVH,WZLOOEHUDUHWKDW
WKHSHUIRUPDQFHJDLQZLOOMXVWLI\WKHORVVRIFODULW\VRZHHQFRXUDJH\RXWRXVHH[FHS
WLRQVRQO\IRUWUXO\£H[FHSWLRQDO¤FRQGLWLRQV1RWHWKDW5XE\DFWXDOO\SURYLGHVDQRQ
ORFDOgotoOLNHPHFKDQLVP,Q5XE\WKHNH\ZRUGVthrowDQGcatchDUHDFWXDOO\UHVHUYHG
IRUWKLVSXUSRVHZKLOHraiseDQGrescueDUHWKHNH\ZRUGVIRUUDLVLQJDQH[FHSWLRQDQG
KDQGOLQJLW
:KDWHYHU\RXUYLHZRQWKHSURSHUXVHRIH[FHSWLRQVZKHQ\RXGHVLJQ$3,VPLQLPL]LQJ
WKHSRVVLELOLW\RIUDLVLQJDQH[FHSWLRQZLOOEHQHILW\RXUXVHUV7KLVLVWKHIOLSVLGHRIDQ
H[FHSWLRQKDQGOLQJVWUDWHJ\SUHYHQWLQJWKHPLQWKHILUVWSODFHOptionFDQKHOS
&RQVLGHUWZRPHWKRGVRQSeqfirstDQGfirstOption
trait Seq[+A] {
...
def first : A = ...
def firstOption : Option[A] = ...
...
}

7KHfirstPHWKRGWKURZVDPredef.UnsupportedOperationExceptionLIWKHVHTXHQFHLV
HPSW\5HWXUQLQJ nullLQWKLVFDVHLVQ¦WDQRSWLRQEHFDXVHWKHVHTXHQFHFRXOGKDYH
null HOHPHQWV ,Q FRQWUDVW WKH firstOption PHWKRG UHWXUQV DQ Option VR LW UHWXUQV
NoneLIWKHVHTXHQFHLVHPSW\ZKLFKLVXQDPELJXRXV
<RXFRXOGDUJXHWKDWWKHSeq$3,ZRXOGEHPRUHUREXVWLILWRQO\KDGD£ILUVW¤PHWKRG
WKDWUHWXUQHGDQOption,W¦VXVHIXOWRDVN\RXUVHOI£+RZFDQ,SUHYHQWWKHXVHUIURP
HYHUIDLOLQJ"¤:KHQ£IDLOXUH¤FDQ¦WEHSUHYHQWHGXVH OptionRUDVLPLODUFRQVWUXFWWR
GRFXPHQWIRUWKHXVHUWKDWDIDLOXUHPRGHLVSRVVLEOH7KLQNLQJLQWHUPVRIYDOLGVWDWH
WUDQVIRUPDWLRQVWKHfirstPHWKRGZKLOHFRQYHQLHQWLVQ¦WUHDOO\YDOLGIRUDVHTXHQFH
LQDQHPSW\VWDWH6KRXOGWKH£ILUVW¤PHWKRGVQRWH[LVWIRUWKLVUHDVRQ"7KLVFKRLFHLV
SUREDEO\WRRGUDFRQLDQEXWE\UHWXUQLQJ OptionIURP firstOptionWKH$3,FRPPX
QLFDWHVWRWKHXVHUWKDWWKHUHDUHFLUFXPVWDQFHVZKHQWKHPHWKRGFDQ¦WVDWLVI\WKHUH
TXHVWDQGLW¦VXSWRWKHXVHUWRUHFRYHUJUDFHIXOO\,QWKLVVHQVHfirstOptionWUHDWVDQ
HPSW\VHTXHQFHDVDQRQH[FHSWLRQDOVLWXDWLRQ
5HFDOOWKDWZHVDZDQRWKHUH[DPSOHRIWKLVGHFLVLRQWUDGHRIILQ£2SWLRQ6RPHDQG
1RQH$YRLGLQJQXOOV¤RQSDJH:HGLVFXVVHGWZRPHWKRGVRQOptionIRUUHWULHYLQJ
WKHYDOXHDQLQVWDQFHZUDSV ZKHQWKHLQVWDQFHLVDFWXDOO\D Some 7KH getPHWKRG
WKURZVDQH[FHSWLRQLIWKHUHLVQRYDOXHLHWKHOptionLQVWDQFHLVDFWXDOO\None7KH
RWKHU PHWKRG getOrElse WDNHV D VHFRQG DUJXPHQW D GHIDXOW YDOXH WR UHWXUQ LI WKH
OptionLVDFWXDOO\None,QWKLVFDVHQRH[FHSWLRQLVWKURZQ

312 | Chapter 13:—Application Design

Download at WoweBook.Com
2IFRXUVHLWLVLPSRVVLEOHWRDYRLGDOOH[FHSWLRQV3DUWRIWKHRULJLQDOLQWHQWRIFKHFNHG
YHUVXVXQFKHFNHGH[FHSWLRQVZDVWRGLVWLQJXLVKEHWZHHQSRWHQWLDOO\UHFRYHUDEOHSURE
OHPVDQGFDWDVWURSKLFIDLOXUHVOLNHRXWRIPHPRU\HUURUV
+RZHYHUWKHDOWHUQDWLYHPHWKRGVLQ SeqDQG OptionVKRZDZD\WR£HQFRXUDJH¤WKH
XVHURIDQ$3,WRFRQVLGHUWKHFRQVHTXHQFHVRIDSRVVLEOHIDLOXUHOLNHDVNLQJIRUWKH
ILUVWHOHPHQWLQDQHPSW\VHTXHQFH7KHXVHUFDQVSHFLI\WKHFRQWLQJHQF\LQWKHHYHQW
WKDWDIDLOXUHRFFXUV0LQLPL]LQJWKHSRVVLELOLW\RIH[FHSWLRQVZLOOLPSURYHWKHUREXVW
QHVVRI\RXU6FDODOLEUDULHVDQGWKHDSSOLFDWLRQVWKDWXVHWKHP

Scalable Abstractions
,WKDVEHHQDJRDOIRUVRPHWLPHLQRXULQGXVWU\WRFUHDWHUHXVDEOHFRPSRQHQWV8Q
IRUWXQDWHO\WKHUHLVOLWWOHDJUHHPHQWRQWKHPHDQLQJRIWKHWHUPFRPSRQHQWQRURQD
UHODWHGWHUPPRGXOH ZKLFKVRPHSHRSOHFRQVLGHUV\QRQ\PRXVZLWKFRPSRQHQW 3UR
SRVHGGHILQLWLRQVXVXDOO\VWDUWZLWKDVVXPSWLRQVDERXWWKHSODWIRUPJUDQXODULW\GH
SOR\PHQWDQGFRQILJXUDWLRQVFHQDULRVYHUVLRQLQJLVVXHVHWF VHH>6]\SHUVNL@ 
:H¦OODYRLGWKDWGLVFXVVLRQDQGXVHWKHWHUPFRPSRQHQWLQIRUPDOO\WRUHIHUWRDJURXSLQJ
RIW\SHVDQGSDFNDJHVWKDWH[SRVHVFRKHUHQWDEVWUDFWLRQV SUHIHUDEO\MXVWRQH IRUWKH
VHUYLFHVLWRIIHUVWKDWKDVPLQLPDOFRXSOLQJWRRWKHUFRPSRQHQWVDQGWKDWLVLQWHUQDOO\
FRKHVLYH
$OOODQJXDJHVRIIHUPHFKDQLVPVIRUGHILQLQJFRPSRQHQWVDWOHDVWWRVRPHGHJUHH2E
MHFWVDUHWKHSULPDU\HQFDSVXODWLRQPHFKDQLVPLQREMHFWRULHQWHGODQJXDJHV+RZHYHU
REMHFWVDORQHDUHQ¦WHQRXJKEHFDXVHZHTXLFNO\ILQGWKDWREMHFWVQDWXUDOO\FOXVWHUWR
JHWKHULQWRPRUHFRDUVHJUDLQHGDJJUHJDWHVHVSHFLDOO\DVRXUDSSOLFDWLRQVJURZ*HQ
HUDOO\VSHDNLQJDQREMHFWLVQ¦WQHFHVVDULO\DFRPSRQHQWDQGDFRPSRQHQWPD\FRQWDLQ
PDQ\REMHFWV6FDODDQG-DYDRIIHUSDFNDJHVIRUDJJUHJDWLQJW\SHV5XE\PRGXOHVVHUYH
DVLPLODUSXUSRVHDVGR&DQG&QDPHVSDFHV
+RZHYHUWKHVHSDFNDJLQJPHFKDQLVPVVWLOOKDYHOLPLWDWLRQV$FRPPRQSUREOHPLV
WKDWWKH\GRQ¦WFOHDUO\GHILQHZKDWLVSXEOLFO\YLVLEOHRXWVLGHWKHFRPSRQHQWERXQGDU\
DQGZKDWLVLQWHUQDOWRWKHFRPSRQHQW)RUH[DPSOHLQ-DYDDQ\SXEOLFW\SHRUSXEOLF
PHWKRGRQDSXEOLFW\SHLVYLVLEOHRXWVLGHWKHSDFNDJHERXQGDU\WRHYHU\RWKHUFRP
SRQHQW<RXFDQPDNHW\SHVDQGPHWKRGV£SDFNDJHSULYDWH¤EXWWKHQWKH\DUHLQYLVLEOH
WRRWKHUSDFNDJHVHQFDSVXODWHGLQWKHFRPSRQHQW-DYDGRHVQ¦WKDYHDFOHDUVHQVHRI
FRPSRQHQWERXQGDULHV
6FDODSURYLGHVDQXPEHURIPHFKDQLVPVWKDWLPSURYHWKLVVLWXDWLRQ:HKDYHVHHQPDQ\
RIWKHPDOUHDG\

Scalable Abstractions | 313

Download at WoweBook.Com
Fine-Grained Visibility Rules
:HVDZLQ£9LVLELOLW\5XOHV¤RQSDJHWKDW6FDODSURYLGHVPRUHILQHJUDLQHGYLVLELOLW\
UXOHVWKDQPRVWRWKHUODQJXDJHV<RXFDQFRQWUROWKHYLVLELOLW\RIW\SHVDQGPHWKRGV
RXWVLGHW\SHDQGSDFNDJHERXQGDULHV
&RQVLGHUWKHIROORZLQJH[DPSOHRIDFRPSRQHQWLQSDFNDJHencodedstring
// code-examples/AppDesign/abstractions/encoded-string.scala

package encodedstring {

trait EncodedString {
protected[encodedstring] val string: String
val separator: EncodedString.Separator.Delimiter

override def toString = string

def toTokens = string.split(separator.toString).toList


}

object EncodedString {
object Separator extends Enumeration {
type Delimiter = Value
val COMMA = Value(",")
val TAB = Value("\t")
}

def apply(s: String, sep: Separator.Delimiter) = sep match {


case Separator.COMMA => impl.CSV(s)
case Separator.TAB => impl.TSV(s)
}

def unapply(es: EncodedString) = Some(Pair(es.string, es.separator))


}

package impl {
private[encodedstring] case class CSV(override val string: String)
extends EncodedString {
override val separator = EncodedString.Separator.COMMA
}

private[encodedstring] case class TSV(override val string: String)


extends EncodedString {
override val separator = EncodedString.Separator.TAB
}
}
}

7KLV H[DPSOH HQFDSVXODWHV KDQGOLQJ RI VWULQJV HQFRGLQJ FRPPDVHSDUDWHG YDOXHV


&69V  RU WDEVHSDUDWHG YDOXHV 769V  7KH encodedstring SDFNDJH H[SRVHV D WUDLW
EncodedStringWKDWLVYLVLEOHWRFOLHQWV7KHFRQFUHWHFODVVHVLPSOHPHQWLQJ&69VDQG
769V DUH GHFODUHG private[encodedstring] LQ WKH encodedstring.impl SDFNDJH 7KH
WUDLWGHILQHVWZRDEVWUDFWvalILHOGVRQHWRKROGWKHHQFRGHGstringZKLFKLVSURWHFWHG

314 | Chapter 13:—Application Design

Download at WoweBook.Com
IURPFOLHQWDFFHVVDQGWKHRWKHUWRKROGWKH separator HJDFRPPD 5HFDOOIURP
&KDSWHUWKDWDEVWUDFWILHOGVOLNHDEVWUDFWW\SHVDQGPHWKRGVPXVWEHLQLWLDOL]HGLQ
FRQFUHWHLQVWDQFHV,QWKLVFDVHstringZLOOEHGHILQHGWKURXJKDFRQFUHWHFRQVWUXFWRU
DQGWKHseparatorLVGHILQHGH[SOLFLWO\LQWKHFRQFUHWHFODVVHVCSVDQGTSV
7KHtoStringPHWKRGRQEncodedStringSULQWVWKHVWULQJDVD£QRUPDO¤VWULQJ%\KLGLQJ
WKHstringYDOXHDQGWKHFRQFUHWHFODVVHVZHKDYHFRPSOHWHIUHHGRPLQKRZWKHVWULQJ
LVDFWXDOO\VWRUHG)RUH[DPSOHIRUH[WUHPHO\ODUJHVWULQJVZHPLJKWZDQWWRVSOLWWKHP
RQWKHGHOLPLWHUDQGVWRUHWKHWRNHQVLQDGDWDVWUXFWXUH7KLVFRXOGVDYHVSDFHLIWKH
VWULQJVDUHODUJHHQRXJKDQGZHFDQVKDUHWRNHQVEHWZHHQVWULQJV$OVRZHPLJKWILQG
WKLV VWRUDJH XVHIXO IRU YDULRXV VHDUFKLQJ VRUWLQJ DQG RWKHU PDQLSXODWLRQ WDVNV $OO
WKHVHLPSOHPHQWDWLRQLVVXHVDUHWUDQVSDUHQWWRWKHFOLHQW
7KHSDFNDJHDOVRH[SRVHVDQREMHFWZLWKDQEnumerationIRUWKHNQRZQVHSDUDWRUVDQ
apply IDFWRU\ PHWKRG WR FRQVWUXFW QHZ HQFRGHG VWULQJV DQG DQ unapply H[WUDFWRU
PHWKRGWRGHFRPSRVHWKHHQFRGHGVWULQJLQWRLWVHQFORVHGVWULQJDQGWKHGHOLPLWHU,Q
WKLVFDVHWKH unapplyPHWKRGORRNVWULYLDOEXWLIZHVWRUHGWKHVWULQJVLQDGLIIHUHQW
ZD\WKLVPHWKRGFRXOGWUDQVSDUHQWO\UHFRQVWLWXWHWKHRULJLQDOVWULQJ
6RFOLHQWVRIWKLVFRPSRQHQWRQO\NQRZDERXWWKHEncodedStringDEVWUDFWLRQDQGWKH
HQXPHUDWLRQUHSUHVHQWLQJWKHVXSSRUWHGW\SHVRIHQFRGHGVWULQJV$OOWKHDFWXDOLP
SOHPHQWDWLRQW\SHVDQGGHWDLOVDUHSULYDWHWRWKHencodedstringSDFNDJH :HSXWWKHP
LQWKHVDPHILOHIRUFRQYHQLHQFHEXWQRUPDOO\\RXZRXOGNHSWWKHPVHSDUDWH +HQFH
WKHERXQGDU\LVFOHDUEHWZHHQWKHH[SRVHGDEVWUDFWLRQVDQGWKHLQWHUQDOLPSOHPHQWD
WLRQGHWDLOV
7KHIROORZLQJVFULSWGHPRQVWUDWHVWKHFRPSRQHQWLQXVH
// code-examples/AppDesign/abstractions/encoded-string-script.scala

import encodedstring._
import encodedstring.EncodedString._

def p(s: EncodedString) = {


println("EncodedString: " + s)
s.toTokens foreach (x => println("token: " + x))
}

val csv = EncodedString("Scala,is,great!", Separator.COMMA)


val tsv = EncodedString("Scala\tis\tgreat!", Separator.TAB)

p(csv)
p(tsv)

println( "\nExtraction:" )
List(csv, "ProgrammingScala", tsv, 3.14159) foreach {
case EncodedString(str, delim) =>
println( "EncodedString: \"" + str + "\", delimiter: \"" + delim + "\"" )
case s: String => println( "String: " + s )
case x => println( "Unknown Value: " + x )
}

Scalable Abstractions | 315

Download at WoweBook.Com
,WSURGXFHVWKHIROORZLQJRXWSXW
EncodedString: Scala,is,great!
token: Scala
token: is
token: great!
EncodedString: Scala is great!
token: Scala
token: is
token: great!

Extraction:
EncodedString: "Scala,is,great!", delimiter: ","
String: ProgrammingScala
EncodedString: "Scala is great!", delimiter: " "
Unknown Value: 3.14159

+RZHYHULIZHWU\WRXVHWKHCSVFODVVGLUHFWO\IRUH[DPSOHZHJHWWKHIROORZLQJHUURU
scala> import encodedstring._
import encodedstring._

scala> val csv = impl.CSV("comma,separated,values")


<console>:6: error: object CSV cannot be accessed in package encodedstring.impl
val csv = impl.CSV("comma,separated,values")
^

scala>

,QWKLVVLPSOHH[DPSOHLWZDVQ¦WHVVHQWLDOWRPDNHWKHFRQFUHWHW\SHVSULYDWHWRWKH
FRPSRQHQW+RZHYHUZHKDYHDYHU\PLQLPDOLQWHUIDFHWRFOLHQWVRIWKHFRPSRQHQW
DQGZHDUHIUHHWRPRGLI\WKHLPSOHPHQWDWLRQDVZHVHHILWZLWKOLWWOHULVNRIIRUFLQJ
FOLHQWFRGHPRGLILFDWLRQV$FRPPRQFDXVHRIPDLQWHQDQFHSDUDO\VLVLQPDWXUHDSSOL
FDWLRQVLVWKHSUHVHQFHRIWRRPDQ\GHSHQGHQFLHVEHWZHHQFRQFUHWHW\SHVZKLFKEH
FRPHGLIILFXOWWRPRGLI\VLQFHWKH\IRUFHFKDQJHVWRFOLHQWFRGH6RIRUODUJHUPRUH
VRSKLVWLFDWHGFRPSRQHQWVWKLVFOHDUVHSDUDWLRQRIDEVWUDFWLRQIURPLPSOHPHQWDWLRQ
FDQNHHSWKHFRGHPDLQWDLQDEOHDQGUHXVDEOHIRUDORQJWLPH

Mixin Composition
:HVDZLQ&KDSWHUKRZWUDLWVSURPRWHPL[LQFRPSRVLWLRQ$FODVVFDQIRFXVRQLWV
SULPDU\ GRPDLQ DQG RWKHU UHVSRQVLELOLWLHV FDQ EH LPSOHPHQWHG VHSDUDWHO\ LQ WUDLWV
:KHQLQVWDQFHVDUHFRQVWUXFWHGFODVVHVDQGWUDLWVFDQEHFRPELQHGWRFRPSRVHWKH
IXOOUDQJHRIUHTXLUHGEHKDYLRUV
)RUH[DPSOHLQ£2YHUULGLQJ$EVWUDFW7\SHV¤RQSDJHZHGLVFXVVHGRXUVHFRQG
YHUVLRQRIWKH2EVHUYHU3DWWHUQ
// code-examples/AdvOOP/observer/observer2.scala

package observer

trait AbstractSubject {

316 | Chapter 13:—Application Design

Download at WoweBook.Com
type Observer

private var observers = List[Observer]()


def addObserver(observer:Observer) = observers ::= observer
def notifyObservers = observers foreach (notify(_))

def notify(observer: Observer): Unit


}

trait SubjectForReceiveUpdateObservers extends AbstractSubject {


type Observer = { def receiveUpdate(subject: Any) }

def notify(observer: Observer): Unit = observer.receiveUpdate(this)


}

trait SubjectForFunctionalObservers extends AbstractSubject {


type Observer = (AbstractSubject) => Unit

def notify(observer: Observer): Unit = observer(this)


}

:HXVHGWKLVYHUVLRQWRREVHUYHEXWWRQ£FOLFNV¤LQD8,/HW¦VUHYLVLWWKLVLPSOHPHQWDWLRQ
DQGUHVROYHDIHZOLPLWDWLRQVXVLQJRXUQH[WWRROIRUVFDODEOHDEVWUDFWLRQVVHOIW\SH
DQQRWDWLRQVFRPELQHGZLWKDEVWUDFWW\SHPHPEHUV

Self-Type Annotations and Abstract Type Members


7KHUH DUH D IHZ WKLQJV WKDW DUH XQVDWLVI\LQJ DERXW WKH LPSOHPHQWDWLRQ RI Abstract
Subject LQ RXU VHFRQG YHUVLRQ RI WKH 2EVHUYHU 3DWWHUQ 7KH ILUVW RFFXUV LQ Subject
ForReceiveUpdateObserversZKHUHWKHObserverW\SHLVGHILQHGWREHWKHVWUXFWXUDOW\SH
{ def receiveUpdate(subject: Any) } ,W ZRXOG EH QLFH WR QDUURZ WKH W\SH RI
subjectWRVRPHWKLQJPRUHVSHFLILFWKDQAny
7KH VHFRQG LVVXH ZKLFK LV UHDOO\ WKH VDPH SUREOHP LQ D GLIIHUHQW IRUP RFFXUV LQ
SubjectForFunctionalObservers ZKHUH WKH Observer W\SH LV GHILQHG WR EH WKH W\SH
(AbstractSubject) => Unit:HZRXOGOLNHWKHDUJXPHQWWRWKHIXQFWLRQWREHVRPH
WKLQJPRUHVSHFLILFWKDQ AbstractSubject3HUKDSVWKLVGUDZEDFNZDVQ¦WVRHYLGHQW
EHIRUHEHFDXVHRXUVLPSOHH[DPSOHVQHYHUQHHGHGWRDFFHVVButtonVWDWHLQIRUPDWLRQ
RUPHWKRGV
,Q IDFW ZH H[SHFW WKH DFWXDO W\SHV RI WKH VXEMHFW DQG REVHUYHU WR EH VSHFLDOL]HG
FRYDULDQWO\)RUH[DPSOHZKHQZH¦UHREVHUYLQJ ButtonsZHH[SHFWRXUREVHUYHUVWR
EHVSHFLDOL]HGIRU ButtonsVRWKH\FDQDFFHVV ButtonVWDWHDQGPHWKRGV7KLVFRYD
ULDQWVSHFLDOL]DWLRQLVVRPHWLPHVFDOOHGIDPLO\SRO\PRUSKLVP VHH>2GHUVN\@ /HW¦V
IL[RXUGHVLJQWRVXSSRUWWKLVFRYDULDQFH
7RVLPSOLI\WKHH[DPSOHOHW¦VIRFXVRQMXVWWKH receiveUpdateIRUPRIWKH Observer
ZKLFKZHLPSOHPHQWHGZLWK SubjectForReceiveUpdateObserversEHIRUH+HUHLVDUH
ZRUNLQJRIRXUSDWWHUQORRVHO\IROORZLQJDQH[DPSOHLQ>2GHUVN\@ 1RWHWKDWWKH
6FDODV\QWD[KDVFKDQJHGVRPHZKDWVLQFHWKDWSDSHUZDVZULWWHQ

Scalable Abstractions | 317

Download at WoweBook.Com
// code-examples/AppDesign/abstractions/observer3-wont-compile.scala
// WON'T COMPILE

package observer

abstract class SubjectObserver {


type S <: Subject
type O <: Observer

trait Subject {
private var observers = List[O]()
def addObserver(observer: O) = observers ::= observer
def notifyObservers = observers foreach (_.receiveUpdate(this)) // ERROR
}

trait Observer {
def receiveUpdate(subject: S)
}
}

:H¦OOH[SODLQWKHHUURULQDPLQXWH1RWHKRZWKHW\SHV SDQG ODUHGHFODUHG$VZH


VDZLQ£8QGHUVWDQGLQJ3DUDPHWHUL]HG7\SHV¤RQSDJHWKHH[SUHVVLRQ type S <:
SubjectGHILQHVDQDEVWUDFWW\SH SZKHUHWKHRQO\DOORZHGFRQFUHWHW\SHVZLOOEHVXE
W\SHVRISubject7KHGHFODUDWLRQRIOLVVLPLODU7REHFOHDUSDQGODUH£SODFHKROGHUV¤
DWWKLVSRLQWZKLOHSubjectDQGObserverDUHDEVWUDFWWUDLWVGHILQHGLQSubjectObserver
%\WKHZD\GHFODULQJ SubjectObserverDVDQDEVWUDFWFODVVYHUVXVDWUDLWLVVRPHZKDW
DUELWUDU\:H¦OOGHULYHFRQFUHWHREMHFWVIURPLWVKRUWO\:HQHHGSubjectObserverSUL
PDULO\VRZHKDYHDW\SHWR£KROG¤RXUDEVWUDFWW\SHPHPEHUVSDQGO
+RZHYHULI\RXDWWHPSWWRFRPSLOHWKLVFRGHDVFXUUHQWO\ZULWWHQ\RXJHWWKHIROORZLQJ
HUURU
... 10: error: type mismatch;
found : SubjectObserver.this.Subject
required: SubjectObserver.this.S
def notifyObservers = observers foreach (_.receiveUpdate(this))
^
one error found

,QWKHQHVWHG ObserverWUDLW receiveUpdateLVH[SHFWLQJDQLQVWDQFHRIW\SH SEXWZH


DUHSDVVLQJLWthisZKLFKLVRIW\SHSubject,QRWKHUZRUGVZHDUHSDVVLQJDQLQVWDQFH
RIDSDUHQWW\SHRIWKHW\SHH[SHFWHG2QHVROXWLRQZRXOGEHWRFKDQJHWKHVLJQDWXUH
WRMXVWH[SHFWWKHSDUHQWW\SHSubject7KDW¦VXQGHVLUDEOH:HMXVWPHQWLRQHGWKDWRXU
FRQFUHWHREVHUYHUVQHHGWKHPRUHVSHFLILFW\SHWKHDFWXDOFRQFUHWHW\SHZH¦OOHYHQWXDOO\
GHILQH IRU S VR WKH\ FDQ FDOO PHWKRGV RQ LW )RU H[DPSOH ZKHQ REVHUYLQJ 8,
CheckBoxesWKHREVHUYHUVZLOOZDQWWRUHDGZKHWKHURUQRWDER[LVFKHFNHG:HGRQ¦W
ZDQWWRIRUFHWKHREVHUYHUVWRXVHXQVDIHFDVWV
:H ORRNHG DW FRPSRVLWLRQ XVLQJ VHOIW\SH DQQRWDWLRQV LQ £6HOI7\SH $QQRWD
WLRQV¤RQSDJH/HW¦VXVHWKLVIHDWXUHQRZWRVROYHRXUFXUUHQWFRPSLODWLRQSUREOHP
+HUHLVWKHVDPHFRGHDJDLQZLWKDVHOIW\SHDQQRWDWLRQ

318 | Chapter 13:—Application Design

Download at WoweBook.Com
// code-examples/AppDesign/abstractions/observer3.scala

package observer

abstract class SubjectObserver {


type S <: Subject
type O <: Observer

trait Subject {
self: S => // #1
private var observers = List[O]()
def addObserver(observer: O) = observers ::= observer
def notifyObservers = observers foreach (_.receiveUpdate(self)) // #2
}

trait Observer {
def receiveUpdate(subject: S)
}
}

&RPPHQWVKRZVWKHVHOIW\SHDQQRWDWLRQself: S =>:HFDQQRZXVHselfDVDQ
DOLDVIRU thisEXWZKHQHYHULWDSSHDUVWKHW\SHZLOOEHDVVXPHGWREHSQRW Subject
,WLVDVLIZH¦UHWHOOLQJSubjectWRLPSHUVRQDWHDQRWKHUW\SHEXWLQDW\SHVDIHZD\DV
ZH¦OOVHH
$FWXDOO\ZHFRXOGKDYHXVHGthisLQVWHDGRIselfLQWKHDQQRWDWLRQEXWselfLVVRPH
ZKDWFRQYHQWLRQDO$GLIIHUHQWQDPHDOVRUHPLQGVXVWKDWZH¦UHZRUNLQJZLWKDGLIIHUHQW
W\SH
$UH VHOIW\SH DQQRWDWLRQV D VDIH WKLQJ WR XVH" :KHQ DQ DFWXDO FRQFUHWH
SubjectObserverLVGHILQHGSDQGOZLOOEHVSHFLILHGDQGW\SHFKHFNLQJZLOOEHSHUIRUPHG
WRHQVXUHWKDWWKHFRQFUHWHSDQGODUHFRPSDWLEOHZLWKSubjectDQGObserver,QWKLV
FDVHEHFDXVHZHDOVRGHILQHG SWREHDVXEW\SHRI SubjectDQG OWREHDVXEW\SHRI
Observer DQ\ FRQFUHWH W\SHV GHULYHG IURP Subject DQG Observer UHVSHFWLYHO\ ZLOO
ZRUN
&RPPHQWVKRZVWKDWZHSDVVselfLQVWHDGRIthisWRreceiveUpdate
1RZWKDWZHKDYHDJHQHULFLPSOHPHQWDWLRQRIWKHSDWWHUQOHW¦VVSHFLDOL]HLWIRURE
VHUYLQJEXWWRQFOLFNV
// code-examples/AppDesign/abstractions/button-observer3.scala

package ui
import observer._

object ButtonSubjectObserver extends SubjectObserver {


type S = ObservableButton
type O = ButtonObserver

class ObservableButton(name: String) extends Button(name) with Subject {


override def click() = {
super.click()
notifyObservers

Scalable Abstractions | 319

Download at WoweBook.Com
}
}

trait ButtonObserver extends Observer {


def receiveUpdate(button: ObservableButton)
}
}

:HGHFODUHDQREMHFWButtonSubjectObserverZKHUHZHGHILQHSDQGOWREHObservable
ButtonDQG ButtonObserverUHVSHFWLYHO\ERWKRIZKLFKDUHGHILQHGLQWKHREMHFW:H
XVHDQobjectQRZVRWKDWZHFDQUHIHUWRWKHQHVWHGW\SHVHDVLO\DVZH¦OOVHHVKRUWO\
ObservableButtonLVDFRQFUHWHFODVVWKDWRYHUULGHVclickWRQRWLI\REVHUYHUVVLPLODUWR
RXUSUHYLRXVLPSOHPHQWDWLRQVLQ&KDSWHU+RZHYHU ButtonObserverLVVWLOODQDE
VWUDFW WUDLW EHFDXVH receiveUpdate LV QRW GHILQHG 1RWLFH WKDW WKH DUJXPHQW WR
receiveUpdateLVQRZDQObservableButtonWKHYDOXHDVVLJQHGWRS
7KHILQDOSLHFHRIWKHSX]]OHLVWRGHILQHDFRQFUHWHREVHUYHU$VEHIRUHZH¦OOFRXQW
EXWWRQFOLFNV+RZHYHUWRHPSKDVL]HWKHYDOXHRIKDYLQJWKHVSHFLILFW\SHRILQVWDQFH
SDVVHGWRWKHREVHUYHUDButtonLQWKLVFDVHZH¦OOHQKDQFHWKHREVHUYHUWRWUDFNFOLFNV
IRUPXOWLSOHEXWWRQVXVLQJDKDVKPDSZLWKWKHEXWWRQODEHOVDVWKHNH\V1RW\SHFDVWV
DUHUHTXLUHG
// code-examples/AppDesign/abstractions/button-click-observer3.scala

package ui
import observer._

class ButtonClickObserver extends ButtonSubjectObserver.ButtonObserver {


val clicks = new scala.collection.mutable.HashMap[String,Int]()

def receiveUpdate(button: ButtonSubjectObserver.ObservableButton) = {


val count = clicks.getOrElse(button.label, 0) + 1
clicks.update(button.label, count)
}
}

(YHU\WLPH ButtonClickObserver.receiveUpdateLVFDOOHGLWIHWFKHVWKHFXUUHQWFRXQW
IRUWKHEXWWRQLIDQ\DQGXSGDWHVWKHPDSZLWKDQLQFUHPHQWHGFRXQW1RWHWKDWLWLV
QRZ LPSRVVLEOH WR FDOO receiveUpdate ZLWK D QRUPDO Button :H KDYH WR XVH DQ
ObservableButton7KLVUHVWULFWLRQHOLPLQDWHVEXJVZKHUHZHGRQ¦WJHWWKHQRWLILFDWLRQV
ZHH[SHFWHG:HDOVRKDYHDFFHVVWRDQ\£HQKDQFHG¤IHDWXUHVWKDW ObservableButton
PD\KDYH
)LQDOO\KHUHLVDVSHFLILFDWLRQWKDWH[HUFLVHVWKHFRGH
// code-examples/AppDesign/abstractions/button-observer3-spec.scala

package ui
import org.specs._
import observer._

object ButtonObserver3Spec extends Specification {

320 | Chapter 13:—Application Design

Download at WoweBook.Com
"An Observer counting button clicks" should {
"see all clicks" in {
val button1 = new ButtonSubjectObserver.ObservableButton("button1")
val button2 = new ButtonSubjectObserver.ObservableButton("button2")
val button3 = new ButtonSubjectObserver.ObservableButton("button3")
val buttonObserver = new ButtonClickObserver
button1.addObserver(buttonObserver)
button2.addObserver(buttonObserver)
button3.addObserver(buttonObserver)
clickButton(button1, 1)
clickButton(button2, 2)
clickButton(button3, 3)
buttonObserver.clicks("button1") mustEqual 1
buttonObserver.clicks("button2") mustEqual 2
buttonObserver.clicks("button3") mustEqual 3
}
}

def clickButton(button: Button, nClicks: Int) =


for (i <- 1 to nClicks)
button.click()
}

:HFUHDWHWKUHHEXWWRQVDQGRQHREVHUYHUIRUDOORIWKHP:HWKHQFOLFNWKHEXWWRQV
GLIIHUHQWQXPEHUVRIWLPHV)LQDOO\ZHFRQILUPWKDWWKHFOLFNVZHUHSURSHUO\FRXQWHG
IRUHDFKEXWWRQ
:HVHHDJDLQKRZDEVWUDFWW\SHVFRPELQHGZLWKVHOIW\SHDQQRWDWLRQVSURYLGHDUHXV
DEOHDEVWUDFWLRQWKDWLVHDV\WRH[WHQGLQDW\SHVDIHZD\IRUSDUWLFXODUQHHGV(YHQ
WKRXJKZHGHILQHGDJHQHUDOSURWRFROIRUREVHUYLQJDQ£HYHQW¤DIWHULWKDSSHQHGZH
ZHUHDEOHWRGHILQHVXEW\SHVVSHFLILFWRButtonsZLWKRXWUHVRUWLQJWRXQVDIHFDVWVIURP
SubjectDEVWUDFWLRQV
7KH 6FDOD FRPSLOHU LWVHOI LV LPSOHPHQWHG XVLQJ WKHVH PHFKDQLVPV VHH >2GHU
VN\@ WRPDNHLWPRGXODULQXVHIXOZD\V)RUH[DPSOHLWLVUHODWLYHO\VWUDLJKWIRU
ZDUGWRLPSOHPHQWFRPSLOHUSOXJLQV
:H¦OO UHYLVLW WKHVH LGLRPV LQ £'HSHQGHQF\ ,QMHFWLRQ LQ 6FDOD 7KH &DNH 3DW
WHUQ¤RQSDJH

Effective Design of Traits


2QHRIWKHUHDVRQVWKDWPDQ\ODQJXDJHV OLNH-DYD GRQRWLPSOHPHQWPXOWLSOHLQKHUL
WDQFHLVEHFDXVHRIWKHSUREOHPVREVHUYHGZLWKPXOWLSOHLQKHULWDQFHLQ&2QHRI
WKRVHSUREOHPVLVWKHVRFDOOHGGLDPRQGRIGHDWKZKLFKLVLOOXVWUDWHGLQ)LJXUH

Effective Design of Traits | 321

Download at WoweBook.Com
)LJXUH'LDPRQGRIGHDWKLQODQJXDJHVZLWKPXOWLSOHLQKHULWDQFH

,Q&HDFKFRQVWUXFWRUIRU CZLOOLQYRNHDFRQVWUXFWRUIRU B1DQGDFRQVWUXFWRUIRU


B2 H[SOLFLWO\RULPSOLFLWO\ (DFKFRQVWUXFWRUIRUB1DQGB2ZLOOLQYRNHDFRQVWUXFWRUIRU
A+HQFHLQDQDwYHLPSOHPHQWDWLRQRIPXOWLSOHLQKHULWDQFHWKHILHOGVRIAa1DQGa2
FRXOGEHLQLWLDOL]HGWZLFHDQGSRVVLEO\LQLWLDOL]HGLQDQLQFRQVLVWHQWZD\RUWKHUHPLJKW
EHWZRGLIIHUHQWA£SLHFHV¤LQWKHCLQVWDQFHRQHIRUB1DQGRQHIRUB2&KDVPHFK
DQLVPVWRFODULI\ZKDWVKRXOGKDSSHQEXWLW¦VXSWRWKHGHYHORSHUWRXQGHUVWDQGWKH
GHWDLOVDQGWRGRWKHFRUUHFWWKLQJ
6FDOD¦VVLQJOHLQKHULWDQFHDQGVXSSRUWIRUWUDLWVDYRLGWKHVHSUREOHPVZKLOHSURYLGLQJ
WKHPRVWLPSRUWDQWEHQHILWRIPXOWLSOHLQKHULWDQFHPL[LQFRPSRVLWLRQ7KHRUGHURI
FRQVWUXFWLRQ LV XQDPELJXRXV VHH £/LQHDUL]DWLRQ RI DQ 2EMHFW¦V +LHUDU
FK\¤RQSDJH 7UDLWVFDQ¦WKDYHFRQVWUXFWRUDUJXPHQWOLVWVEXW6FDODHQVXUHVWKDW
WKHLU ILHOGV DUH SURSHUO\ LQLWLDOL]HG ZKHQ LQVWDQFHV DUH FUHDWHG DV ZH VDZ LQ £&RQ
VWUXFWLQJ 7UDLWV¤ RQ SDJH  DQG £2YHUULGLQJ $EVWUDFW DQG &RQFUHWH )LHOGV LQ
7UDLWV¤RQSDJH:HVDZDQRWKHUH[DPSOHRILQLWLDOL]LQJ valsLQDWUDLWLQ£)LQH
*UDLQHG9LVLELOLW\5XOHV¤RQSDJH7KHUHZHGHILQHGFRQFUHWHFODVVHVWKDWRYHUURGH
WKHGHILQLWLRQVRIWKHWZRDEVWUDFWILHOGVLQWKHEncodedStringWUDLW
6R6FDODKDQGOHVPDQ\SRWHQWLDOLVVXHVWKDWDULVHZKHQPL[LQJWKHFRQWULEXWLRQVRI
GLIIHUHQWWUDLWVLQWRWKHVHWRISRVVLEOHVWDWHVRIDQLQVWDQFH6WLOOLW¦VLPSRUWDQWWRFRQ
VLGHUKRZWKHFRQWULEXWLRQVRIGLIIHUHQWWUDLWVLQWHUDFWZLWKHDFKRWKHU
:KHQFRQVLGHULQJWKHVWDWHRIDQLQVWDQFHLWLVXVHIXOWRFRQVLGHUWKHLQVWDQFHDVSRV
VHVVLQJDVWDWHPDFKLQHZKHUHHYHQWV HJPHWKRGFDOOVDQGILHOGZULWHV FDXVHWUDQVL
WLRQVIURPRQHVWDWHWRDQRWKHU7KHVHWRIDOOSRVVLEOHVWDWHVIRUPDVSDFH<RXFDQ
WKLQNRIHDFKILHOGDVFRQWULEXWLQJRQHGLPHQVLRQWRWKLVVSDFH
)RUH[DPSOHUHFDOORXU VetoableClicksWUDLWLQ£6WDFNDEOH7UDLWV¤RQSDJHZKHUH
EXWWRQFOLFNVZHUHFRXQWHGDQGDGGLWLRQDOFOLFNVZHUHYHWRHGDIWHUDFHUWDLQQXPEHURI
FOLFNVRFFXUUHG2XUVLPSOH ButtonFODVVFRQWULEXWHGRQO\D labelGLPHQVLRQZKLOH

322 | Chapter 13:—Application Design

Download at WoweBook.Com
VetoableClicksFRQWULEXWHGD countGLPHQVLRQDQGD maxAllowedFRQVWDQW+HUHLVD
UHFDSRIWKHVHW\SHVFROOHFWHGWRJHWKHULQWRDVLQJOHVFULSWWKDWDOVRH[HUFLVHVWKHFRGH
// code-examples/AppDesign/abstractions/vetoable-clicks1-script.scala

trait Clickable {
def click()
}

class Widget
class Button(val label: String) extends Widget with Clickable {
def click() = println("click!")
}

trait VetoableClicks extends Clickable {


val maxAllowed = 1
private var count = 0
abstract override def click() = {
if (count < maxAllowed) {
count += 1
super.click()
}
}
}

val button1 = new Button("click me!")


println("new Button(...)")
for (i <- 1 to 3 ) button1.click()

val button2 = new Button("click me!") with VetoableClicks


println("new Button(...) with VetoableClicks")
for (i <- 1 to 3 ) button2.click()

7KLVVFULSWSULQWVWKHIROORZLQJRXWSXW
new Button(...)
click!
click!
click!
new Button(...) with VetoableClicks
click!

1RWHWKDW maxAllowedLVDFRQVWDQWEXWLWFDQEHRYHUULGGHQZKHQLQVWDQWLDWLQJHDFK
LQVWDQFH6RWZRLQVWDQFHVFRXOGGLIIHURQO\E\WKHYDOXHRI maxAllowed7KHUHIRUH
maxAllowed DOVR FRQWULEXWHV D GLPHQVLRQ WR WKH VWDWH EXW ZLWK RQO\ RQH YDOXH SHU
LQVWDQFH
6RIRUDEXWWRQODEHOHG£6XEPLW¤ZLWKmaxAllowedVHWWRDQGZKLFKKDVEHHQFOLFNHG
WZLFH VRcountHTXDOV LWVVWDWHFDQEHUHSUHVHQWHGE\WKHWXSOH("Submit", 2, 3)
,QJHQHUDODVLQJOHWUDLWFDQHLWKHUEHVWDWHOHVVLHLWFRQWULEXWHVQRQHZGLPHQVLRQV
RIVWDWHWRWKHLQVWDQFHRULWFDQFRQWULEXWHRUWKRJRQDOVWDWHGLPHQVLRQVWRWKHLQVWDQFH
LHGLPHQVLRQVWKDWDUHLQGHSHQGHQWRIWKHVWDWHFRQWULEXWLRQVIURPRWKHUWUDLWVDQG
WKHSDUHQWFODVV,QWKHVFULSWClickableLVWULYLDOO\VWDWHOHVV LJQRULQJWKHEXWWRQ¦VODEHO 

Effective Design of Traits | 323

Download at WoweBook.Com
ZKLOH VetoableClicksFRQWULEXWHV maxAllowedDQG count7UDLWVZLWKRUWKRJRQDOVWDWH
RIWHQKDYHRUWKRJRQDOPHWKRGVWRR)RUH[DPSOHWKH2EVHUYHU3DWWHUQWUDLWVZHXVHG
LQ&KDSWHUFRQWDLQHGPHWKRGVIRUPDQDJLQJWKHLUOLVWVRIREVHUYHUV
,QGHSHQGHQWRIZKHWKHUDWUDLWFRQWULEXWHVVWDWHGLPHQVLRQVDWUDLWFDQDOVRPRGLI\WKH
SRVVLEOHYDOXHVIRUDGLPHQVLRQFRQWULEXWHGE\DGLIIHUHQWWUDLWRUWKHSDUHQWFODVV7R
VHHDQH[DPSOHOHW¦VUHIDFWRUWKHVFULSWWRPRYHWKHFOLFNcountWRWKHClickableWUDLW
// code-examples/AppDesign/abstractions/vetoable-clicks2-script.scala

trait Clickable {
private var clicks = 0
def count = clicks

def click() = { clicks += 1 }


}

class Widget
class Button(val label: String) extends Widget with Clickable {
override def click() = {
super.click()
println("click!")
}
}

trait VetoableClicks extends Clickable {


val maxAllowed = 1
abstract override def click() = {
if (count < maxAllowed)
super.click()
}
}

val button1 = new Button("click me!")


println("new Button(...)")
for (i <- 1 to 3 ) button1.click()

val button2 = new Button("click me!") with VetoableClicks


println("new Button(...) with VetoableClicks")
for (i <- 1 to 3 ) button2.click()

7KLVVFULSWSULQWVWKHVDPHRXWSXWDVEHIRUH1RZClickableFRQWULEXWHVRQHVWDWHGL
PHQVLRQ IRU count ZKLFK LV QRZ D PHWKRG WKDW UHWXUQV WKH YDOXH RI WKH SULYDWH
clicksILHOG VetoableClicksPRGLILHVWKLVGLPHQVLRQE\UHGXFLQJWKHQXPEHURISRV
VLEOHYDOXHVIRUcountIURP0WRLQILQLW\GRZQWRMXVW0DQG17KHUHIRUHRQHWUDLWDIIHFWV
WKH EHKDYLRU RI DQRWKHU :H PLJKW VD\ WKDW VetoableClicks LV LQYDVLYH EHFDXVH LW
FKDQJHVWKHEHKDYLRURIRWKHUPL[LQV
:K\LVDOOWKLVLPSRUWDQW":KLOHWKHSUREOHPVRIPXOWLSOHLQKHULWDQFHDUHHOLPLQDWHG
LQ6FDOD¦VPRGHORIVLQJOHLQKHULWDQFHSOXVWUDLWVFDUHLVUHTXLUHGZKHQPL[LQJVWDWHDQG
EHKDYLRUFRQWULEXWLRQVWRFUHDWHZHOOEHKDYHGDSSOLFDWLRQV)RUH[DPSOHLI\RXKDYH
DWHVWVXLWHWKDWButtonSDVVHVZLOODButton with VetoableClicksLQVWDQFHSDVVWKHVDPH

324 | Chapter 13:—Application Design

Download at WoweBook.Com
WHVWVXLWH"7KHVXLWHZRQ¦WSDVVLILWDVVXPHVWKDW\RXFDQFOLFNDEXWWRQDVPDQ\WLPHV
DV\RXZDQW7KHUHDUHGLIIHUHQW£VSHFLILFDWLRQV¤IRUWKHVHWZRNLQGVRIEXWWRQV7KLV
GLIIHUHQFHLVH[SUHVVHGE\WKH/LVNRY6XEVWLWXWLRQ3ULQFLSOH VHH>0DUWLQ@ $QLQ
VWDQFHRIDButton with VetoableClicksZRQ¦WEHVXEVWLWXWDEOHLQHYHU\VLWXDWLRQZKHUH
D UHJXODU Button LQVWDQFH LV XVHG 7KLV LV D FRQVHTXHQFH RI WKH LQYDVLYH QDWXUH RI
VetoableClicks
:KHQDWUDLWDGGVRQO\RUWKRJRQDOVWDWHDQGEHKDYLRUZLWKRXWDIIHFWLQJWKHUHVWRIWKH
VWDWHDQGEHKDYLRURIWKHLQVWDQFHLWPDNHVUHXVHDQGFRPSRVLWLRQPXFKHDVLHUDVZHOO
DVUHGXFLQJWKHSRWHQWLDOIRUEXJV7KH2EVHUYHU3DWWHUQLPSOHPHQWDWLRQVZHKDYHVHHQ
DUHTXLWHUHXVDEOH7KHRQO\UHTXLUHPHQWIRUUHXVHLVWRSURYLGHVRPH£JOXH¤WRDGDSW
WKHJHQHULFVXEMHFWDQGREVHUYHUWUDLWVWRSDUWLFXODUFLUFXPVWDQFHV
7KLVGRHVQRWPHDQWKDWLQYDVLYHPL[LQVDUHEDGMXVWWKDWWKH\VKRXOGEHXVHGZLVHO\
7KH£YHWRDEOHHYHQWV¤SDWWHUQFDQEHYHU\XVHIXO

Design Patterns
'HVLJQSDWWHUQVKDYHWDNHQDEHDWLQJODWHO\&ULWLFVGLVPLVVWKHPDVZRUNDURXQGVIRU
PLVVLQJ ODQJXDJH IHDWXUHV ,QGHHG VRPH RI WKH *DQJ RI )RXU SDWWHUQV VHH
>*2)@ DUHQRWUHDOO\QHHGHGLQ6FDODDVQDWLYHIHDWXUHVSURYLGHEHWWHUVXEVWLWXWHV
2WKHUSDWWHUQVDUHSDUWRIWKHODQJXDJHLWVHOIVRQRVSHFLDOFRGLQJLVQHHGHG2IFRXUVH
SDWWHUQVDUHIUHTXHQWO\PLVXVHGEXWWKDW¦VQRWWKHIDXOWRIWKHSDWWHUQVWKHPVHOYHV
:HWKLQNWKHFULWLFLVPVRIWHQRYHUORRNDQLPSRUWDQWSRLQWWKHGLVWLQFWLRQEHWZHHQDQ
LGHD DQG KRZ LW LV LPSOHPHQWHG DQG XVHG LQ D SDUWLFXODU VLWXDWLRQ 'HVLJQ SDWWHUQV
GRFXPHQWUHFXUULQJZLGHO\XVHIXOLGHDV7KHVHLGHDVDUHSDUWRIWKHYRFDEXODU\WKDW
VRIWZDUHGHYHORSHUVXVHWRGHVFULEHWKHLUGHVLJQV
6RPHFRPPRQSDWWHUQVDUHQDWLYHODQJXDJHIHDWXUHVLQ6FDODOLNHVLQJOHWRQREMHFWVWKDW
HOLPLQDWHWKHQHHGIRUD6LQJOHWRQ3DWWHUQ >*2)@ LPSOHPHQWDWLRQOLNH\RXRIWHQ
XVHLQ-DYDFRGH
7KH,WHUDWRU3DWWHUQ >*2)@ LVVRSHUYDVLYHLQSURJUDPPLQJWKDWPRVWODQJXDJHV
LQFOXGHLWHUDWLRQPHFKDQLVPVIRUDQ\W\SHWKDWFDQEHWUHDWHGOLNHDFROOHFWLRQ)RU
H[DPSOHLQ6FDOD\RXFDQLWHUDWHWKURXJKWKHFKDUDFWHUVLQDStringZLWKforeach
"Programming Scala" foreach {c => println(c)}

$FWXDOO\ LQ WKLV FDVH DQ LPSOLFLW FRQYHUVLRQ LV LQYRNHG WR FRQYHUW WKH
java.lang.StringWRD RichStringZKLFKKDVWKH foreachPHWKRG7KDW¦VDQH[DPSOH
RI WKH SDWWHUQ FDOOHG 3LPS 0\ /LEUDU\ ZKLFK ZH VDZ LQ £,PSOLFLW &RQYHU
VLRQV¤RQSDJH
2WKHUFRPPRQSDWWHUQVKDYHEHWWHUDOWHUQDWLYHVLQ6FDOD:H¦OOGLVFXVVDEHWWHUDOWHU
QDWLYHWRWKH9LVLWRU3DWWHUQ >*2)@ LQDPRPHQW

Design Patterns | 325

Download at WoweBook.Com
)LQDOO\VWLOORWKHUSDWWHUQVFDQEHLPSOHPHQWHGLQ6FDODDQGUHPDLQYHU\XVHIXO)RU
H[DPSOHWKH2EVHUYHU3DWWHUQWKDWZHGLVFXVVHGHDUOLHULQWKLVFKDSWHUDQGLQ&KDS
WHULVDYHU\XVHIXOSDWWHUQIRUPDQ\GHVLJQSUREOHPV,WFDQEHLPSOHPHQWHGYHU\
HOHJDQWO\XVLQJPL[LQFRPSRVLWLRQ
:HZRQ¦WGLVFXVVDOOWKHZHOONQRZQSDWWHUQVVXFKDVWKRVHLQ>*2)@$QXPEHU
RIWKH*2)SDWWHUQVDUHGLVFXVVHGDW>6FDOD:LNL3DWWHUQV@DORQJZLWKRWKHUSDWWHUQV
WKDWDUHVRPHZKDWVSHFLILFWR6FDOD,QVWHDGZH¦OOGLVFXVVDIHZLOOXVWUDWLYHH[DPSOHV
:H¦OO VWDUW E\ GLVFXVVLQJ D UHSODFHPHQW IRU WKH 9LVLWRU 3DWWHUQ WKDW XVHV IXQFWLRQDO
LGLRPVDQGLPSOLFLWFRQYHUVLRQV7KHQZH¦OOGLVFXVVDSRZHUIXOZD\RILPSOHPHQWLQJ
GHSHQGHQF\LQMHFWLRQLQ6FDODXVLQJWKH&DNH3DWWHUQ

The Visitor Pattern: A Better Alternative


7KH9LVLWRU3DWWHUQVROYHVWKHSUREOHPRIDGGLQJDQHZRSHUDWLRQWRDFODVVKLHUDUFK\
ZLWKRXWHGLWLQJWKHVRXUFHFRGHIRUWKHFODVVHVLQWKHKLHUDUFK\)RUDQXPEHURISUDF
WLFDOUHDVRQVLWPD\QRWEHIHDVLEOHRUGHVLUDEOHWRHGLWWKHKLHUDUFK\WRVXSSRUWWKHQHZ
RSHUDWLRQ
/HW¦VORRNDWDQH[DPSOHRIWKHSDWWHUQXVLQJWKH ShapeFODVVKLHUDUFK\ZHKDYHXVHG
SUHYLRXVO\:H¦OOVWDUWZLWKWKHFDVHFODVVYHUVLRQIURP£&DVH&ODVVHV¤RQSDJH
// code-examples/AdvOOP/shapes/shapes-case.scala

package shapes {
case class Point(x: Double, y: Double)

abstract class Shape() {


def draw(): Unit
}

case class Circle(center: Point, radius: Double) extends Shape() {


def draw() = println("Circle.draw: " + this)
}

case class Rectangle(lowerLeft: Point, height: Double, width: Double)


extends Shape() {
def draw() = println("Rectangle.draw: " + this)
}

case class Triangle(point1: Point, point2: Point, point3: Point)


extends Shape() {
def draw() = println("Triangle.draw: " + this)
}
}

6XSSRVHZHGRQ¦WZDQWWKH drawPHWKRGLQWKHFODVVHV7KLVLVDUHDVRQDEOHGHVLJQ
FKRLFHVLQFHWKHGUDZLQJPHWKRGZLOOEHKLJKO\GHSHQGHQWRQWKHSDUWLFXODUFRQWH[W
RIXVHVXFKDVGHWDLOVRIWKHJUDSKLFVOLEUDULHVRQWKHSODWIRUPVWKHDSSOLFDWLRQZLOOUXQ
RQ)RUJUHDWHUUHXVDELOLW\ZHZRXOGOLNHGUDZLQJWREHDQRSHUDWLRQZHGHFRXSOHIURP
WKHVKDSHVWKHPVHOYHV

326 | Chapter 13:—Application Design

Download at WoweBook.Com
)LUVWZHUHIDFWRUWKHShapeKLHUDUFK\WRVXSSRUWWKH9LVLWRU3DWWHUQIROORZLQJWKHH[
DPSOHLQ>*2)@
// code-examples/AppDesign/patterns/shapes-visitor.scala

package shapes {
trait ShapeVisitor {
def visit(circle: Circle): Unit
def visit(rect: Rectangle): Unit
def visit(tri: Triangle): Unit
}

case class Point(x: Double, y: Double)

sealed abstract class Shape() {


def accept(visitor: ShapeVisitor): Unit
}

case class Circle(center: Point, radius: Double) extends Shape() {


def accept(visitor: ShapeVisitor) = visitor.visit(this)
}

case class Rectangle(lowerLeft: Point, height: Double, width: Double)


extends Shape() {
def accept(visitor: ShapeVisitor) = visitor.visit(this)
}

case class Triangle(point1: Point, point2: Point, point3: Point)


extends Shape() {
def accept(visitor: ShapeVisitor) = visitor.visit(this)
}
}

:HGHILQHD ShapeVisitorWUDLWZKLFKKDVRQHPHWKRGIRUHDFKFRQFUHWHFODVVLQWKH
KLHUDUFK\HJvisit(circle: Circle)(DFKVXFKPHWKRGWDNHVRQHSDUDPHWHURIWKH
FRUUHVSRQGLQJW\SHWRYLVLW&RQFUHWHGHULYHGFODVVHVZLOOLPSOHPHQWHDFKPHWKRGWR
GRWKHDSSURSULDWHRSHUDWLRQIRUWKHSDUWLFXODUW\SHSDVVHGLQ
7KH9LVLWRU3DWWHUQUHTXLUHVDRQHWLPHPRGLILFDWLRQWRWKHFODVVKLHUDUFK\$QRYHU
ULGGHQPHWKRGQDPHG acceptPXVWEHDGGHGZKLFKWDNHVD VisitorSDUDPHWHU7KLV
PHWKRGPXVWEHRYHUULGGHQIRUHDFKFODVV,WFDOOVWKHFRUUHVSRQGLQJPHWKRGGHILQHG
RQWKHvisitorLQVWDQFHSDVVLQJthisDVWKHDUJXPHQW
)LQDOO\QRWHWKDWZHGHFODUHGShapeWREHsealed,WZRQ¦WKHOSXVSUHYHQWVRPHEXJV
LQWKH9LVLWRU3DWWHUQLPSOHPHQWDWLRQEXWLWZLOOSURYHXVHIXOVKRUWO\
+HUHLVDFRQFUHWHYLVLWRUWKDWVXSSRUWVRXURULJLQDOdrawRSHUDWLRQ
// code-examples/AppDesign/patterns/shapes-drawing-visitor.scala

package shapes {
class ShapeDrawingVisitor extends ShapeVisitor {
def visit(circle: Circle): Unit =
println("Circle.draw: " + circle)

Design Patterns | 327

Download at WoweBook.Com
def visit(rect: Rectangle): Unit =
println("Rectangle.draw: " + rect)

def visit(tri: Triangle): Unit =


println("Triangle.draw: " + tri)
}
}

)RUHDFKvisitPHWKRGLW£GUDZV¤WKHShapeLQVWDQFHDSSURSULDWHO\)LQDOO\KHUHLVD
VFULSWWKDWH[HUFLVHVWKHFRGH
// code-examples/AppDesign/patterns/shapes-drawing-visitor-script.scala

import shapes._

val p00 = Point(0.0, 0.0)


val p10 = Point(1.0, 0.0)
val p01 = Point(0.0, 1.0)

val list = List(Circle(p00, 5.0),


Rectangle(p00, 2.0, 3.0),
Triangle(p00, p10, p01))

val shapesDrawer = new ShapeDrawingVisitor


list foreach { _.accept(shapesDrawer) }

,WSURGXFHVWKHIROORZLQJRXWSXW
Circle.draw: Circle(Point(0.0,0.0),5.0)
Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,3.0)
Triangle.draw: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0))

9LVLWRUKDVEHHQFULWLFL]HGIRUEHLQJVRPHZKDWLQHOHJDQWDQGIRUEUHDNLQJWKH2SHQ
&ORVHG3ULQFLSOH 2&3VHH>0DUWLQ@ EHFDXVHLIWKHKLHUDUFK\FKDQJHV\RXDUH
IRUFHGWRHGLW DQGWHVWDQGUHGHSOR\ DOOWKHYLVLWRUVIRUWKDWKLHUDUFK\1RWHWKDWHYHU\
ShapeVisitorWUDLWKDVPHWKRGVWKDWKDUGFRGHLQIRUPDWLRQDERXWHYHU\ ShapeGHULYHG
W\SH7KHVHNLQGVRIFKDQJHVDUHDOVRHUURUSURQH
,QODQJXDJHVZLWK£RSHQW\SHV¤OLNH5XE\DQDOWHUQDWLYHWRWKH9LVLWRU3DWWHUQLVWR
FUHDWHDQHZVRXUFHILOHWKDWUHRSHQVDOOWKHW\SHVLQWKHKLHUDUFK\DQGLQVHUWVDQDS
SURSULDWHPHWKRGLPSOHPHQWDWLRQLQHDFKRQH1RPRGLILFDWLRQVWRWKHRULJLQDOVRXUFH
FRGHDUHUHTXLUHG
6FDODGRHVQRWVXSSRUWRSHQW\SHVRIFRXUVHEXWLWRIIHUVDIHZDOWHUQDWLYHV7KHILUVW
DSSURDFKZH¦OOGLVFXVVFRPELQHVSDWWHUQPDWFKLQJZLWKLPSOLFLWFRQYHUVLRQV/HW¦VEH
JLQE\UHIDFWRULQJWKHShapeVisitorFRGHWRUHPRYHWKH9LVLWRU3DWWHUQORJLF
// code-examples/AppDesign/patterns/shapes.scala

package shapes2 {
case class Point(x: Double, y: Double)

sealed abstract class Shape()

case class Circle(center: Point, radius: Double) extends Shape()

328 | Chapter 13:—Application Design

Download at WoweBook.Com
case class Rectangle(lowerLeft: Point, height: Double, width: Double)
extends Shape()

case class Triangle(point1: Point, point2: Point, point3: Point)


extends Shape()
}

,IZHZRXOGOLNHWRLQYRNHdrawDVDPHWKRGRQDQ\ShapeWKHQZHZLOOKDYHWRXVHDQ
LPSOLFLWFRQYHUVLRQWRDZUDSSHUFODVVZLWKWKHdrawPHWKRG
// code-examples/AppDesign/patterns/shapes-drawing-implicit.scala

package shapes2 {
class ShapeDrawer(val shape: Shape) {
def draw = shape match {
case c: Circle => println("Circle.draw: " + c)
case r: Rectangle => println("Rectangle.draw: " + r)
case t: Triangle => println("Triangle.draw: " + t)
}
}

object ShapeDrawer {
implicit def shape2ShapeDrawer(shape: Shape) = new ShapeDrawer(shape)
}
}

,QVWDQFHVRIShapeDrawerKROGDShapeREMHFW:KHQdrawLVFDOOHGWKHVKDSHLVSDWWHUQ
PDWFKHGEDVHGRQLWVW\SHWRGHWHUPLQHWKHDSSURSULDWHZD\WRGUDZLW
$FRPSDQLRQREMHFWGHFODUHVDQLPSOLFLWFRQYHUVLRQWKDWZUDSVDShapeLQDShapeDrawer
7KLVVFULSWH[HUFLVHVWKHFRGH
// code-examples/AppDesign/patterns/shapes-drawing-implicit-script.scala

import shapes2._

val p00 = Point(0.0, 0.0)


val p10 = Point(1.0, 0.0)
val p01 = Point(0.0, 1.0)

val list = List(Circle(p00, 5.0),


Rectangle(p00, 2.0, 3.0),
Triangle(p00, p10, p01))

import shapes2.ShapeDrawer._

list foreach { _.draw }

,WSURGXFHVWKHVDPHRXWSXWDVWKHH[DPSOHXVLQJWKH9LVLWRU3DWWHUQ
7KLVLPSOHPHQWDWLRQRIShapeDrawerKDVVRPHVLPLODULWLHVZLWKWKH9LVLWRU3DWWHUQEXW
LWLVPRUHFRQFLVHHOHJDQWDQGUHTXLUHVQRFRGHPRGLILFDWLRQVWRWKHRULJLQDO Shape
KLHUDUFK\

Design Patterns | 329

Download at WoweBook.Com
7HFKQLFDOO\WKHLPSOHPHQWDWLRQKDVWKHVDPH2&3LVVXHDVWKH9LVLWRU3DWWHUQ&KDQJ
LQJWKHShapeKLHUDUFK\UHTXLUHVDFKDQJHWRWKHSDWWHUQPDWFKLQJH[SUHVVLRQ+RZHYHU
WKHUHTXLUHGFKDQJHVDUHLVRODWHGWRRQHSODFHDQGWKH\DUHPRUHVXFFLQFW,QIDFWDOO
WKHORJLFIRUGUDZLQJLVQRZFRQWDLQHGLQRQHSODFHUDWKHUWKDQVHSDUDWHGLQWR draw
PHWKRGVLQHDFK ShapeFODVVDQGSRWHQWLDOO\VFDWWHUHGDFURVVGLIIHUHQWILOHV1RWHWKDW
EHFDXVHZHsealedWKHKLHUDUFK\DFRPSLODWLRQHUURULQdrawZLOORFFXULIZHIRUJHWWR
FKDQJHLWZKHQWKHKLHUDUFK\FKDQJHV
,IZHGRQ¦WOLNHWKHSDWWHUQPDWFKLQJLQWKHGUDZPHWKRGZHFRXOGLPSOHPHQWDVHS
DUDWH£GUDZHU¤FODVVDQGDVHSDUDWHLPSOLFLWFRQYHUVLRQIRUHDFKShapeFODVV7KDWZRXOG
DOORZXVWRNHHSHDFKVKDSHGUDZLQJRSHUDWLRQLQDVHSDUDWHILOHIRUPRGXODULW\ZLWK
WKHGUDZEDFNRIPRUHFRGHDQGILOHVWRPDQDJH
,IRQWKHRWKHUKDQGZHGRQ¦WFDUHDERXWXVLQJWKHREMHFWRULHQWHGshape.drawV\QWD[
ZHFRXOGHOLPLQDWHWKHLPSOLFLWFRQYHUVLRQDQGGRWKHVDPHSDWWHUQPDWFKLQJWKDWLV
GRQHLQ ShapeDrawer.draw7KLVDSSURDFKFRXOGEHVLPSOHUHVSHFLDOO\ZKHQWKHH[WUD
EHKDYLRUFDQEHLVRODWHGWRRQHSODFH,QGHHGWKLVDSSURDFKZRXOGEHDFRQYHQWLRQDO
IXQFWLRQDODSSURDFKDVLOOXVWUDWHGLQWKHIROORZLQJVFULSW
// code-examples/AppDesign/patterns/shapes-drawing-pattern-script.scala

import shapes2._

val p00 = Point(0.0, 0.0)


val p10 = Point(1.0, 0.0)
val p01 = Point(0.0, 1.0)

val list = List(Circle(p00, 5.0),


Rectangle(p00, 2.0, 3.0),
Triangle(p00, p10, p01))

val drawText = (shape:Shape) => shape match {


case circle: Circle => println("Circle.draw: " + circle)
case rect: Rectangle => println("Rectangle.draw: " + rect)
case tri: Triangle => println("Triangle.draw: " + tri)
}

def pointToXML(point: Point) =


"<point><x>%.1f</x><y>%.1f</y></point>".format(point.x, point.y)

val drawXML = (shape:Shape) => shape match {


case circle: Circle => {
println("<circle>")
println(" <center>" + pointToXML(circle.center) + "</center>")
println(" <radius>" + circle.radius + "</radius>")
println("</circle>")
}
case rect: Rectangle => {
println("<rectangle>")
println(" <lower-left>" + pointToXML(rect.lowerLeft) + "</lower-left>")
println(" <height>" + rect.height + "</height>")
println(" <width>" + rect.width + "</width>")

330 | Chapter 13:—Application Design

Download at WoweBook.Com
println("</rectangle>")
}
case tri: Triangle => {
println("<triangle>")
println(" <point1>" + pointToXML(tri.point1) + "</point1>")
println(" <point2>" + pointToXML(tri.point2) + "</point2>")
println(" <point3>" + pointToXML(tri.point3) + "</point3>")
println("</triangle>")
}
}

list foreach (drawText)


println("")
list foreach (drawXML)

:H GHILQH WZR IXQFWLRQ YDOXHV DQG DVVLJQ WKHP WR YDULDEOHV drawText DQG drawXML
UHVSHFWLYHO\(DFKdrawXIXQFWLRQWDNHVDQLQSXWShapeSDWWHUQPDWFKHVLWWRWKHFRUUHFW
W\SH DQG £GUDZV¤ LW DSSURSULDWHO\ :H DOVR GHILQH D KHOSHU PHWKRG WR FRQYHUW D
PointWR;0/LQWKHIRUPDWZHZDQW
)LQDOO\ZHORRSWKURXJKWKHOLVWRIVKDSHVWZLFH7KHILUVWWLPHZHSDVV drawTextDV
WKHDUJXPHQWWR foreach7KHVHFRQGWLPHZHSDVV drawXML5XQQLQJWKLVVFULSWUH
SURGXFHVWKHSUHYLRXVUHVXOWVIRU£WH[W¤RXWSXWIROORZHGE\QHZ;0/RXWSXW
Circle.draw: Circle(Point(0.0,0.0),5.0)
Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,3.0)
Triangle.draw: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0))

<circle>
<center><point><x>0.0</x><y>0.0</y></point></center>
<radius>5.0</radius>
</circle>
<rectangle>
<lower-left><point><x>0.0</x><y>0.0</y></point></lower-left>
<height>2.0</height>
<width>3.0</width>
</rectangle>
<triangle>
<point1><point><x>0.0</x><y>0.0</y></point></point1>
<point2><point><x>1.0</x><y>0.0</y></point></point2>
<point3><point><x>0.0</x><y>1.0</y></point></point3>
</triangle>

$Q\RIWKHVHLGLRPVSURYLGHVDSRZHUIXOZD\WRDGGDGGLWLRQDOVSHFLDOSXUSRVHIXQF
WLRQDOLW\WKDWPD\QRWEHQHHGHG£HYHU\ZKHUH¤LQWKHDSSOLFDWLRQ,W¦VDJUHDWZD\WR
UHPRYHPHWKRGVIURPREMHFWVWKDWGRQ¦WDEVROXWHO\KDYHWREHWKHUH
$GUDZLQJDSSOLFDWLRQVKRXOGRQO\QHHGWRNQRZKRZWRGRLQSXWDQGRXWSXWRIVKDSHV
LQRQHSODFHZKHWKHULWLVVHULDOL]LQJVKDSHVWRDWH[WXDOIRUPDWIRUVWRUDJHRUUHQGHULQJ
VKDSHV WR WKH VFUHHQ :H FDQ VHSDUDWH WKH GUDZLQJ £FRQFHUQ¤ IURP WKH UHVW RI WKH
IXQFWLRQDOLW\IRUVKDSHVDQGZHFDQLVRODWHWKHORJLFIRUGUDZLQJDOOZLWKRXWPRGLI\LQJ
WKHShapeKLHUDUFK\RUDQ\RIWKHSODFHVZKHUHLWLVXVHGLQWKHDSSOLFDWLRQ7KH9LVLWRU

Design Patterns | 331

Download at WoweBook.Com
3DWWHUQJLYHVXVVRPHRIWKLVVHSDUDWLRQDQGLVRODWLRQEXWZHDUHUHTXLUHGWRDGGYLVLWRU
LPSOHPHQWDWLRQORJLFWRHDFKShape
/HW¦VFRQFOXGHZLWKDGLVFXVVLRQRIRQHRWKHURSWLRQWKDWPD\EHDSSOLFDEOHLQVRPH
FRQWH[WV,I\RXKDYHFRPSOHWHFRQWURORYHUKRZVKDSHVDUHFRQVWUXFWHGHJWKURXJK
DVLQJOHIDFWRU\\RXFDQPRGLI\WKHIDFWRU\WRPL[LQWUDLWVWKDWDGGQHZEHKDYLRUVDV
QHHGHG
// code-examples/AppDesign/patterns/shapes-drawing-factory.scala

package shapes2 {
trait Drawing {
def draw: Unit
}

trait CircleDrawing extends Drawing {


def draw = println("Circle.draw " + this)
}
trait RectangleDrawing extends Drawing {
def draw = println("Rectangle.draw: " + this)
}
trait TriangleDrawing extends Drawing {
def draw = println("Triangle.draw: " + this)
}

object ShapeFactory {
def makeShape(args: Any*) = args(0) match {
case "circle" => {
val center = args(1).asInstanceOf[Point]
val radius = args(2).asInstanceOf[Double]
new Circle(center, radius) with CircleDrawing
}
case "rectangle" => {
val lowerLeft = args(1).asInstanceOf[Point]
val height = args(2).asInstanceOf[Double]
val width = args(3).asInstanceOf[Double]
new Rectangle(lowerLeft, height, width) with RectangleDrawing
}
case "triangle" => {
val p1 = args(1).asInstanceOf[Point]
val p2 = args(2).asInstanceOf[Point]
val p3 = args(3).asInstanceOf[Point]
new Triangle(p1, p2, p3) with TriangleDrawing
}
case x => throw new IllegalArgumentException("unknown: " + x)
}
}
}

:HGHILQHD DrawingWUDLWDQGFRQFUHWHGHULYHGWUDLWVIRUHDFK ShapeFODVV7KHQZH


GHILQHD ShapeFactoryREMHFWZLWKD makeShapeIDFWRU\PHWKRGWKDWWDNHVDYDULDEOH
OHQJWKOLVWRIDUJXPHQWV$PDWFKLVGRQHRQWKHILUVWDUJXPHQWWRGHWHUPLQHZKLFK
VKDSHWRPDNH7KHWUDLOLQJDUJXPHQWVDUHFDVWWRDSSURSULDWHW\SHVWRFRQVWUXFWHDFK
VKDSHZLWKWKHFRUUHVSRQGLQJGUDZLQJWUDLWPL[HGLQ$VLPLODUIDFWRU\FRXOGEHZULWWHQ

332 | Chapter 13:—Application Design

Download at WoweBook.Com
IRU DGGLQJ GUDZ PHWKRGV WKDW RXWSXW ;0/ 7KH YDULDEOHOHQJWK OLVW RI Any YDOXHV
KHDY\XVHRIFDVWLQJDQGPLQLPDOHUURUFKHFNLQJZHUHGRQHIRUH[SHGLHQF\$UHDO
LPSOHPHQWDWLRQFRXOGPLQLPL]HWKHVH£KDFNV¤
7KHIROORZLQJVFULSWH[HUFLVHVWKHIDFWRU\
// code-examples/AppDesign/patterns/shapes-drawing-factory-script.scala

import shapes2._

val p00 = Point(0.0, 0.0)


val p10 = Point(1.0, 0.0)
val p01 = Point(0.0, 1.0)

val list = List(


ShapeFactory.makeShape("circle", p00, 5.0),
ShapeFactory.makeShape("rectangle", p00, 2.0, 3.0),
ShapeFactory.makeShape("triangle", p00, p10, p01))

list foreach { _.draw }

&RPSDUHGWRRXUSUHYLRXVVFULSWVWKHOLVWRIVKDSHVLVQRZFRQVWUXFWHGXVLQJWKHIDF
WRU\:KHQZHZDQWWRGUDZWKHVKDSHVLQWKHforeachVWDWHPHQWZHVLPSO\FDOOdraw
RQHDFKVKDSH$VEHIRUHWKHRXWSXWLVWKHIROORZLQJ
Circle.draw Circle(Point(0.0,0.0),5.0)
Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,3.0)
Triangle.draw: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0))

7KHUHLVRQHVXEWOHW\ZLWKWKLVDSSURDFKWKDWZHVKRXOGGLVFXVV1RWLFHWKDWWKHVFULSW
QHYHUDVVLJQVWKHUHVXOWRID ShapeFactory.makeShapeFDOOWRD ShapeYDULDEOH,ILWGLG
WKDWLWZRXOGQRWEHDEOHWRFDOOdrawRQWKHLQVWDQFH
,QWKLVVFULSW6FDODLQIHUUHGDVOLJKWO\GLIIHUHQWFRPPRQVXSHUW\SHIRUWKHSDUDPHWHUL]HG
OLVW<RXFDQVHHWKDWW\SHLI\RXXVHWKH:loadFRPPDQGWRORDGWKHVFULSWZKLOHLQVLGH
WKHLQWHUDFWLYHscalaLQWHUSUHWHUDVLQWKHIROORZLQJVHVVLRQ
$ scala -cp ...
Welcome to Scala version 2.8.0.final (Java ...).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :load design-patterns/shapes-drawing-factory-script.scala


Loading design-patterns/shapes-drawing-factory-script.scala...
import shapes2._
p00: shapes2.Point = Point(0.0,0.0)
p10: shapes2.Point = Point(1.0,0.0)
p01: shapes2.Point = Point(0.0,1.0)
list: List[Product with shapes2.Shape with shapes2.Drawing] = List(...)
Circle.draw Circle(Point(0.0,0.0),5.0)
Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,3.0)
Triangle.draw: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0))

scala>

Design Patterns | 333

Download at WoweBook.Com
1RWLFH WKH OLQH WKDW EHJLQV list: List[Product with shapes2.Shape with
shapes2.Drawing]7KLVOLQHZDVSULQWHGDIWHUWKHOLVWRIVKDSHVZDVSDUVHG7KHLQIHUUHG
FRPPRQVXSHUW\SHLVProduct with shapes2.Shape with shapes2.DrawingProductLVD
WUDLWPL[HGLQWRDOOFDVHFODVVHVVXFKDVRXUFRQFUHWHVXEFODVVHVRIShape5HFDOOWKDWWR
DYRLG FDVHFODVV LQKHULWDQFH Shape LWVHOI LV QRW D FDVH FODVV 6HH £&DVH
&ODVVHV¤RQSDJHIRUGHWDLOVRQZK\FDVHFODVVLQKHULWDQFHVKRXOGEHDYRLGHG 6R
RXUFRPPRQVXSHUW\SHLVDQDQRQ\PRXVFODVVWKDWLQFRUSRUDWHV Shape ProductDQG
WKHDrawingWUDLW
,I\RXZDQWWRDVVLJQRQHRIWKHVHGUDZDEOHVKDSHVWRDYDULDEOHDQGVWLOOEHDEOHWR
LQYRNHdrawXVHDGHFODUDWLRQOLNHWKHIROORZLQJ VKRZQDVDFRQWLQXDWLRQRIWKHVDPH
LQWHUDFWLYHscalaVHVVLRQ 
scala> val s: Shape with Drawing = ShapeFactory.makeShape("circle", p00, 5.0)
s: shapes2.Shape with shapes2.Drawing = Circle(Point(0.0,0.0),5.0)

scala> s.draw
Circle.draw Circle(Point(0.0,0.0),5.0)

scala>

Dependency Injection in Scala: The Cake Pattern


'HSHQGHQF\LQMHFWLRQ ', DIRUPRILQYHUVLRQRIFRQWURO ,R& LVDSRZHUIXOWHFKQLTXH
IRUUHVROYLQJGHSHQGHQFLHVEHWZHHQ£FRPSRQHQWV¤LQODUJHUDSSOLFDWLRQV,WVXSSRUWV
PLQLPL]LQJWKHFRXSOLQJEHWZHHQWKHVHFRPSRQHQWVVRLWLVUHODWLYHO\HDV\WRVXEVWLWXWH
GLIIHUHQWFRPSRQHQWVIRUGLIIHUHQWFLUFXPVWDQFHV
,WXVHGWREHWKDWZKHQDFOLHQWREMHFWQHHGHGDGDWDEDVH£DFFHVVRU¤REMHFWIRUH[DPSOH
LWZRXOGMXVWLQVWDQWLDWHWKHDFFHVVRULWVHOI:KLOHFRQYHQLHQWWKLVDSSURDFKPDNHVXQLW
WHVWLQJYHU\GLIILFXOWEHFDXVH\RXKDYHWRWHVWZLWKDUHDOGDWDEDVH,WDOVRFRPSURPLVHV
UHXVHIRUWKRVHDOWHUQDWLYHVLWXDWLRQVZKHUHDQRWKHUSHUVLVWHQFHPHFKDQLVP RUQRQH
LVUHTXLUHG,QYHUVLRQRIFRQWUROVROYHVWKLVSUREOHPE\UHYHUVLQJUHVSRQVLELOLW\IRUVDW
LVI\LQJWKHGHSHQGHQF\EHWZHHQWKHREMHFWDQGWKHGDWDEDVHFRQQHFWLRQ
$QH[DPSOHRI,R&LV-1',,QVWHDGRILQVWDQWLDWLQJDQDFFHVVRUREMHFWWKHFOLHQWREMHFW
DVNV-'1,WRSURYLGHRQH7KHFOLHQWGRHVQ¦WFDUHZKDWDFWXDOW\SHRIDFFHVVRULVUH
WXUQHG+HQFHWKHFOLHQWREMHFWLVQRORQJHUFRXSOHGWRDFRQFUHWHLPSOHPHQWDWLRQRI
WKHGHSHQGHQF\,WRQO\GHSHQGVRQDQDSSURSULDWHDEVWUDFWLRQRIDSHUVLVWHQFHDFFHVVRU
LHD-DYDLQWHUIDFHRU6FDODWUDLW
'HSHQGHQF\LQMHFWLRQWDNHV,R&WRLWVORJLFDOFRQFOXVLRQ1RZWKHREMHFWGRHVQRWKLQJ
WRUHVROYHWKHGHSHQGHQF\,QVWHDGDQH[WHUQDOPHFKDQLVPZLWKV\VWHPZLGHNQRZO
HGJH£LQMHFWV¤WKHDSSURSULDWHDFFHVVRUREMHFWXVLQJDFRQVWUXFWRUDUJXPHQWRUDVHWWHU
PHWKRG7KLVKDSSHQVZKHQWKHFOLHQWLVFRQVWUXFWHG',HOLPLQDWHVGHSHQGHQFLHVRQ
,R&PHFKDQLVPVLQFRGH HJQRPRUH-1',FDOOV DQGNHHSVREMHFWVUHODWLYHO\VLPSOH
ZLWKPLQLPDOFRXSOLQJWRRWKHUREMHFWV

334 | Chapter 13:—Application Design

Download at WoweBook.Com
%DFNWRXQLWWHVWLQJLWLVSUHIHUDEOHWRXVHDWHVWGRXEOHIRUKHDY\ZHLJKWGHSHQGHQFLHV
WRPLQLPL]HWKHRYHUKHDGDQGRWKHUFRPSOLFDWLRQVRIWHVWLQJ2XUFOLHQWREMHFWZLWKD
GHSHQGHQF\RQDGDWDEDVHDFFHVVRUREMHFWLVDFODVVLFH[DPSOH:KLOHXQLWWHVWLQJWKH
FOLHQWWKHRYHUKHDGDQGFRPSOLFDWLRQVRIXVLQJDUHDOGDWDEDVHDUHSURKLELWLYH8VLQJ
DOLJKWZHLJKWWHVWGRXEOHZLWKKDUGFRGHGVDPSOHGDWDSURYLGHVVLPSOHUVHWXSDQGWHDU
GRZQIDVWHUH[HFXWLRQDQGSUHGLFWDEOHEHKDYLRUIURPWKHGDWDDFFHVVRUGHSHQGHQF\
,Q -DYD ', LV XVXDOO\ GRQH XVLQJ DQ LQYHUVLRQ RI FRQWURO FRQWDLQHU OLNH WKH 6SULQJ
)UDPHZRUN >6SULQJ)UDPHZRUN@ RUD-DYD$3,HTXLYDOHQWOLNH*RRJOH¦V*XLFH$3,
VHH >*XLFH@  7KHVH RSWLRQV FDQ EH XVHG ZLWK 6FDOD FRGH HVSHFLDOO\ ZKHQ \RX DUH
LQWURGXFLQJ6FDODLQWRDPDWXUH-DYDHQYLURQPHQW
+RZHYHU6FDODRIIHUVVRPHXQLTXHRSWLRQVIRULPSOHPHQWLQJ',LQ6FDODFRGHZKLFK
DUHGLVFXVVHGE\>%RQpUE@:H¦OOGLVFXVVRQHRIWKHPWKH&DNH3DWWHUQZKLFKFDQ
UHSODFHRUFRPSOHPHQWWKHVHRWKHUGHSHQGHQF\LQMHFWLRQPHFKDQLVPV:H¦OOVHHWKDW
LWLVVLPLODUWRWKHLPSOHPHQWDWLRQRIWKH2EVHUYHU3DWWHUQZHGLVFXVVHGHDUOLHULQWKLV
FKDSWHULQ£6HOI7\SH$QQRWDWLRQVDQG$EVWUDFW7\SH0HPEHUV¤RQSDJH7KH
&DNH3DWWHUQZDVGHVFULEHGE\>2GHUVN\@DOWKRXJKLWZDVJLYHQWKDWQDPHDIWHU
WKDWSDSHUZDVSXEOLVKHG>%RQpUE@DOVRGLVFXVVHVDOWHUQDWLYHV
/HW¦VEXLOGDVLPSOHFRPSRQHQWPRGHOIRUDQRYHUO\VLPSOLILHG7ZLWWHUFOLHQW:HZDQW
DFRQILJXUDEOH8,DFRQILJXUDEOHORFDOFDFKHRISDVWWZHHWVDQGDFRQILJXUDEOHFRQ
QHFWLRQWRWKH7ZLWWHUVHUYLFHLWVHOI(DFKRIWKHVH£FRPSRQHQWV¤ZLOOEHVSHFLILHGVHS
DUDWHO\DORQJZLWKDFOLHQWFRPSRQHQWWKDWZLOOIXQFWLRQDVWKH£PLGGOHZDUH¤WKDWWLHV
WKHDSSOLFDWLRQWRJHWKHU7KHFOLHQWFRPSRQHQWZLOOGHSHQGRQWKHRWKHUFRPSRQHQWV
:KHQZHFUHDWHDFRQFUHWHFOLHQWZH¦OOFRQILJXUHLQWKHFRQFUHWHSLHFHVRIWKHRWKHU
FRPSRQHQWVWKDWZHQHHG
// code-examples/AppDesign/dep-injection/twitter-client.scala

package twitterclient
import java.util.Date
import java.text.DateFormat

class TwitterUserProfile(val userName: String) {


override def toString = "@" + userName
}

case class Tweet(


val tweeter: TwitterUserProfile,
val message: String,
val time: Date) {

override def toString = "(" +


DateFormat.getDateInstance(DateFormat.FULL).format(time) + ") " +
tweeter + ": " + message
}

trait Tweeter {
def tweet(message: String)
}

Design Patterns | 335

Download at WoweBook.Com
trait TwitterClientUIComponent {
val ui: TwitterClientUI

abstract class TwitterClientUI(val client: Tweeter) {


def sendTweet(message: String) = client.tweet(message)
def showTweet(tweet: Tweet): Unit
}
}

trait TwitterLocalCacheComponent {
val localCache: TwitterLocalCache

trait TwitterLocalCache {
def saveTweet(tweet: Tweet): Unit
def history: List[Tweet]
}
}

trait TwitterServiceComponent {
val service: TwitterService

trait TwitterService {
def sendTweet(tweet: Tweet): Boolean
def history: List[Tweet]
}
}

trait TwitterClientComponent {
self: TwitterClientUIComponent with
TwitterLocalCacheComponent with
TwitterServiceComponent =>

val client: TwitterClient

class TwitterClient(val user: TwitterUserProfile) extends Tweeter {


def tweet(msg: String) = {
val twt = new Tweet(user, msg, new Date)
if (service.sendTweet(twt)) {
localCache.saveTweet(twt)
ui.showTweet(twt)
}
}
}
}

7KHILUVWFODVVTwitterUserProfileHQFDSVXODWHVDXVHU¦VSURILOHZKLFKZHOLPLWWRWKH
XVHUQDPH7KHVHFRQGFODVVLVDFDVHFODVVTweetWKDWHQFDSVXODWHVDVLQJOH£WZHHW¤ D
7ZLWWHUPHVVDJHOLPLWHGWRFKDUDFWHUVE\WKH7ZLWWHUVHUYLFH %HVLGHVWKHPHVVDJH
VWULQJLWHQFDSVXODWHVWKHXVHUZKRVHQWWKHWZHHWDQGWKHGDWHDQGWLPHZKHQLWZDV
VHQW:HPDGHWKLVFODVVDFDVHFODVVIRUWKHFRQYHQLHQWVXSSRUWFDVHFODVVHVSURYLGH
IRUFUHDWLQJREMHFWVDQGSDWWHUQPDWFKLQJRQWKHP:HGLGQ¦WPDNHWKHSURILOHFODVVD
FDVHFODVVEHFDXVHLWLVPRUHOLNHO\WREHXVHGDVWKHSDUHQWRIPRUHGHWDLOHGSURILOH
FODVVHV

336 | Chapter 13:—Application Design

Download at WoweBook.Com
1H[WLVWKHTweeterWUDLWWKDWGHFODUHVRQHPHWKRGtweet7KLVWUDLWLVGHILQHGVROHO\WR
HOLPLQDWH D SRWHQWLDO FLUFXODU GHSHQGHQF\ EHWZHHQ WZR FRPSRQHQWV TwitterClient
ComponentDQGTwitterClientUIComponent$OOWKHFRPSRQHQWVDUHGHILQHGQH[WLQWKH
ILOH
7KHUHDUHIRXUFRPSRQHQWV1RWHWKDWWKH\DUHLPSOHPHQWHGDVWUDLWV
‡ TwitterClientUIComponentIRUWKH8,
‡ TwitterLocalCacheComponentIRUWKHORFDOFDFKHRISULRUWZHHWV
‡ TwitterServiceComponentIRUDFFHVVLQJWKH7ZLWWHUVHUYLFH
‡ TwitterClientComponentWKHFOLHQWWKDWSXOOVWKHSLHFHVWRJHWKHU
7KH\DOOKDYHDVLPLODUVWUXFWXUH(DFKRQHGHFODUHVDQHVWHGWUDLWRUFODVVWKDWHQFDS
VXODWHVWKHFRPSRQHQW¦VEHKDYLRU(DFKRQHDOVRGHFODUHVD valZLWKRQHLQVWDQFHRI
WKHQHVWHGW\SH
2IWHQLQ-DYDSDFNDJHVDUHLQIRUPDOO\DVVRFLDWHGZLWKFRPSRQHQWV7KLVLVFRPPRQ
LQRWKHUODQJXDJHVWRRXVLQJWKHLUHTXLYDOHQWRIDSDFNDJHHJDPRGXOHRUDQDPH
VSDFH+HUHZHGHILQHDPRUHSUHFLVHQRWLRQRIDFRPSRQHQWDQGDWUDLWLVWKHEHVW
YHKLFOHIRULWEHFDXVHWUDLWVDUHGHVLJQHGIRUPL[LQFRPSRVLWLRQ
TwitterClientUIComponent GHFODUHV D val QDPHG ui RI WKH QHVWHG W\SH Twitter
ClientUI7KLVFODVVKDVDclientILHOGWKDWPXVWEHLQLWLDOL]HGZLWKDTweeterLQVWDQFH
,Q IDFW WKLV LQVWDQFH ZLOO EH D TwitterClient GHILQHG LQ TwitterClientComponent 
ZKLFKH[WHQGVTweeter
TwitterClientUIKDVWZRPHWKRGV7KHILUVWLV sendTweetZKLFKLVGHILQHGWRFDOOWKH
clientREMHFW7KLVPHWKRGZRXOGEHXVHGE\WKH8,WRFDOOWKHFOLHQWZKHQWKHXVHU
VHQGVDQHZWZHHW7KHVHFRQGPHWKRGshowTweetJRHVWKHRWKHUGLUHFWLRQ,WLVFDOOHG
ZKHQHYHUDQHZWZHHWLVWREHGLVSOD\HGHJIURPDQRWKHUXVHU,WLVDEVWUDFWSHQGLQJ
WKH£GHFLVLRQ¤RIWKHNLQGRI8,WRXVH
6LPLODUO\TwitterLocalCacheComponentGHFODUHVTwitterLocalCacheDQGDQLQVWDQFHRI
LW,QVWDQFHVZLWKWKLVWUDLWVDYHWZHHWVWRWKHORFDOSHUVLVWHQWFDFKHZKHQsaveTweetLV
FDOOHG<RXFDQUHWULHYHWKHFDFKHGWZHHWVZLWKhistory
TwitterServiceComponentLVYHU\VLPLODU,WVQHVWHGW\SHKDVDPHWKRGsendTweetWKDW
VHQGVDQHZWZHHWWR7ZLWWHU,WDOVRKDVDhistoryPHWKRGWKDWUHWULHYHVDOOWKHWZHHWV
IRUWKHFXUUHQWXVHU
)LQDOO\TwitterClientComponentFRQWDLQVDFRQFUHWHFODVVTwitterClientWKDWLQWHJUD
WHVWKHFRPSRQHQWV,WVRQH tweetPHWKRGVHQGVQHZWZHHWVWRWKH7ZLWWHUVHUYLFH,I
VXFFHVVIXOLWVHQGVWKHWZHHWEDFNWRWKH8,DQGWRWKHORFDOSHUVLVWHQWFDFKH
TwitterClientComponentDOVRKDVWKHIROORZLQJVHOIW\SHDQQRWDWLRQ
self: TwitterClientUIComponent with
TwitterLocalCacheComponent with
TwitterServiceComponent =>

Design Patterns | 337

Download at WoweBook.Com
7KHHIIHFWRIWKLVGHFODUDWLRQLVWRVD\WKDWDQ\FRQFUHWH TwitterClientComponentPXVW
DOVREHKDYHOLNHWKHVHRWKHUWKUHHFRPSRQHQWVWKHUHE\FRPSRVLQJDOOWKHFRPSRQHQWV
LQWRRQHFOLHQWDSSOLFDWLRQLQVWDQFH7KLVFRPSRVLWLRQZLOOEHUHDOL]HGE\PL[LQJLQ
WKHVHFRPSRQHQWVZKLFKDUHWUDLWVZKHQZHFUHDWHFRQFUHWHFOLHQWVDVZHZLOOVHH
VKRUWO\
7KHVHOIW\SHDQQRWDWLRQDOVRPHDQVZHFDQUHIHUHQFHWKHvalsGHFODUHGLQWKHVHFRP
SRQHQWV1RWLFHKRZTwitterClient.tweetUHIHUHQFHVWKHservicelocalCacheDQGWKH
uiDVLIWKH\DUHYDULDEOHVLQWKHVFRSHRIWKLVPHWKRG,QIDFWWKH\DUHLQVFRSHEHFDXVH
RIWKHVHOIW\SHDQQRWDWLRQ
1RWLFHDOVRWKDWDOOWKHPHWKRGVWKDWFDOORWKHUFRPSRQHQWVDUHFRQFUHWH7KRVHLQWHU
FRPSRQHQWUHODWLRQVKLSVDUHIXOO\VSHFLILHG7KHDEVWUDFWLRQVDUHGLUHFWHG£RXWZDUG¤
WRZDUGWKHJUDSKLFDOXVHULQWHUIDFHDFDFKLQJPHFKDQLVPHWF
/HW¦VQRZGHILQHDFRQFUHWH7ZLWWHUFOLHQWWKDWXVHVDWH[WXDO FRPPDQGOLQH 8,DQ
LQPHPRU\ORFDOFDFKHDQGIDNHVWKHLQWHUDFWLRQZLWKWKH7ZLWWHUVHUYLFH
// code-examples/AppDesign/dep-injection/twitter-text-client.scala

package twitterclient

class TextClient(userProfile: TwitterUserProfile)


extends TwitterClientComponent
with TwitterClientUIComponent
with TwitterLocalCacheComponent
with TwitterServiceComponent {

// From TwitterClientComponent:

val client = new TwitterClient(userProfile)

// From TwitterClientUIComponent:

val ui = new TwitterClientUI(client) {


def showTweet(tweet: Tweet) = println(tweet)
}

// From TwitterLocalCacheComponent:

val localCache = new TwitterLocalCache {


private var tweets: List[Tweet] = Nil

def saveTweet(tweet: Tweet) = tweets ::= tweet

def history = tweets


}

// From TwitterServiceComponent

val service = new TwitterService() {


def sendTweet(tweet: Tweet) = {
println("Sending tweet to Twitter HQ")

338 | Chapter 13:—Application Design

Download at WoweBook.Com
true
}
def history = List[Tweet]()
}
}

2XUTextClientFRQFUHWHFODVVH[WHQGVTwitterClientComponentDQGPL[HVLQWKHWKUHH
RWKHUFRPSRQHQWV%\PL[LQJLQWKHRWKHUFRPSRQHQWVZHVDWLVI\WKHVHOIW\SHDQQR
WDWLRQVLQTwitterClientComponent,QRWKHUZRUGVTextClientLVDOVRDTwitterClientUI
ComponentDTwitterLocalCacheComponentDQGDTwitterServiceComponentLQDGGLWLRQ
WREHLQJDTwitterClientComponent
7KH TextClientFRQVWUXFWRUWDNHVRQHDUJXPHQWDXVHUSURILOHZKLFKZLOOEHSDVVHG
RQWRWKHQHVWHGFOLHQWFODVV
TextClientKDVWRGHILQHIRXU valsRQHIURP TwitterClientComponentDQGWKUHHIURP
WKHRWKHUPL[LQV)RUWKHclientLWVLPSO\FUHDWHVDQHZTwitterClientSDVVLQJLWWKH
userProfile
)RUWKHuiLWLQVWDQWLDWHVDQDQRQ\PRXVFODVVGHULYHGIURPTwitterClientUI,WGHILQHV
showTweetWRSULQWRXWWKHWZHHW
)RU WKH localCache LW LQVWDQWLDWHV DQ DQRQ\PRXV FODVV GHULYHG IURP
TwitterLocalCache,WNHHSVWKHKLVWRU\RIWZHHWVLQDList
)LQDOO\ IRU WKH service LW LQVWDQWLDWHV DQ DQRQ\PRXV FODVV GHULYHG IURP
TwitterService7KLV£IDNH¤GHILQHVsendTweetWRSULQWRXWDPHVVDJHDQGWRUHWXUQDQ
HPSW\OLVWIRUWKHKLVWRU\
/HW¦VWU\RXUFOLHQWZLWKWKHIROORZLQJVFULSW
// code-examples/AppDesign/dep-injection/twitter-text-client-script.scala

import twitterclient._

val client = new TextClient(new TwitterUserProfile("BuckTrends"))


client.ui.sendTweet("My First Tweet. How's this thing work?")
client.ui.sendTweet("Is this thing on?")
client.ui.sendTweet("Heading to the bathroom...")
println("Chat history:")
client.localCache.history.foreach {t => println(t)}

:HLQVWDQWLDWHDTextClientIRUWKHXVHU£%XFN7UHQGV¤2OG%XFNVHQGVWKUHHLQVLJKWIXO
WZHHWVWKURXJKWKH8,:HILQLVKE\UHSULQWLQJWKHKLVWRU\RIWZHHWVLQUHYHUVHRUGHU
WKDWDUHFDFKHGORFDOO\5XQQLQJWKLVVFULSW\LHOGVRXWSXWOLNHWKHIROORZLQJ
Sending tweet to Twitter HQ
(Sunday, May 3, 2009) @BuckTrends: My First Tweet. How's this thing work?
Sending tweet to Twitter HQ
(Sunday, May 3, 2009) @BuckTrends: Is this thing on?
Sending tweet to Twitter HQ
(Sunday, May 3, 2009) @BuckTrends: Heading to the bathroom...
Chat history:
(Sunday, May 3, 2009) @BuckTrends: Heading to the bathroom...

Design Patterns | 339

Download at WoweBook.Com
(Sunday, May 3, 2009) @BuckTrends: Is this thing on?
(Sunday, May 3, 2009) @BuckTrends: My First Tweet. How's this thing work?

<RXU GDWH ZLOO YDU\ RI FRXUVH 5HFDOO WKDW WKH Sending tweet to Twitter HQ OLQH LV
SULQWHGE\WKHIDNHVHUYLFH
7RUHFDSHDFKPDMRUFRPSRQHQWLQWKH7ZLWWHUFOLHQWZDVGHFODUHGLQLWVRZQWUDLW
ZLWK D QHVWHG W\SH IRU WKH FRPSRQHQW¦V ILHOGV DQG PHWKRGV 7KH FOLHQW FRPSRQHQW
GHFODUHGLWVGHSHQGHQFLHVRQWKHRWKHUFRPSRQHQWVWKURXJKDVHOIW\SHDQQRWDWLRQ7KH
FRQFUHWHFOLHQWFODVVPL[HGLQWKRVHFRPSRQHQWVDQGGHILQHGHDFKFRPSRQHQW valWR
EHDQDSSURSULDWHVXEW\SHRIWKHFRUUHVSRQGLQJDEVWUDFWFODVVHVDQGWUDLWVWKDWZHUH
GHFODUHGLQWKHFRPSRQHQWV
:HJHWW\SHVDIH£ZLULQJ¤WRJHWKHURIFRPSRQHQWVDIOH[LEOHFRPSRQHQWPRGHODQG
ZHGLGLWDOOLQ6FDODFRGH7KHUHDUHDOWHUQDWLYHVWRWKH&DNH3DWWHUQIRULPSOHPHQWLQJ
GHSHQGHQF\LQMHFWLRQLQ6FDOD6HH>%RQpUE@IRURWKHUH[DPSOHV

Better Design with Design By Contract


:H¦OOFRQFOXGHWKLVFKDSWHUZLWKDORRNDWDQDSSURDFKWRSURJUDPPLQJFDOOHG'HVLJQ
E\&RQWUDFW >'HVLJQ%\&RQWUDFW@ ZKLFKZDVGHYHORSHGE\%HUWUDQG0H\HUIRUWKH
(LIIHOODQJXDJH VHH>(LIIHO@>+XQW@DQG&KDSWHU 'HVLJQE\&RQWUDFWKDVEHHQ
DURXQGIRUDERXW\HDUV,WKDVIDOOHQVRPHZKDWRXWRIIDYRUEXWLWLVVWLOOYHU\XVHIXO
IRUWKLQNLQJDERXWGHVLJQ
:KHQFRQVLGHULQJWKH£FRQWUDFW¤RIDPRGXOH\RXFDQVSHFLI\WKUHHW\SHVRIFRQGLWLRQV
)LUVW\RXFDQVSHFLI\WKHUHTXLUHGLQSXWVIRUDPRGXOHWRVXFFHVVIXOO\SHUIRUPDVHUYLFH
HJZKHQDPHWKRGLVFDOOHG 7KHVHFRQVWUDLQWVDUHFDOOHGSUHFRQGLWLRQV7KH\FDQ
DOVRLQFOXGHV\VWHPUHTXLUHPHQWVHJJOREDOGDWD ZKLFK\RXVKRXOGQRUPDOO\DYRLG
RIFRXUVH 
<RXFDQDOVRVSHFLI\WKHUHVXOWVWKHPRGXOHJXDUDQWHHVWRGHOLYHUWKHSRVWFRQGLWLRQVLI
WKHSUHFRQGLWLRQVZHUHVDWLVILHG
)LQDOO\\RXFDQVSHFLI\LQYDULDQWVWKDWPXVWEHWUXHEHIRUHDQGDIWHUDQLQYRFDWLRQRI
DVHUYLFH
7KHVSHFLILFDGGLWLRQWKDW'HVLJQE\&RQWUDFWEULQJVLVWKHLGHDWKDWWKHVHFRQWUDFWXDO
FRQVWUDLQWVVKRXOGEHVSHFLILHGDVH[HFXWDEOHFRGHVRWKH\FDQEHHQIRUFHGDXWRPDWL
FDOO\DWUXQWLPHEXWXVXDOO\RQO\GXULQJWHVWLQJ
$FRQVWUDLQWIDLOXUHVKRXOGWHUPLQDWHH[HFXWLRQLPPHGLDWHO\IRUFLQJ\RXWRIL[WKHEXJ
2WKHUZLVHLWLVYHU\HDV\WRLJQRUHWKHVHEXJV
6FDODGRHVQ¦WSURYLGHH[SOLFLWVXSSRUWIRU'HVLJQE\&RQWUDFWEXWWKHUHDUHVHYHUDO
PHWKRGVLQ PredefWKDWFDQEHXVHGIRUWKLVSXUSRVH7KHIROORZLQJH[DPSOHVKRZV
KRZWRXVHrequireDQGassumeIRUFRQWUDFWHQIRUFHPHQW

340 | Chapter 13:—Application Design

Download at WoweBook.Com
// code-examples/AppDesign/design-by-contract/bank-account.scala

class BankAccount(val balance: Double) {


require(balance >= 0.0)
def debit(amount: Double) = {
require(amount > 0.0, "The debit amount must be > 0.0")
assume(balance - amount > 0.0, "Overdrafts are not permitted")
new BankAccount(balance - amount)
}
def credit(amount: Double) = {
require(amount > 0.0, "The credit amount must be > 0.0")
new BankAccount(balance + amount)
}
}

7KHFODVV BankAccountXVHV requireWRHQVXUHWKDWDQRQQHJDWLYHEDODQFHLVVSHFLILHG


IRUWKHFRQVWUXFWRU6LPLODUO\WKHdebitDQGcreditPHWKRGVXVHrequireWRHQVXUHWKDW
DSRVLWLYHamountLVVSHFLILHG
7KHVSHFLILFDWLRQLQ([DPSOHFRQILUPVWKDWWKH£FRQWUDFW¤LVREH\HG
([DPSOHGHVLJQE\FRQWUDFWEDQNDFFRXQWVSHFVFDOD7HVWLQJWKHFRQWUDFW
// code-examples/AppDesign/design-by-contract/bank-account-spec.scala

import org.specs._

object BankAccountSpec extends Specification {


"Creating an account with a negative balance" should {
"fail because the initial balance must be positive." in {
new BankAccount(-100.0) must throwAn[IllegalArgumentException]
}
}

"Debiting an account" should {


"fail if the debit amount is < 0" in {
val account = new BankAccount(100.0)
(account.debit(-10.0)) must throwAn[IllegalArgumentException]
}
}

"Debiting an account" should {


"fail if the debit amount is > the balance" in {
val account = new BankAccount(100.0)
(account.debit(110.0)) must throwAn[AssertionError]
}
}
}

,IZHDWWHPSWWRFUHDWHDBankAccountZLWKDQHJDWLYHEDODQFHDQIllegalArgumentExcep
tionLVWKURZQ6LPLODUO\WKHVDPHNLQGRIH[FHSWLRQLVWKURZQLIWKHGHELWDPRXQWLV
OHVV WKDQ ]HUR %RWK FRQGLWLRQV DUH HQIRUFHG XVLQJ require ZKLFK WKURZV DQ
IllegalArgumentExceptionZKHQWKHFRQGLWLRQVSHFLILHGLVIDOVH

Better Design with Design By Contract | 341

Download at WoweBook.Com
7KHassumePHWKRGZKLFKLVXVHGWRHQVXUHWKDWRYHUGUDIWVGRQ¦WRFFXULVIXQFWLRQDOO\
DOPRVW LGHQWLFDO WR require ,W WKURZV DQ AssertionError LQVWHDG RI DQ
IllegalArgumentException
%RWKrequireDQGassumeFRPHLQWZRIRUPVRQHWKDWWDNHVMXVWDERROHDQFRQGLWLRQ
DQGWKHRWKHUWKDWDOVRWDNHVDQHUURUPHVVDJHVWULQJ
7KHUHLVDOVRDQassertSDLURIPHWKRGVWKDWEHKDYHLGHQWLFDOO\WRassumeH[FHSWIRUD
VOLJKWFKDQJHLQWKHJHQHUDWHGIDLOXUHPHVVDJH3LFN assertRU assumeGHSHQGLQJRQ
ZKLFKRIWKHVH£QDPHV¤SURYLGHVDEHWWHUFRQFHSWXDOILWLQDJLYHQFRQWH[W
PredefDOVRGHILQHVDQEnsuringFODVVWKDWFDQEHXVHGWRJHQHUDOL]HWKHFDSDELOLWLHVRI
WKHVHPHWKRGVEnsuringKDVRQHRYHUORDGHGPHWKRGensureVRPHYHUVLRQVRIZKLFK
WDNHDIXQFWLRQOLWHUDODVD£SUHGLFDWH¤
$GUDZEDFNRIXVLQJWKHVHPHWKRGVDQGEnsuringLVWKDW\RXFDQ¦WGLVDEOHWKHVHFKHFNV
LQSURGXFWLRQ,WPD\QRWEHDFFHSWDEOHWRWHUPLQDWHDEUXSWO\LIDFRQGLWLRQIDLOVDO
WKRXJKLIWKHV\VWHPLVDOORZHGWR£OLPSDORQJ¤LWPLJKWFUDVKODWHUDQGWKHSUREOHP
ZRXOGEHKDUGHUWRGHEXJ7KHSHUIRUPDQFHRYHUKHDGPD\EHDQRWKHUUHDVRQWRGLVDEOH
FRQWUDFWFKHFNVDWUXQWLPH
7KHVHGD\VWKHJRDOVRI'HVLJQE\&RQWUDFWDUHODUJHO\PHWE\7HVW'ULYHQ'HYHORS
PHQW 7'' +RZHYHUWKLQNLQJLQWHUPVRI'HVLJQE\&RQWUDFWZLOOFRPSOHPHQWWKH
GHVLJQEHQHILWVRI7'',I\RXGHFLGHWRXVH'HVLJQE\&RQWUDFWLQ\RXUFRGHFRQVLGHU
FUHDWLQJDFXVWRPPRGXOHWKDWOHWV\RXGLVDEOHWKHWHVWVIRUSURGXFWLRQFRGH

Recap and What’s Next


:HOHDUQHGDQXPEHURISUDJPDWLFWHFKQLTXHVSDWWHUQVDQGLGLRPVIRUHIIHFWLYHDS
SOLFDWLRQGHYHORSPHQWXVLQJ6FDOD
*RRGWRROVDQGOLEUDULHVDUHLPSRUWDQWIRUEXLOGLQJDSSOLFDWLRQVLQDQ\ODQJXDJH7KH
QH[WFKDSWHUSURYLGHVPRUHGHWDLOVDERXW6FDOD¦VFRPPDQGOLQHWRROVGHVFULEHVWKH
VWDWHRI6FDOD,'(VXSSRUWDQGLQWURGXFHV\RXWRVRPHLPSRUWDQW6FDODOLEUDULHV

342 | Chapter 13:—Application Design

Download at WoweBook.Com
CHAPTER 14
Scala Tools, Libraries, and IDE Support

,QWKHSUHYLRXVFKDSWHU&KDSWHUZHORRNHGDWKRZWRGHVLJQVFDODEOHDSSOLFDWLRQV
LQ6FDOD,QWKLVFKDSWHUZHGLVFXVVWRROVDQGOLEUDULHVWKDWDUHHVVHQWLDOIRU6FDODDS
SOLFDWLRQGHYHORSHUV
:H EULHIO\ LQWURGXFHG \RX WR WKH 6FDOD FRPPDQGOLQH WRROV LQ &KDSWHU  1RZ ZH
H[SORUHWKHVHWRROVLQJUHDWHUGHWDLODQGOHDUQDERXWRWKHUWRROVWKDWDUHHVVHQWLDOIRU
WKH6FDODGHYHORSHU:H¦OOGLVFXVVODQJXDJHDZDUHSOXJLQVIRUHGLWRUVDQG,'(VWHVWLQJ
WRROVDQGYDULRXVOLEUDULHVDQGIUDPHZRUNV:HZRQ¦WFRYHUWKHVHWRSLFVLQH[KDXVWLYH
GHWDLOEXWZHZLOOWHOO\RXZKHUHWRORRNIRUPRUHLQIRUPDWLRQ

Command-Line Tools
(YHQLI\RXGRPRVWRI\RXUZRUNZLWK,'(VXQGHUVWDQGLQJKRZWKHFRPPDQGOLQH
WRROVZRUNJLYHV\RXDGGLWLRQDOIOH[LELOLW\DVZHOODVDIDOOEDFNVKRXOGWKHJUDSKLFDO
WRROVIDLO\RX,QWKLVFKDSWHUZH¦OOJLYH\RXVRPHSUDFWLFDODGYLFHIRULQWHUDFWLQJZLWK
WKHVHWRROV+RZHYHUZHZRQ¦WGHVFULEHHDFKDQGHYHU\FRPPDQGOLQHRSWLRQ)RU
WKRVHJRU\GHWDLOVZHUHFRPPHQGGRZQORDGLQJDQGFRQVXOWLQJWKHWRROGRFXPHQWDWLRQ
SDFNDJH scala-devel-docsDVGHVFULEHGLQ£)RU0RUH,QIRUPDWLRQ¤RQSDJHDQG
DOVRLQ£7KHVED]&RPPDQG/LQH7RRO¤RQSDJH
$OOWKHFRPPDQGOLQHWRROVDUHLQVWDOOHGLQWKHscala-homeELQGLUHFWRU\ VHH£,QVWDOOLQJ
6FDOD¤RQSDJH 

scalac Command-Line Tool


7KHscalacFRPPDQGFRPSLOHV6FDODVRXUFHILOHVJHQHUDWLQJ-90FODVVILOHV,QFRQWUDVW
ZLWK-DYDUHTXLUHPHQWVWKHVRXUFHILOHQDPHGRHVQ¦WKDYHWRPDWFKWKHSXEOLFFODVV
QDPHLQWKHILOH,QIDFW\RXFDQGHILQHDVPDQ\SXEOLFFODVVHVLQWKHILOHDV\RXZDQW
<RX FDQ DOVR XVH DUELWUDU\ SDFNDJH GHFODUDWLRQV ZLWKRXW SXWWLQJ WKH ILOHV LQ FRUUH
VSRQGLQJGLUHFWRULHV

343

Download at WoweBook.Com
+RZHYHU LQ RUGHU WR FRQIRUP WR -90 UHTXLUHPHQWV D VHSDUDWH FODVV ILOH ZLOO EH
JHQHUDWHGIRUHDFKW\SHZLWKDQDPHWKDWFRUUHVSRQGVWRWKHW\SH¦VQDPH VRPHWLPHV
HQFRGHGHJIRUQHVWHGW\SHGHILQLWLRQV $OVRWKHFODVVILOHVZLOOEHZULWWHQWRGLUHF
WRULHVFRUUHVSRQGLQJWRWKHSDFNDJHGHFODUDWLRQV:H¦OOVHHDQH[DPSOHRIWKHW\SHVRI
FODVVILOHVJHQHUDWHGLQWKHQH[WVHFWLRQZKHQZHGLVFXVVWKHscalaFRPPDQG
7KHscalacFRPPDQGLVMXVWDVKHOOVFULSWZUDSSHUDURXQGWKHjavaFRPPDQGSDVVLQJ
LW WKH QDPH RI WKH 6FDOD FRPSLOHU¦V Main REMHFW ,W DGGV 6FDOD -$5 ILOHV WR WKH
CLASSPATHDQGLWGHILQHVVHYHUDO6FDODUHODWHGV\VWHPSURSHUWLHV<RXLQYRNHWKHFRP
PDQGDVIROORZV
scalac [options ...] [source-files]

)RU H[DPSOH ZH XVHG WKH IROORZLQJ scalac LQYRFDWLRQ FRPPDQG LQ £$ 7DVWH RI
6FDOD¤ RQ SDJH  ZKHUH ZH FUHDWHG D VLPSOH FRPPDQGOLQH WRRO WR FRQYHUW LQSXW
VWULQJVWRXSSHUFDVH
scalac upper3.scala

7DEOHVKRZVWKHOLVWRIWKHscalacoptionsDVUHSRUWHGE\scalac -help
7DEOH7KHVFDODFFRPPDQGRSWLRQV
Option Description
-X Print a synopsis of advanced options.
-bootclasspath path Override location of bootstrap class files.
-classpath path Specify where to find user class files.
-d directory Specify where to place generated class files.
-dependencyfile file Specify the file in which dependencies are tracked. (version 2.8)
-deprecation Output source locations where deprecated APIs are used.
-encoding encoding Specify character encoding used by source files.
-explaintypes Explain type errors in more detail.
-extdirs dirs Override location of installed compiler extensions.
-g:level Specify level of generated debugging info: none, source, line, vars, notailcalls.
-help Print a synopsis of standard options.
-make:strategy Specify recompilation detection strategy: all, changed, immediate, transitive.
(version 2.8)
-nowarn Generate no warnings.
-optimise Generate faster byte code by applying optimizations to the program.
-print Print program with all Scala-specific features removed.
-sourcepath path Specify where to find input source files.
-target:target Specify for which target JVM object files should be built: jvm-1.5, jvm-1.4, msil.
-unchecked Enable detailed unchecked warnings.
-uniqid Print identifiers with unique names for debugging.

344 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
Option Description
-verbose Output messages about what the compiler is doing.
-version Print product version and exit.
@ file A text file containing compiler arguments (options and source files).

:HUHFRPPHQGURXWLQHXVHRIWKH-deprecationDQG-uncheckedRSWLRQV
7KH\KHOSSUHYHQWVRPHEXJVDQGHQFRXUDJH\RXWRHOLPLQDWHXVHRI
REVROHWHOLEUDULHV

7KHDGYDQFHG-XRSWLRQVFRQWUROYHUERVHRXWSXWILQHWXQHWKHFRPSLOHUEHKDYLRULQ
FOXGLQJXVHRIH[SHULPHQWDOH[WHQVLRQVDQGSOXJLQVHWF:H¦OOGLVFXVVWKH -Xscript
RSWLRQZKHQZHGLVFXVVWKHscalaFRPPDQGLQWKHQH[WVHFWLRQ
$IHZRWKHUDGYDQFHGRSWLRQV-XfutureDQG-XcheckinitDUHXVHIXOIRUWKHvalRYHUULGH
LVVXHGHVFULEHGLQ£2YHUULGLQJ$EVWUDFWDQG&RQFUHWH)LHOGVLQ7UDLWV¤RQSDJHWKDW
DIIHFWV6FDODYHUVLRQ;6LPLODUO\WKH-XexperimentalRSWLRQHQDEOHVH[SHULPHQWDO
FKDQJHVDQGLVVXHVZDUQLQJVIRUSRWHQWLDOO\ULVN\EHKDYLRUFKDQJHV6HH£2YHUULGLQJ
$EVWUDFWDQG&RQFUHWH)LHOGVLQ7UDLWV¤RQSDJHIRUGHWDLOV
$QLPSRUWDQWIHDWXUHRIscalacLVLWVSOXJLQDUFKLWHFWXUHZKLFKKDVEHHQVLJQLILFDQWO\
HQKDQFHGLQYHUVLRQ&RPSLOHUSOXJLQVFDQEHLQVHUWHGLQDOOSKDVHVRIWKHFRPSL
ODWLRQHQDEOLQJFRGHWUDQVIRUPDWLRQVDQDO\VLVHWF)RUH[DPSOHYHUVLRQZLOOLQ
FOXGHDFRQWLQXDWLRQVSOXJLQWKDWGHYHORSHUVFDQXVHWRJHQHUDWHE\WHFRGHWKDWXVHVD
FRQWLQXDWLRQSDVVLQJVW\OH &36 UDWKHUWKDQDVWDFNEDVHGVW\OH2WKHUSOXJLQVWKDW
DUHXQGHUGHYHORSPHQWLQFOXGHDQ£HIIHFWV¤DQDO\]HUXVHIXOIRUGHWHUPLQLQJZKHWKHU
IXQFWLRQVDUHWUXO\VLGHHIIHFWIUHHZKHWKHURUQRWYDULDEOHVDUHPRGLILHGHWF)LQDOO\
WKHSUHOLPLQDU\sxrGRFXPHQWDWLRQWRRO VHH>6;5@ XVHVDFRPSLOHUSOXJLQWRJHQHUDWH
K\SHUOLQNHGGRFXPHQWDWLRQRI6FDODFRGH
<RXFDQUHDGPRUHLQIRUPDWLRQDERXW scalacLQWKHGHYHORSHUWRROVGRFXPHQWDWLRQ
WKDW\RXFDQLQVWDOOZLWKWKHsbazFRPPDQGGLVFXVVHGODWHULQ£7KHVED]&RPPDQG
/LQH7RRO¤RQSDJH,QSDUWLFXODU7DEOHVKRZVDQH[DPSOH sbazFRPPDQG
WKDWLQVWDOOVWKHscala-devel-docsGRFXPHQWDWLRQ

6FDODYHUVLRQFRPSLOHGE\WHFRGHZLOOQRWEHIXOO\FRPSDWLEOHZLWK
YHUVLRQE\WHFRGH6RXUFHFRPSDWLELOLW\ZLOOEHSUHVHUYHGLQPRVW
FDVHV ,I \RX KDYH \RXU RZQ FROOHFWLRQV LPSOHPHQWDWLRQV WKH\ PD\
UHTXLUHFKDQJHV

The scala Command-Line Tool


7KHscalaFRPPDQGLVDOVRDVKHOOVFULSWZUDSSHUDURXQGWKHjavaFRPPDQG,WDGGV
6FDOD-$5ILOHVWRWKHCLASSPATHDQGLWGHILQHVVHYHUDO6FDODUHODWHGV\VWHPSURSHUWLHV
<RXLQYRNHWKHFRPPDQGDVIROORZV

Command-Line Tools | 345

Download at WoweBook.Com
scala [options ...] [script-or-object] [arguments]

)RUH[DPSOHDIWHUFRPSLOLQJRXUXSSHUVFDODILOHLQ£$7DVWHRI6FDOD¤RQSDJH
ZKLFKZHUHYLVLWHGLQWKHSUHYLRXVGLVFXVVLRQRIscalacZHFDQH[HFXWHWKH£DSSOLFD
WLRQ¤DVIROORZV
scala -cp . Upper Hello World!

7KH-cp .RSWLRQDGGVWKHFXUUHQWZRUNLQJGLUHFWRU\WRWKHFODVVSDWKUpperLVWKHFODVV
QDPHZLWKD mainPHWKRGWRUXQ Hello WorldDUHDUJXPHQWVSDVVHGWR Upper7KLV
FRPPDQGSURGXFHVWKHIROORZLQJRXWSXW
HELLO WORLD!

7KHFRPPDQGGHFLGHVZKDWWRGREDVHGRQWKHscript-or-objectVSHFLILHG,I\RXGRQ¦W
VSHFLI\DVFULSWRUREMHFWscalaUXQVDVDQLQWHUDFWLYHLQWHUSUHWHU<RXW\SHLQFRGHWKDW
LVHYDOXDWHGRQWKHIO\DVHWXSVRPHWLPHVUHIHUUHGWRDVD5(3/ 5HDG(YDOXDWH3ULQW
/RRS  7KHUH DUH D IHZ VSHFLDO FRPPDQGV DYDLODEOH LQ WKH LQWHUDFWLYH PRGH
7\SH:helpWRVHHDOLVWRIWKHP

7KH YHUVLRQ  5(3/ DGGV PDQ\ HQKDQFHPHQWV LQFOXGLQJ FRGH


FRPSOHWLRQ

2XU UpperH[DPSOHGHPRQVWUDWHVWKHFDVHZKHUH\RXVSHFLI\DIXOO\TXDOLILHG object


QDPH RU-DYDclassQDPH ,QWKLVFDVHscalaEHKDYHVMXVWOLNHWKHjavaFRPPDQGLW
VHDUFKHVWKHCLASSPATHIRUWKHFRUUHVSRQGLQJFRGH,WZLOOH[SHFWWRILQGDmainPHWKRG
LQWKHW\SH5HFDOOWKDWIRU6FDODW\SHV\RXKDYHWRGHILQHmainPHWKRGVLQobjects$Q\
argumentsDUHSDVVHGDVDUJXPHQWVWRWKHmainPHWKRG
,I\RXVSHFLI\D6FDODVRXUFHILOHIRUscript-or-objectscalaLQWHUSUHWVWKHILOHDVDVFULSW
LHFRPSLOHVDQGUXQVLW 0DQ\RIWKHH[DPSOHVLQWKHERRNDUHLQYRNHGWKLVZD\
$Q\ argumentsDUHPDGHDYDLODEOHWRWKHVFULSWLQWKH argsDUUD\+HUHLVDQH[DPSOH
VFULSWWKDWLPSOHPHQWVWKHVDPH£XSSHU¤IHDWXUH
// code-examples/ToolsLibs/upper-script.scala

args.map(_.toUpperCase()).foreach(printf("%s ",_))
println("")

,IZHUXQWKLVVFULSWZLWKWKHIROORZLQJFRPPDQGscala upper.scala Hello WorldZH


JHWWKHVDPHRXWSXWZHJRWEHIRUHHELLO WORLD
)LQDOO\LI\RXLQYRNHscalaZLWKRXWDVFULSWILOHRUREMHFWQDPHDUJXPHQWscalaUXQV
LQLQWHUSUHWHGPRGH+HUHLVDQH[DPSOHLQWHUDFWLYHVHVVLRQ
$ scala
Welcome to Scala version 2.8.0.final (Java ...).
Type in expressions to have them evaluated.
Type :help for more information.

346 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
scala> "Programming Scala" foreach { c => println(c) }
P
r
o
g
...

7KHscalaFRPPDQGDFFHSWVDOOWKHRSWLRQVWKDWscalacDFFHSWV VHH7DEOH SOXV


WKHRSWLRQVOLVWHGLQ7DEOH
7DEOH7KHVFDODFRPPDQGRSWLRQV LQDGGLWLRQWRWKHVFDODFRSWLRQV
Option Description
-howtorun script Explicitly interpret script-or-object as a script file.
-howtorun object Explicitly interpret script-or-object as a compiled object.
-howtorun guess Guess what script-or-object is (default).
-i file Preload file. It is only meaningful for interactive shells.
-e argument Parse argument as Scala code.
-savecompiled Save the compiled script for future use.
-nocompdaemon Don’t use fsc, the offline compiler. (See “The fsc Command-Line Tool” on page 353.)
-Dproperty=value Set a Java system property to value.

8VHWKH-ifileRSWLRQLQWKHLQWHUDFWLYHPRGHZKHQ\RXZDQWWRSUHORDGDILOHEHIRUH
W\SLQJ FRPPDQGV 2QFH LQ WKH VKHOO \RX FDQ DOVR ORDG D ILOH XVLQJ WKH FRP
PDQG :load filename7DEOHOLVWVWKHVSHFLDO :XFRPPDQGVDYDLODEOHZLWKLQWKH
LQWHUDFWLYHPRGH
7DEOH&RPPDQGVDYDLODEOHZLWKLQWKHVFDODLQWHUDFWLYHPRGH
Option Description
:help Prints a help message about these commands.
:load Followed by a file name, loads a Scala file.
:replay Resets execution and replays all previous commands.
:quit Exits the interpreter.
:power Enables power user mode. (version 2.8)

7KHQHZ£SRZHUXVHUPRGH¤DGGVDGGLWLRQDOFRPPDQGVIRUYLHZLQJLQPHPRU\GDWD
VXFK DV WKH DEVWUDFW V\QWD[ WUHH DQG LQWHUSUHWHU SURSHUWLHV DQG IRU GRLQJ RWKHU
RSHUDWLRQV
)RUEDWFKPRGHLQYRFDWLRQXVHWKH-eargumentRSWLRQWRVSHFLI\6FDODFRGHWRLQWHUSUHW
,I\RXDUHXVLQJFRPPDQGVKHOOVWKDWVXSSRUW,2UHGLUHFWLRQ HJWKH%RXUQHVKHOO
WKH&VKHOORUWKHLUGHVFHQGDQWV DQG\RXQHHGWREXLOGXSOLQHVRIFRGHG\QDPLFDOO\

Command-Line Tools | 347

Download at WoweBook.Com
\RXFDQDOVRSLSHWKHFRGHLQWRscalaDVVKRZQLQWKHIROORZLQJVRPHZKDWFRQWULYHG
EDVKVFULSWH[DPSOH
#!/usr/bin/env bash
# code-examples/ToolsLibs/pipe-example.sh

h=Hello
w=World
function commands {
cat <<-EOF
println("$h")
println("$w")
EOF
}

commands | scala

,QYRNLQJVFULSWVZLWKscalaLVWHGLRXVZKHQ\RXXVHWKHVHVFULSWVIUHTXHQWO\2Q:LQ
GRZVDQG8QL[OLNHV\VWHPV\RXFDQFUHDWHVWDQGDORQH6FDODVFULSWVWKDWGRQ¦WUHTXLUH
\RXWRXVHWKHscalascript-file-nameLQYRFDWLRQ
)RU8QL[OLNHV\VWHPVWKHIROORZLQJH[DPSOHGHPRQVWUDWHVKRZWRPDNHDQH[HFXWDEOH
VFULSW5HPHPEHUWKDW\RXKDYHWRPDNHWKHSHUPLVVLRQVH[HFXWDEOHHJ chmod +x
secho
#!/bin/sh
exec scala "$0" "$@"
!#
print("You entered: ")
argv.toList foreach { s => format("%s ", s) }
println

+HUHLVKRZ\RXPLJKWXVHLW
$ secho Hello World
You entered: Hello World

6LPLODUO\KHUHLVDQH[DPSOH:LQGRZV.batFRPPDQG
::#!
@echo off
call scala %0 %*
goto :eof
::!#
print("You entered: ")
argv.toList foreach { s => format("%s ", s) }
println

6HHWKHscalaPDQSDJHLQWKHGHYHORSHUGRFXPHQWDWLRQSDFNDJHscala-devel-docsWR
ILQGRXWPRUHDERXWDOOWKHFRPPDQGOLQHRSWLRQVIRUscala

Limitations of scala versus scalac


7KHUHDUHVRPHOLPLWDWLRQVZKHQUXQQLQJDVRXUFHILOHZLWK scalaYHUVXVFRPSLOLQJLW
ZLWKscalac

348 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
$Q\VFULSWVH[HFXWHGZLWKscalaDUHZUDSSHGLQDQDQRQ\PRXVobjectWKDWORRNVPRUH
RUOHVVOLNHWKHIROORZLQJH[DPSOH
// code-examples/ToolsLibs/script-wrapper.scala

object Script {
def main(args: Array[String]): Unit = {
new AnyRef {
// Your script code is inserted here.
}
}
}

$VRIWKLVZULWLQJ6FDODobjectsFDQQRWHPEHGSDFNDJHGHFODUDWLRQVDQGDVVXFK\RX
FDQ¦WGHFODUHSDFNDJHVLQVFULSWV7KLVLVZK\WKHH[DPSOHVLQWKLVERRNWKDWGHFODUH
SDFNDJHVPXVWEHFRPSLOHGDQGH[HFXWHGVHSDUDWHO\VXFKDVWKLVH[DPSOHIURP&KDS
WHU
// code-examples/TypeLessDoMore/package-example1.scala

package com.example.mypkg

class MyClass {
// ...
}

&RQYHUVHO\WKHUHDUHYDOLGVFULSWVWKDWFDQ¦WEHFRPSLOHGZLWKscalacXQOHVVDVSHFLDO
-XRSWLRQLVXVHG)RUH[DPSOHIXQFWLRQGHILQLWLRQVDQGIXQFWLRQLQYRFDWLRQVRXWVLGH
RIW\SHVDUHQRWDOORZHG7KHIROORZLQJH[DPSOHUXQVILQHZLWKscala
// code-examples/ToolsLibs/example-script.scala

case class Message(name: String)

def printMessage(msg: Message) = {


println(msg)
}

printMessage(new Message(
"Must compile this script with scalac -Xscript <name>!"))

5XQQLQJWKLVVFULSWZLWKscalaSURGXFHVWKHIROORZLQJH[SHFWHGRXWSXW
Message(Must compile this script with scalac -Xscript <name>!)

+RZHYHULI\RXWU\WRFRPSLOHWKHVFULSWZLWK scalac ZLWKRXWWKH -XscriptRSWLRQ 


\RXJHWWKHIROORZLQJHUURUV
example-script.scala:3: error: expected class or object definition
def printMessage(msg: Message) = {
^
example-script.scala:7: error: expected class or object definition
printMessage(new Message("Must compile this script with scalac -Xscript <name>!"))
^
two errors found

Command-Line Tools | 349

Download at WoweBook.Com
7KHVFULSWLWVHOIGHVFULEHVWKHVROXWLRQWRFRPSLOHWKLVVFULSWZLWKscalac\RXPXVWDGG
WKHRSWLRQ-XscriptnameZKHUHnameLVWKHQDPH\RXZDQWWRJLYHWKHFRPSLOHGFODVV
ILOH)RUH[DPSOHXVLQJ MessagePrinterIRU nameZLOOUHVXOWLQWKHFUHDWLRQRIVHYHUDO
FODVVILOHVZLWKWKHQDPHSUHIL[MessagePrinter
scalac -Xscript MessagePrinter example-script.scala

<RXFDQQRZUXQWKHFRPSLOHGFRGHZLWKWKHFRPPDQG
scala -classpath . MessagePrinter

7KHFXUUHQWGLUHFWRU\ZLOOFRQWDLQWKHIROORZLQJFODVVILOHV
MessagePrinter$$anon$1$Message$.class
MessagePrinter$$anon$1$Message.class
MessagePrinter$$anon$1.class
MessagePrinter$.class
MessagePrinter.class

:KDWDUHDOOWKRVHILOHV"MessagePrinterDQGMessagePrinter$DUHZUDSSHUVJHQHUDWHG
E\scalacWRSURYLGHWKHHQWU\SRLQWIRUWKHVFULSWDVDQ£DSSOLFDWLRQ¤5HFDOOWKDWZH
VSHFLILHG MessagePrinterDVWKH nameDUJXPHQWIRU -Xscript MessagePrinterKDVWKH
static mainPHWKRGZHQHHG
MessagePrinter$$anon$1 LV D JHQHUDWHG FODVV WKDW ZUDSV WKH ZKROH VFULSW 7KH
printMessage PHWKRG LQ WKH VFULSW LV D PHWKRG LQ WKLV FODVV MessagePrinter$$anon
$1$MessageDQGMessagePrinter$$anon$1$Message$DUHWKHMessageFODVVDQGFRPSDQLRQ
REMHFWUHVSHFWLYHO\WKDWDUHGHFODUHGLQWKHVFULSW7KH\DUHQHVWHGLQVLGHWKHJHQHUDWHG
FODVVMessagePrinter$$anon$1IRUWKHZKROHVFULSW,I\RXZDQWWRVHHZKDW¦VLQVLGHWKHVH
FODVVILOHVXVHRQHRIWKHGHFRPSLOHUVZKLFKZHGHVFULEHQH[W

The scalap, javap, and jad Command-Line Tools


:KHQ\RXDUHOHDUQLQJ6FDODDQG\RXZDQWWRXQGHUVWDQGKRZ6FDODFRQVWUXFWVDUH
PDSSHGWRWKHUXQWLPHWKHUHDUHVHYHUDOGHFRPSLOHUVWKDWDUHYHU\XVHIXO7KH\DUH
HVSHFLDOO\XVHIXOZKHQ\RXQHHGWRLQYRNH6FDODFRGHIURP-DYDDQG\RXZDQWWRNQRZ
KRZ6FDODQDPHVDUHPDQJOHGLQWR-90FRPSDWLEOHQDPHVRU\RXZDQWWRXQGHUVWDQG
KRZWKHVFDODFRPSLOHUWUDQVODWHV6FDODIHDWXUHVLQWRYDOLGE\WHFRGH
/HW¦VGLVFXVVWKUHHGHFRPSLOHUVDQGWKHEHQHILWVWKH\RIIHU6LQFHWKHFODVVILOHVJHQHUDWHG
E\scalacFRQWDLQYDOLG-90E\WHFRGHV\RXFDQXVH-DYDGHFRPSLOHUVWRROV
‡ scalapLVLQFOXGHGZLWKWKH6FDODGLVWULEXWLRQ,WRXWSXWVGHFODUDWLRQVDVWKH\ZRXOG
DSSHDULQ6FDODVRXUFHFRGH
‡ javapLVLQFOXGHGZLWKWKH-'.,WRXWSXWVGHFODUDWLRQVDVWKH\ZRXOGDSSHDULQ
-DYDVRXUFHFRGH7KHUHIRUHUXQQLQJjavapRQ6FDODJHQHUDWHGFODVVILOHVLVDJRRG
ZD\WRVHHKRZ6FDODGHILQLWLRQVDUHPDSSHGWRYDOLGE\WHFRGH

350 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
‡ jadLVDQRSHQVRXUFHFRPPDQGOLQHWRRO VHH>-$'@ ,WDWWHPSWVWRUHFRQVWUXFWDQ
HQWLUH-DYDVRXUFHILOHIURPWKHFODVVILOHLQFOXGLQJPHWKRGGHILQLWLRQVDVZHOODV
WKHGHFODUDWLRQV
0HVVDJH3ULQWHUFODVVLVRQHRIWKHFODVVILOHVJHQHUDWHGIURPWKHH[DPSOHVFULSWLQWKH
SUHYLRXVVHFWLRQ/HW¦VUXQscalap -classpath . MessagePrinter:HJHWWKHIROORZLQJ
RXWSXW
package MessagePrinter;
final class MessagePrinter extends scala.AnyRef {
}
object MessagePrinter {
def main(scala.Array[java.lang.String]): scala.Unit;
def $tag(): scala.Int;
throws java.rmi.RemoteException
}

1RWH WKDW WKH ILUVW PHWKRG LQVLGH object MessagePrinter LV WKH main PHWKRG 7KH
$tagPHWKRGLVSDUWRI6FDOD¦VLQWHUQDOLPSOHPHQWDWLRQ,WLVDQDEVWUDFWPHWKRGGHILQHG
E\ ScalaObject7KHFRPSLOHUDXWRPDWLFDOO\JHQHUDWHVLPSOHPHQWDWLRQVIRUFRQFUHWH
W\SHV7KH$tagPHWKRGZDVRULJLQDOO\LQWURGXFHGWRRSWLPL]HSDWWHUQPDWFKLQJEXWLW
LVQRZGHSUHFDWHGDQGLWPD\EHUHPRYHGLQDIRUWKFRPLQJUHOHDVHRI6FDOD
/HW¦V FRPSDUH WKH scalap RXWSXW WR ZKDW ZH JHW ZKHQ ZH UXQ javap -classpath .
MessagePrinter
Compiled from "(virtual file)"
public final class MessagePrinter extends java.lang.Object{
public static final void main(java.lang.String[]);
public static final int $tag() throws java.rmi.RemoteException;
}

1RZZHVHHWKHGHFODUDWLRQRImainDVZHZRXOGW\SLFDOO\VHHLWLQD-DYDVRXUFHILOH
)LQDOO\WRXVHjad\RXVLPSO\JLYHLWWKHILOHQDPHRIWKHFODVVILOH,WJHQHUDWHVDFRU
UHVSRQGLQJRXWSXWILOHZLWKWKHMDGH[WHQVLRQ,I\RXUXQ jad MessagePrinter.class
\RXJHWDORQJILOHQDPHG0HVVDJH3ULQWHUMDG<RXZLOODOVRJHWVHYHUDOZDUQLQJVWKDW
jadFRXOGQRWIXOO\GHFRPSLOHVRPHPHWKRGV:HZRQ¦WUHSURGXFHWKHRXWSXWKHUH
EXWWKHMDGILOHZLOOSULQWQRUPDO-DYDVWDWHPHQWVLQWHUVSHUVHGZLWKVHYHUDOVHFWLRQVRI
-90E\WHFRGHLQVWUXFWLRQVZKHUHLWFRXOGQRWGHFRPSLOHWKHE\WHFRGH
$OOWKHVHWRROVKDYHFRPPDQGOLQHKHOS
‡ scalap -help
‡ javap -help
‡ jad --help
7KH6FDODGHYHORSHUGRFXPHQWDWLRQFRQWDLQVGRFXPHQWDWLRQIRUscalap6LPLODUGRF
XPHQWDWLRQFRPHVZLWKWKH-'.IRUjavap7KHjadGLVWULEXWLRQLQFOXGHVD5($'0(
ILOHZLWKGRFXPHQWDWLRQ7KH0DFDQG/LQX[GLVWULEXWLRQVDOVRLQFOXGHDPDQSDJH

Command-Line Tools | 351

Download at WoweBook.Com
)LQDOO\DVDQH[HUFLVHFRPSLOHWKHIROORZLQJYHU\VLPSOH ComplexFODVVUHSUHVHQWLQJ
FRPSOH[QXPEHUV7KHQUXQscalapjavapDQGjadRQWKHUHVXOWLQJFODVVILOHV
// code-examples/ToolsLibs/complex.scala

case class Complex(real: Double, imaginary: Double) {


def +(that: Complex) =
new Complex(real + that.real, imaginary + that.imaginary)
def -(that: Complex) =
new Complex(real - that.real, imaginary - that.imaginary)
}

+RZDUHWKH+DQG-PHWKRGVHQFRGHG":KDWDUHWKHQDPHVRIWKHUHDGHUPHWKRGVIRU
WKHrealDQGimaginaryILHOGV":KDW-DYDW\SHVDUHXVHGIRUWKHILHOGV"

The scaladoc Command-Line Tool


7KHscaladocFRPPDQGLVDQDORJRXVWRjavadoc,WLVXVHGWRJHQHUDWHGRFXPHQWDWLRQ
IURP 6FDOD VRXUFH ILOHV FDOOHG 6FDODGRFV 7KH scaladoc SDUVHU VXSSRUWV WKH VDPH @
DQQRWDWLRQVWKDWjavadocVXSSRUWVVXFKDV@author@paramHWF
,I\RXXVHscaladocIRU\RXUGRFXPHQWDWLRQ\RXPLJKWZDQWWRLQYHVWLJDWHvscaladoc
DQLPSURYHGscaladocWRROWKDWLVDYDLODEOHDWKWWSFRGHJRRJOHFRPSYVFDODGRF<RX
FDQDOVRILQGGRFXPHQWDWLRQRQvscaladocDW>6FDOD7RROV@

The sbaz Command-Line Tool


7KH6FDOD%D]DDU6\VWHP sbaz LVDSDFNDJLQJV\VWHPWKDWKHOSVDXWRPDWHPDLQWHQDQFH
RID6FDODLQVWDOODWLRQ,WLVDQDORJRXVWRWKHJHPSDFNDJLQJV\VWHPIRU5XE\&3$1IRU
3HUOHWF
7KHUHLVDQLFHVXPPDU\RIKRZWRXVHsbazRQWKHVFDODODQJRUJZHEVLWH$OOFRPPDQG
OLQHRSWLRQVDUHGHVFULEHGLQWKHGHYHORSHUGRFXPHQWDWLRQ7DEOHVXPPDUL]HVWKH
PRVWXVHIXORSWLRQV
7DEOH7KHPRVWXVHIXOVED]FRPPDQGRSWLRQV
Command Description
sbaz showuniverse Show the current “universe” (remote repository). Defaults to http://scala-we
bapps.epfl.ch/sbaz/scala-dev.
sbaz setuniverse univ Points to a new “universe” univ.
sbaz installed What’s already installed locally?
sbaz available What goodness awaits on the Interwebs?
sbaz install scala-devel-docs Install the invaluable scala-devel-docs package (for example).
sbaz upgrade Upgrade all installed packages to the latest and greatest.

1RWHWKDWDUHPRWHUHSRVLWRU\XVHGE\sbazLVFDOOHGD£XQLYHUVH¤

352 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
The fsc Command-Line Tool
7KHIDVW RIIOLQH VFDODFRPSLOHUUXQVDVDGDHPRQSURFHVVWRHQDEOHIDVWHULQYRFDWLRQV
RIWKHFRPSLOHUPRVWO\E\HOLPLQDWLQJWKHVWDUWXSRYHUKHDG,WLVSDUWLFXODUO\XVHIXO
ZKHQUXQQLQJVFULSWVUHSHDWHGO\ IRUH[DPSOHZKHQUHUXQQLQJDWHVWVXLWHXQWLODEXJ
FDQEHUHSURGXFHG ,QIDFWfscLVLQYRNHGDXWRPDWLFDOO\E\WKHscalaFRPPDQG<RX
FDQDOVRLQYRNHLWGLUHFWO\

Build Tools
6FDODSOXJLQVKDYHEHHQLPSOHPHQWHGIRUVHYHUDOFRPPRQO\XVHGEXLOGWRROVLQFOXGLQJ
$QW0DYHQDQG%XLOGU7KHUHDUHDOVRVHYHUDOEXLOGWRROVZULWWHQLQ6FDODDQGDLPHG
VSHFLILFDOO\DW6FDODGHYHORSPHQW3HUKDSVWKHEHVWNQRZQH[DPSOHRIWKHVHWRROVLV
6%7 VLPSOHEXLOGWRRO¢VHH>6%7@ 
7KHVHSOXJLQVDQGWRROVDUHGRFXPHQWHGYHU\ZHOORQWKHLUUHVSHFWLYHZHEVLWHVVRZH
UHIHU\RXWRWKRVHVLWHVIRUGHWDLOV
7KH6FDODGLVWULEXWLRQLQFOXGHV$QWWDVNVIRUscalacfscDQGscaladoc7KH\DUHXVHG
YHU\PXFKOLNHWKHFRUUHVSRQGLQJ-DYD$QWWDVNV7KH\DUHGHVFULEHGDWKWWSVFDODODQJ
RUJQRGH
$ 6FDOD 0DYHQ SOXJLQ LV DYDLODEOH DW KWWSVFDODWRROVRUJPYQVLWHVPDYHQVFDODSOX
JLQ,WGRHVQRWUHTXLUH6FDODWREHLQVWDOOHGDVLWZLOOGRZQORDG6FDODIRU\RX6HYHUDO
WKLUGSDUW\6FDODSURMHFWVVXFKDV/LIW VHH£/LIW¤RQSDJH XVH0DYHQ
%XLOGULVDQ$SDFKHSURMHFWDYDLODEOHDWKWWSEXLOGUDSDFKHRUJ,WLVDLPHGDW-90
DSSOLFDWLRQVZULWWHQLQDQ\ODQJXDJHZLWKEXLOWLQVXSSRUWIRU6FDODDQG*URRY\DVZHOO
DV-DYD,WLVFRPSDWLEOHZLWK0DYHQUHSRVLWRULHVDQGSURMHFWOD\RXWV6LQFHEXLOGVFULSWV
DUHZULWWHQLQ5XE\WKH\WHQGWREHPXFKPRUHVXFFLQFWWKDQFRUUHVSRQGLQJ0DYHQ
ILOHV%XLOGULVDOVRXVHIXOIRUWHVWLQJ-90DSSOLFDWLRQVZLWK5XE\WHVWLQJWRROVOLNH
56SHFDQG&XFXPEHULI\RXXVH-5XE\WRUXQ\RXUEXLOGV
7KH 6FDODRULHQWHG 6%7 DYDLODEOH DW KWWSFRGHJRRJOHFRPSVLPSOHEXLOGWRRO KDV
VRPHVLPLODULWLHVWR%XLOGU,WLVDOVRFRPSDWLEOHZLWK0DYHQEXWLWXVHV6FDODDVWKH
ODQJXDJHIRUZULWLQJEXLOGVFULSWV,WDOVRKDVEXLOWLQVXSSRUWIRUJHQHUDWLQJ6FDODGRFV
DQGIRUWHVWLQJZLWK6FDOD7HVW6SHFVDQG6FDOD&KHFN

Integration with IDEs


,I\RXFRPHIURPD-DYDEDFNJURXQG\RXDUHSUREDEO\DOLWWOHELWVSRLOHGE\WKHULFK
IHDWXUHVRIWRGD\¦V-DYD,'(V6FDOD,'(VXSSRUWLVQRW\HWDVJRRGEXWLWLVHYROYLQJ
UDSLGO\LQ(FOLSVH,QWHOOL-,'($DQG1HW%HDQV$WWKHWLPHRIWKLVZULWLQJDOOWKH6FDOD
SOXJLQV IRU WKHVH ,'(V VXSSRUW V\QWD[ KLJKOLJKWLQJ SURMHFW PDQDJHPHQW OLPLWHG
VXSSRUWIRUDXWRPDWHGUHIDFWRULQJVHWF:KLOHHDFKRIWKHSOXJLQVKDVSDUWLFXODUDG

Integration with IDEs | 353

Download at WoweBook.Com
YDQWDJHVRYHUWKHRWKHUVWKH\DUHDOOFORVHHQRXJKLQIXQFWLRQDOLW\WKDW\RXZLOOSURE
DEO\ILQGLWDFFHSWDEOHWRDGRSWWKHSOXJLQIRUWKH,'(WKDW\RXDOUHDG\SUHIHU
7KLVVHFWLRQGHVFULEHVKRZWRXVHWKH6FDODVXSSRUWDYDLODEOHLQ(FOLSVH,QWHOOL-,'($
DQG1HW%HDQV:HDVVXPH\RXDOUHDG\NQRZKRZWRXVHHDFK,'(IRUGHYHORSPHQWLQ
RWKHUODQJXDJHVOLNH-DYD

Eclipse
)RUGHWDLOVRQWKH(FOLSVH6FDODSOXJLQVWDUWDWWKLVZHESDJHKWWSZZZVFDODODQJ
RUJQRGH,I\RXDUHLQWHUHVWHGLQFRQWULEXWLQJWRWKHGHYHORSPHQWRIWKHSOXJLQVHH
WKLVZHESDJHKWWSODPSVYQHSIOFKWUDFVFDODZLNL(FOLSVH3OXJLQ

Installing the Scala plugin


7KHSOXJLQUHTXLUHV-'.RUKLJKHU -'.LVUHFRPPHQGHG DQG(FOLSVHRUKLJKHU
(FOLSVHLVUHFRPPHQGHG 7KHSOXJLQLQVWDOOVWKH6FDOD6'.LWVHOI7RLQVWDOOWKH
SOXJLQLQYRNHWKH£6RIWZDUH8SGDWHV¤FRPPDQGLQWKH+HOSPHQX
&OLFNWKH$YDLODEOH6RIWZDUHWDEDQGFOLFNWKH£$GG6LWHš¤EXWWRQRQWKHULJKWKDQG
VLGH<RXZLOOVHHWKHGLDORJVKRZQLQ)LJXUH

)LJXUH7KH$GG6LWH(FOLSVHGLDORJ

354 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
(QWHUWKH85/WKDWLVVKRZQLQWKHILJXUHKWWSZZZVFDODODQJRUJVFDODHFOLSVHSOX
JLQ6RPHSHRSOHSUHIHUWRZRUNZLWKWKHQLJKWO\UHOHDVHVKWWSZZZVFDODODQJRUJ
VFDODHFOLSVHSOXJLQQLJKWO\EXW\RXVKRXOGEHDZDUHWKDWWKHUHLVQRJXDUDQWHHWKH\
ZLOOZRUN
6HOHFWWKHFKHFNER[QH[WWRWKHQHZO\DGGHGXSGDWHVLWHDQGFOLFNWKH,QVWDOOEXWWRQ
DVLQGLFDWHGLQ)LJXUH'RQ¦WFOLFNWKH£GHIDXOW¤&ORVHEXWWRQ

)LJXUH7KH6RIWZDUH8SGDWHVDQG$GGRQVGLDORJ

,WLVHDV\WREHFRQIXVHGE\WKHSRRUXVDELOLW\RIWKH6RIWZDUH8SGDWHV
GLDORJ

$IWHUILQGLQJWKHSOXJLQRQWKHXSGDWHVLWHDQ,QVWDOOGLDORJLVSUHVHQWHG&OLFNWKURXJK
WKHVHTXHQFHRIVFUHHQVWRFRPSOHWHWKHLQVWDOODWLRQ<RXZLOOEHDVNHGWRUHVWDUW(FOLSVH
ZKHQWKHLQVWDOODWLRQFRPSOHWHV

Developing Scala applications


2QFH WKH SOXJLQ LV LQVWDOOHG \RX FDQ FUHDWH 6FDOD SURMHFWV XVLQJ WKH )LOH z 1HZ z
2WKHUšPHQXLWHP<RXZLOOILQGD6FDOD:L]DUGVIROGHUWKDWFRQWDLQVDZL]DUGFDOOHG
6FDOD3URMHFW7KLVZL]DUGZRUNVMXVWOLNHWKHIDPLOLDU-DYD3URMHFW:L]DUG
<RXFDQZRUNZLWK\RXU6FDODSURMHFWXVLQJPRVWRIWKHVDPHFRPPDQGV\RXZRXOG
XVHZLWKDW\SLFDO-DYDSURMHFW)RUH[DPSOH\RXFDQFUHDWHDQHZ6FDODtraitclass
RUobjectXVLQJWKHFRQWH[WPHQX
7KH(FOLSVH6FDODSOXJLQVWLOOKDVVRPHURXJKHGJHVEXW6FDODGHYHORSHUVXVLQJ(FOLSVH
VKRXOGILQGLWDFFHSWDEOHIRUWKHLUGDLO\QHHGV

Integration with IDEs | 355

Download at WoweBook.Com
IntelliJ
7KH,QWHOOL-,'($WHDPSURYLGHVDEHWDTXDOLW\6FDODSOXJLQ6WDUWKHUHIRUGHWDLOVKWWS
ZZZMHWEUDLQVQHWFRQIOXHQFHGLVSOD\6&$6FDOD3OXJLQIRU,QWHOOL-,'($

Installing the Scala plugins


7RXVHWKHSOXJLQ\RXPXVWXVH,QWHOOL-;RUODWHU&RQVLGHUXVLQJWKHPRVWUHFHQW
£($3¤EXLOGIRUWKHODWHVWIHDWXUHXSGDWHV
7RLQVWDOOWKH6FDODSOXJLQVWDUW,'($2SHQWKH6HWWLQJVSDQHOHJXVLQJWKH)LOHz
6HWWLQJVPHQXLWHP2QWKHOHIWKDQGVLGHVFUROOGRZQWRDQGFOLFNWKH3OXJLQVLWHPDV
VKRZQLQ)LJXUH

)LJXUH,QWHOOL-,'($6HWWLQJVz3OXJLQV

6HOHFWWKH$YDLODEOHWDERQWKHULJKWKDQGVLGH6FUROOGRZQWRWKH6FDODSOXJLQDVVKRZQ
LQ)LJXUH

)LJXUH$YDLODEOH,QWHOOL-,'($6FDODSOXJLQV

356 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
5LJKWFOLFNWKH6FDODSOXJLQQDPHDQGVHOHFW£'RZQORDGDQG,QVWDOO¤IURPWKHPHQX
5HSHDWIRUWKH6FDOD$SSOLFDWLRQSOXJLQ<RXZLOOKDYHWRUHVWDUW,'($IRUWKHSOXJLQV
WREHHQDEOHG
$IWHU,'($UHVWDUWVFRQILUPWKDWWKHWZRSOXJLQVZHUHLQVWDOOHGFRUUHFWO\E\UHRSHQLQJ
WKH3OXJLQ0DQDJHU&OLFNWKH,QVWDOOHGWDEDQGVFUROOGRZQWRILQGWKHWZR6FDODSOX
JLQV7KH\VKRXOGEHOLVWHGZLWKDEODFNIRQWDQGWKHFKHFNER[HVQH[WWRWKHPVKRXOG
EHFKHFNHGDVVHHQLQ)LJXUH

)LJXUH,QVWDOOHG,QWHOOL-,'($6FDODSOXJLQV

,IWKHIRQWLVUHGRUWKHFKHFNER[HVDUHQRWFKHFNHGUHIHUWRWKH6FDODSOXJLQZHESDJH
DERYHIRUGHEXJJLQJKHOS

Developing Scala applications


7RFUHDWHDQ,'($6FDODSURMHFWVWDUWE\VHOHFWLQJWKH)LOHz1HZ3URMHFWPHQXLWHP
,QWKHGLDORJVHOHFWWKHDSSURSULDWHUDGLREXWWRQIRU\RXUVLWXDWLRQHJ£&UHDWH1HZ
3URMHFWIURP6FUDWFK¤
2QWKHQH[WVFUHHQVHOHFW£-DYD0RGXOH¤DQGILOOLQWKHXVXDOSURMHFWLQIRUPDWLRQ$Q
H[DPSOHLVVKRZQLQ)LJXUH

Integration with IDEs | 357

Download at WoweBook.Com
)LJXUH6SHFLI\LQJ,QWHOOL-,'($6FDODSURMHFWGHWDLOV

&OLFN WKURXJK WR WKH VFUHHQ WLWOHG £3OHDVH 6HOHFW 'HVLUHG 7HFKQRORJ\¤ &KHFN WKH
£6FDOD¤FKHFNER[DQGFKHFNWKH£1HZ6FDOD6'.¤FKHFNER[&OLFNWKHEXWWRQODEHOHG
£š¤ WR QDYLJDWH WR WKH ORFDWLRQ RI \RXU 6FDOD 6'. LQVWDOODWLRQ DV VKRZQ LQ )LJ
XUH<RXZLOORQO\QHHGWRVSHFLI\WKH6'.WKHILUVWWLPH\RXFUHDWHDSURMHFWRU
ZKHQ\RXLQVWDOODQHZ6'.LQDGLIIHUHQWORFDWLRQ

)LJXUH$GGLQJ6FDODWRWKH,QWHOOL-,'($SURMHFW

&OLFN)LQLVK<RXZLOOEHSURPSWHGWRFUHDWHHLWKHUDSURMHFWRUDQDSSOLFDWLRQ6HOHFW
£$SSOLFDWLRQ¤LI\RXZDQWWRVKDUHWKLVSURMHFWZLWKRWKHU6FDODSURMHFWVRQWKHVDPH
PDFKLQH

358 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
1RZ\RXFDQZRUNZLWK\RXU6FDODSURMHFWXVLQJPRVWRIWKHVDPHFRPPDQGV\RX
ZRXOGXVHZLWKDW\SLFDO-DYDSURMHFW)RUH[DPSOH\RXFDQFUHDWHDQHZ6FDODtrait
objectRUclassXVLQJWKHFRQWH[WPHQXDVIRU-DYDSURMHFWV
7KH,QWHOOL-,'($6FDODSOXJLQLVVWLOOEHWDTXDOLW\EXW6FDODGHYHORSHUVXVLQJ,'($
VKRXOGILQGLWDFFHSWDEOHIRUWKHLUGDLO\QHHGV

NetBeans
1HW%HDQVKDVEHWDTXDOLW\6FDODSOXJLQV6WDUWDWWKLVZHESDJHIRUGHWDLOVKWWSZLNL
QHWEHDQVRUJ6FDOD1HW%HDQVRUDPRUHUHFHQWQLJKWO\EXLOGLVUHTXLUHG7KH6FDOD
SOXJLQFRQWDLQVDYHUVLRQRIWKH6FDOD6'.7KHZLNLSDJHSURYLGHVLQVWUXFWLRQVIRU
XVLQJDGLIIHUHQW6'.ZKHQGHVLUHG

Installing the Scala plugins


7RLQVWDOOWKHSOXJLQGRZQORDGWKHSOXJLQV=,3ILOHIURPKWWSVRXUFHIRUJHQHWSURMHFW
VKRZILOHVSKS"JURXSBLG  SDFNDJHBLG 8Q]LSWKHILOHLQDFRQYHQLHQW
GLUHFWRU\
6WDUW1HW%HDQVDQGLQYRNHWKH7RROVz3OXJLQVPHQXLWHP6HOHFWWKH'RZQORDGHGWDE
DQGFOLFNWKH£$GG3OXJLQVš¤EXWWRQ&KRRVHWKHGLUHFWRU\ZKHUHWKH6FDODSOXJLQVDUH
XQ]LSSHGDQGVHOHFWDOOWKHOLVWHG QEPILOHVDVVKRZQLQ)LJXUH&OLFN2SHQ

)LJXUH$GGLQJWKH6FDODSOXJLQVWREHLQVWDOOHG

Integration with IDEs | 359

Download at WoweBook.Com
%DFN LQ WKH 3OXJLQV GLDORJ PDNH VXUH WKH FKHFNER[HV IRU DOO WKH QHZ SOXJLQV DUH
FKHFNHG&OLFN,QVWDOO
&OLFNWKURXJKWKHLQVWDOODWLRQGLDORJDQGUHVWDUW1HW%HDQVZKHQILQLVKHG

Developing Scala applications


7RFUHDWHD1HW%HDQV6FDOD3URMHFWVWDUWE\VHOHFWLQJWKH)LOHz1HZ3URMHFWPHQXLWHP
RUFOLFNLQJWKH1HZ3URMHFWEXWWRQ,QWKHSRSXSGLDORJVHOHFW£6FDOD¤XQGHU&DWH
JRULHVDQG£6FDOD$SSOLFDWLRQ¤XQGHU3URMHFWVDVVKRZQLQ)LJXUH&OLFN1H[W

)LJXUH&UHDWLQJDQHZ1HW%HDQV6FDODSURMHFW

)LOOLQWKHSURMHFWQDPHORFDWLRQHWFDQGFOLFN)LQLVK
2QFHWKHSURMHFWLVFUHDWHG\RXFDQZRUNZLWKLWXVLQJPRVWRIWKHVDPHFRPPDQGV
\RXZRXOGXVHZLWKDW\SLFDO-DYDSURMHFW7KHUHDUHVRPHGLIIHUHQFHV)RUH[DPSOH
ZKHQ\RXLQYRNHWKH1HZLWHPLQWKHFRQWH[WPHQXWKHVXEPHQXGRHVQRWVKRZLWHPV
IRUFUHDWLQJQHZ6FDODW\SHV,QVWHDG\RXKDYHLQYRNHWKH2WKHUšPHQXLWHPDQGZRUN
WKURXJKDGLDORJ7KLVZLOOEHFKDQJHGLQDIXWXUHUHOHDVH
'HVSLWHVRPHPLQRULVVXHVOLNHWKLVWKH1HW%HDQV6FDODSOXJLQLVPDWXUHHQRXJKIRU
UHJXODUXVH

Text Editors
7KHsbazWRROPDQDJHVWKHscala-tool-supportSDFNDJHWKDWLQFOXGHV6FDODSOXJLQVIRU
VHYHUDOHGLWRUVLQFOXGLQJ(PDFV9LP7H[W0DWHDQGRWKHUV/LNHsbazWKHscala-tool-
supportSDFNDJHLVDOVRLQFOXGHGZLWKWKHODQJXDJHLQVWDOODWLRQ6HHWKHGLUHFWRULHVLQ
scala-homePLVFVFDODWRROVXSSRUW IRU WKH VXSSRUWHG HGLWRUV 0RVW RI WKH HGLWRU
VSHFLILFGLUHFWRULHVFRQWDLQLQVWUXFWLRQVIRULQVWDOOLQJWKHSOXJLQ,QRWKHUFDVHVFRQVXOW
\RXUHGLWRU¦VLQVWUXFWLRQVIRULQVWDOOLQJWKLUGSDUW\SOXJLQV
6RPHRIWKHSDFNDJHVDUHIDLUO\LPPDWXUH,I\RXZDQWWRFRQWULEXWHWRWKH6FDODFRP
PXQLW\SOHDVHFRQVLGHULPSURYLQJWKHTXDOLW\RIWKHH[LVWLQJSOXJLQVRUFRQWULEXWLQJ
QHZSOXJLQV

360 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
$WWKHWLPHRIWKLVZULWLQJWKHUHDUHVHYHUDOYDULDWLRQVRID6FDOD£EXQGOH¤
IRUWKH7H[W0DWHHGLWRUZKLFKLVDSRSXODUWH[WHGLWRUIRU0DF26;
7KHVH EXQGOHV DUH FXUUHQWO\ EHLQJ PDQDJHG E\ 3DXO 3KLOOLSV RQ WKH
*LW+XE ZHEVLWH +RSHIXOO\ WKH EHVW IHDWXUHV RI HDFK EXQGOH ZLOO EH
XQLILHG LQWR DQ £DXWKRULWDWLYH¤ EXQGOH DQG LQWHJUDWHG EDFN LQWR WKH
scala-tool-supportSDFNDJH

Test-Driven Development in Scala


2QHRIWKHPRVWLPSRUWDQWGHYHORSHUSUDFWLFHVLQWURGXFHGLQWKHODVWGHFDGHLV7HVW
'ULYHQ'HYHORSPHQW 7'' 7KH6FDODFRPPXQLW\KDVFUHDWHGVHYHUDOWRROVWRVXSSRUW
7''
,I\RXZRUNLQD£SXUH¤-DYDVKRSFRQVLGHULQWURGXFLQJRQHRUPRUHRIWKHVH6FDOD
WHVWLQJWRROVWRWHVWGULYH\RXU-DYDFRGH7KLVDSSURDFKLVDORZULVNZD\WRLQWURGXFH
6FDODWR\RXUHQYLURQPHQWVR\RXFDQJDLQH[SHULHQFHZLWKLWEHIRUHPDNLQJWKHFRP
PLWPHQWWR6FDODDV\RXUSURGXFWLRQFRGHODQJXDJH,QSDUWLFXODU\RXPLJKWH[SHUL
PHQWZLWK6FDOD7HVW VHH£6FDOD7HVW¤QH[W ZKLFKFDQEHXVHGZLWK-8QLW >-8QLW@ DQG
7HVW1* >7HVW1*@  <RX PLJKW DOVR FRQVLGHU 6FDOD&KHFN RU 5HGXFWLR VHH £6FDOD
&KHFN¤RQSDJH ZKLFKRIIHULQQRYDWLRQVWKDWPD\QRWEHDYDLODEOHLQ-DYDWHVWLQJ
IUDPHZRUNV$OORIWKHWRROVZHGHVFULEHKHUHLQWHJUDWHZLWK-DYDWHVWLQJDQGEXLOGWRROV
OLNH-8QLW7HVW1*YDULRXVPRFNLQJOLEUDULHV$QW >$QW@ DQG0DYHQ >0DYHQ@ $OO
RIWKHPDOVRRIIHUFRQYHQLHQW6FDOD'6/VIRUWHVWLQJ

ScalaTest
6FDOD¦VYHUVLRQRIWKHYHQHUDEOH;8QLWWRROLV6FDOD7HVWDYDLODEOHDWKWWSZZZDUWLPD
FRPVFDODWHVW
<RXFDQGULYH\RXUWHVWVXVLQJWKHEXLOWLQRunnerRUXVHWKHSURYLGHGLQWHJUDWLRQZLWK
-8QLWRU7HVW1*6FDOD7HVWDOVRFRPHVZLWKDQ$QWWDVNDQGLWZRUNVZLWKWKH6FDOD
&KHFNWHVWLQJWRRO GHVFULEHGODWHU 
%HVLGHVVXSSRUWLQJWKHWUDGLWLRQDO;8QLWVW\OHV\QWD[ZLWKWHVWPHWKRGVDQGDVVHUWLRQV
6FDOD7HVWSURYLGHVD%HKDYLRU'ULYHQ'HYHORSPHQW >%''@ V\QWD[WKDWLVEHFRPLQJ
LQFUHDVLQJO\SRSXODU7KH6FDOD7HVWZHEVLWHSURYLGHVH[DPSOHVIRUWKHVHDQGRWKHURS
WLRQV
+HUHLVDQH[DPSOH6FDOD7HVWWHVWIRUWKHVLPSOHComplexFODVVZHXVHGLQ£7KHVFDODS
MDYDSDQGMDG&RPPDQG/LQH7RROV¤RQSDJH
// code-examples/ToolsLibs/complex-test.scala

import org.scalatest.FunSuite

class ComplexSuite extends FunSuite {

val c1 = Complex(1.2, 3.4)

Test-Driven Development in Scala | 361

Download at WoweBook.Com
val c2 = Complex(5.6, 7.8)

test("addition with (0, 0)") {


assert(c1 + Complex(0.0, 0.0) === c1)
}

test("subtraction with (0, 0)") {


assert(c1 - Complex(0.0, 0.0) === c1)
}

test("addition") {
assert((c1 + c2).real === (c1.real + c2.real))
assert((c1 + c2).imaginary === (c1.imaginary + c2.imaginary))
}

test("subtraction") {
assert((c1 - c2).real === (c1.real - c2.real))
assert((c1 - c2).imaginary === (c1.imaginary - c2.imaginary))
}
}

7KLVSDUWLFXODUH[DPSOHXVHVWKH£IXQFWLRQYDOXH¤V\QWD[IRUHDFKWHVWWKDWLVSURYLGHG
E\WKHFunSuiteSDUHQWWUDLW(DFKFDOOWRtestUHFHLYHVDVDUJXPHQWVDGHVFULSWLYHVWULQJ
DQGDIXQFWLRQOLWHUDOZLWKWKHDFWXDOWHVWFRGH
7KHIROORZLQJFRPPDQGVFRPSLOHFRPSOH[VFDODDQGFRPSOH[WHVWVFDODSXWWLQJWKH
FODVVILOHVLQDEXLOGGLUHFWRU\DQGWKHQUXQWKHWHVWV1RWHWKDWZHDVVXPHWKDWVFDODW
HVWMDU WKHODWHVWUHOHDVHDWWKHWLPHRIWKLVZULWLQJ LVLQWKHOLEGLUHFWRU\7KH
GRZQORDGDEOHGLVWULEXWLRQRIWKHFRGHH[DPSOHVLVRUJDQL]HGWKLVZD\
scalac -classpath ../lib/scalatest-0.9.5.jar -d build complex.scala complex-test.scala
scala -classpath build:../lib/scalatest-0.9.5.jar org.scalatest.tools.Runner \
-p build -o -s ComplexSuite

:H XVHG D \ WR FRQWLQXH WKH ORQJ FRPPDQG RQ D VHFRQG OLQH  7KH RXWSXW LV WKH
IROORZLQJ
Run starting. Expected test count is: 4
Suite Starting - ComplexSuite: The execute method of a nested suite is \
about to be invoked.
Test Starting - ComplexSuite: addition with (0, 0)
Test Succeeded - ComplexSuite: addition with (0, 0)
Test Starting - ComplexSuite: subtraction with (0, 0)
Test Succeeded - ComplexSuite: subtraction with (0, 0)
Test Starting - ComplexSuite: addition
Test Succeeded - ComplexSuite: addition
Test Starting - ComplexSuite: subtraction
Test Succeeded - ComplexSuite: subtraction
Suite Completed - ComplexSuite: The execute method of a nested suite \
returned normally.
Run completed. Total number of tests run was: 4
All tests passed.

$JDLQZHZUDSSHGWKHORQJRXWSXWOLQHVZLWKD\

362 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
Specs
7KH6SHFVOLEUDU\ >6FDOD6SHFV7RRO@ LVD%HKDYLRU'ULYHQ'HYHORSPHQW >%''@ WHVW
LQJWRROIRU6FDOD,WLVLQVSLUHGE\5XE\¦V56SHF >56SHF@ ,QDQXWVKHOOWKHJRDORI
%''LVWRUHFDVWWUDGLWLRQDOWHVWV\QWD[LQWRDIRUPWKDWEHWWHUHPSKDVL]HVWKHUROHRI
7'' DV D SURFHVV WKDW GULYHV GHVLJQ ZKLFK LQ WXUQ VKRXOG LPSOHPHQW WKH UHTXLUH
PHQWV£VSHFLILFDWLRQ¤7KHV\QWD[RIWUDGLWLRQDO7''WRROVOLNHWKH;8QLWIUDPHZRUNV
WHQGWRHPSKDVL]HWKHWHVWLQJUROHRI7'':LWKWKHV\QWD[UHDOLJQHGLWLVEHOLHYHGWKDW
WKHGHYHORSHUZLOOEHPRUHOLNHO\WRVWD\IRFXVHGRQWKHSULPDU\UROHRI7''GULYLQJ
DSSOLFDWLRQGHVLJQ
<RXFDQDOVRILQGGRFXPHQWDWLRQRQ6SHFVDW>6FDOD7RROV@
:H KDYH DOUHDG\ XVHG 6SHFV LQ VHYHUDO H[DPSOHV LQ WKH ERRN HJ ButtonObserver
Spec LQ £7UDLWV $V 0L[LQV¤ RQ SDJH  +HUH LV DQRWKHU H[DPSOH IRU WKH VLPSOH
ComplexFODVVZHVKRZHGSUHYLRXVO\
// code-examples/ToolsLibs/complex-spec.scala

import org.specs._

object ComplexSpec extends Specification {


"Complex addition with (0.0, 0.0)" should {
"return a number N' that is identical to original number N" in {
val c1 = Complex(1.2, 3.4)
(c1 + Complex(0.0, 0.0)) mustEqual c1
}
}
"Complex subtraction with (0.0, 0.0)" should {
"return a number N' that is identical to original number N" in {
val c1 = Complex(1.2, 3.4)
(c1 - Complex(0.0, 0.0)) mustEqual c1
}
}
"Complex addition" should {
"""return a new number where
the real and imaginary parts are the sums of the
input values' real and imaginary parts, respectively.""" in {
val c1 = Complex(1.2, 3.4)
val c2 = Complex(5.6, 7.8)
(c1 + c2).real mustEqual (c1.real + c2.real)
(c1 + c2).imaginary mustEqual (c1.imaginary + c2.imaginary)
}
}
"Complex subtraction" should {
"""return a new number where
the real and imaginary parts are the differences of the
input values' real and imaginary parts, respectively.""" in {
val c1 = Complex(1.2, 3.4)
val c2 = Complex(5.6, 7.8)
(c1 - c2).real mustEqual (c1.real - c2.real)
(c1 - c2).imaginary mustEqual (c1.imaginary - c2.imaginary)
}

Test-Driven Development in Scala | 363

Download at WoweBook.Com
}
}

$Q objectWKDWH[WHQGV SpecificationLVWKHDQDORJRIDWHVWVXLWH7KHQH[WOHYHORI


JURXSLQJHJWKHFODXVH"Complex addition with (0.0, 0.0)" should {...}HQFDS
VXODWHVWKHLQIRUPDWLRQDWWKHOHYHORIWKHW\SHEHLQJWHVWHGRUSHUKDSVD£FOXVWHU¤RI
EHKDYLRUVWKDWJRWRJHWKHUIRUWKHW\SH
7KH QH[W OHYHO FODXVH HJ WKH FODXVH "return a number N' that is identical to
original number N" in {...}LVFDOOHGDQ£H[DPSOH¤LQ%''WHUPLQRORJ\,WLVDQDOR
JRXVWRDVLQJOHWHVW/LNHW\SLFDO;8QLWIUDPHZRUNVWKHWHVWLQJLVGRQHXVLQJ£UHSUH
VHQWDWLYH H[DPSOHV¤ UDWKHU WKDQ E\ GRLQJ DQ H[KDXVWLYH H[SORUDWLRQ RI WKH HQWLUH
£VSDFH¤RISRVVLEOHVWDWHV+HQFHWKHWHUP£H[DPSOH¤ +RZHYHUVHHWKHGLVFXVVLRQ
RI6FDOD&KHFNQH[W
6WDWHPHQWV OLNH (c1 + Complex(0.0, 0.0)) mustEqual c1 DUH FDOOHG £H[SHFWDWLRQV¤
7KH\GRWKHDFWXDOYHULILFDWLRQVWKDWFRQGLWLRQVDUHVDWLVILHG+HQFHH[SHFWDWLRQVDUH
DQDORJRXVWRDVVHUWLRQVLQ;8QLWWRROV
7KHUHDUHVHYHUDOZD\VWRUXQ\RXUVSHFV$IWHUFRPSLOLQJFRPSOH[VSHFVFDODHDUOLHU
ZHFDQUXQWKHVSHFVDVIROORZV
scala -classpath ../lib/specs-1.4.3.jar:build ComplexSpec

+HUHDVEHIRUHZHDVVXPHWKH6SHFV-$5LVLQWKHOLEGLUHFWRU\DQGZHDVVXPHWKH
FRPSLOHGFODVVILOHVDUHLQWKHEXLOGGLUHFWRU\:HJHWWKHIROORZLQJRXWSXW
Specification "ComplexSpec"
Complex addition with (0.0, 0.0) should
+ return a number N' that is identical to original number N

Total for SUT "Complex addition with (0.0, 0.0)":


Finished in 0 second, 0 ms
1 example, 1 expectation, 0 failure, 0 error

Complex subtraction with (0.0, 0.0) should


+ return a number N' that is identical to original number N

Total for SUT "Complex subtraction with (0.0, 0.0)":


Finished in 0 second, 0 ms
1 example, 1 expectation, 0 failure, 0 error

Complex addition should


+ return a new number where
the real and imaginary parts are the sums of the
input values real and imaginary parts, respectively.

Total for SUT "Complex addition":


Finished in 0 second, 0 ms
1 example, 2 expectations, 0 failure, 0 error

Complex subtraction should


+ return a new number where
the real and imaginary parts are the differences of the

364 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
input values real and imaginary parts, respectively.

Total for SUT "Complex subtraction":


Finished in 0 second, 0 ms
1 example, 2 expectations, 0 failure, 0 error

Total for specification "ComplexSpec":


Finished in 0 second, 37 ms
4 examples, 6 expectations, 0 failure, 0 error

1RWHWKDWWKHVWULQJVLQWKHVSHFLILFDWLRQDUHZULWWHQLQDIRUPWKDWUHDGVVRPHZKDWOLNH
DUHTXLUHPHQWVVSHFLILFDWLRQ
...
Complex addition with (0.0, 0.0) should
+ return a number N' that is identical to original number N
...

7KHUHDUHPDQ\ZD\VWRUXQVSHFLILFDWLRQVLQFOXGLQJXVLQJDQ$QWWDVNRUXVLQJWKH
EXLOWLQ LQWHJUDWLRQ ZLWK 6FDOD7HVW RU -8QLW -8QLW LV WKH EHVW DSSURDFK IRU UXQQLQJ
VSHFLILFDWLRQVLQVRPH,'(V7KHVHDQGRWKHURSWLRQVDUHGHVFULEHGLQWKH8VHU¦V*XLGH
DWKWWSFRGHJRRJOHFRPSVSHFVZLNL5XQQLQJ6SHFV

ScalaCheck
6FDOD&KHFN >6FDOD&KHFN7RRO@LVD6FDODSRUWRIWKHLQQRYDWLYH+DVNHOO4XLFN&KHFN
>4XLFN&KHFN@ WRROWKDWVXSSRUWV$XWRPDWHG6SHFLILFDWLRQ%DVHG7HVWLQJVRPHWLPHV
FDOOHGW\SHEDVHG£SURSHUW\¤WHVWLQJLQWKH+DVNHOOOLWHUDWXUH HJ>2¦6XOOLYDQ@ 
6FDOD&KHFNFDQEHLQVWDOOHGXVLQJsbazLHsbaz install scalacheck
8VLQJ6FDOD&KHFN RU4XLFN&KHFNIRU+DVNHOO FRQGLWLRQVIRUDW\SHDUHVSHFLILHGWKDW
VKRXOGEHWUXHIRUDQ\LQVWDQFHVRIWKHW\SH7KHWRROWULHVWKHFRQGLWLRQVXVLQJDXWR
PDWLFDOO\JHQHUDWHGLQVWDQFHVRIWKHW\SHDQGYHULILHVWKDWWKHFRQGLWLRQVDUHVDWLVILHG
+HUHLVD6FDOD&KHFNWHVWIRUComplex
// code-examples/ToolsLibs/complex-check-script.scala

import org.scalacheck._
import org.scalacheck.Prop._

def toD(i: Int) = i * .1

implicit def arbitraryComplex: Arbitrary[Complex] = Arbitrary {


Gen.sized {s =>
for {
r <- Gen.choose(-toD(s), toD(s))
i <- Gen.choose(-toD(s), toD(s))
} yield Complex(r, i)
}
}

object ComplexSpecification extends Properties("Complex") {

Test-Driven Development in Scala | 365

Download at WoweBook.Com
def additionTest(a: Complex, b: Complex) =
(a + b).real.equals(a.real + b.real) &&
(a + b).imaginary.equals(a.imaginary + b.imaginary)

def subtractionTest(a: Complex, b: Complex) =


(a - b).real.equals(a.real - b.real) &&
(a - b).imaginary.equals(a.imaginary - b.imaginary)

val zero = Complex(0.0, 0.0)

specify("addition with (0,0)", (a: Complex) => additionTest(a, zero))


specify("subtraction with (0,0)", (a: Complex) => subtractionTest(a, zero))

specify("addition", (a: Complex, b: Complex) => additionTest(a,b))


specify("subtraction", (a: Complex, b: Complex) => subtractionTest(a,b))
}
ComplexSpecification.check

7KHtoDIXQFWLRQMXVWFRQYHUWVDQIntWRDDoubleE\GLYLGLQJE\0.1,W¦VXVHIXOWRFRQYHUW
DQIntLQGH[SURYLGHGE\6FDOD&KHFNLQWRDoubleYDOXHVWKDWZHZLOOXVHWRFRQVWUXFW
ComplexLQVWDQFHV
:H DOVR QHHG DQ LPSOLFLW FRQYHUVLRQ YLVLEOH LQ WKH VFRSH RI WKH WHVW WKDW JHQHUDWHV
QHZ Complex YDOXHV 7KH arbitraryComplex IXQFWLRQ SURYLGHV WKLV JHQHUDWRU $Q
Arbitrary[Complex]REMHFW SDUWRIWKH6FDOD&KHFN$3, LVUHWXUQHGE\WKLVPHWKRG
6FDOD&KHFNLQYRNHVDQRWKHU$3,PHWKRGGen[Complex].sized:HSURYLGHDIXQFWLRQ
OLWHUDOWKDWDVVLJQVDSDVVHGLQIntYDOXHWRDYDULDEOHs:HWKHQXVHDforFRPSUHKHQ
VLRQWRUHWXUQComplexQXPEHUVZLWKUHDODQGLPDJLQDU\SDUWVWKDWUDQJHIURP-toD(s)WR
toD(s) LH -(s * .1) WR (s * .1)  )RUWXQDWHO\ \RX GRQ¦W KDYH WR GHILQH LPSOLFLW
FRQYHUVLRQVRUJHQHUDWRUVIRUPRVWRIWKHFRPPRQO\XVHG6FDODDQG-DYDW\SHV
7KHPRVWLQWHUHVWLQJSDUWLVWKHGHILQLWLRQDQGXVHRIComplexSpecification7KLVREMHFW
GHILQHV D IHZ KHOSHU PHWKRGV additionTest DQG subtractionTest WKDW HDFK UHWXUQ
trueLIWKHFRQGLWLRQVWKH\GHILQHDUHWUXH)RUadditionTestLIDQHZComplexQXPEHU
LVWKHVXPRIWZRRWKHUComplexQXPEHUVWKHQLWVrealSDUWPXVWHTXDOWKHVXPRIWKH
realSDUWVRIWKHWZRRULJLQDOQXPEHUV/LNHZLVHDVLPLODUFRQGLWLRQPXVWKROGIRUWKH
imaginarySDUWRIWKHQXPEHUV)RU subtractionTestWKHVDPHFRQGLWLRQVPXVWKROG
ZLWKVXEWUDFWLRQVXEVWLWXWHGIRUDGGLWLRQ
1H[WWZRspecifyFODXVHVDVVHUWWKDWWKHDGGLWLRQDQGVXEWUDFWLRQFRQGLWLRQVVKRXOG
KROGIRUDQ\ComplexQXPEHUZKHQComplex(0.0, 0.0)LVDGGHGWRLWRUVXEWUDFWHGIURP
LWUHVSHFWLYHO\7ZRPRUHspecifyFODVVHVDVVHUWWKDWWKHFRQGLWLRQVVKRXOGDOVRKROG
IRUDQ\SDLURIComplexQXPEHUV
)LQDOO\ZKHQComplexSpecification.checkLVFDOOHGWHVWUXQVDUHPDGHZLWKGLIIHUHQW
YDOXHVRI ComplexQXPEHUVYHULI\LQJWKDWWKHSURSHUWLHVVSHFLILHGDUHYDOLGIRUHDFK
FRPELQDWLRQRIQXPEHUVSDVVHGWRWKHKHOSHUPHWKRGV
:H FDQ UXQ WKH FKHFN XVLQJ WKH IROORZLQJ FRPPDQG RQFH DJDLQ DVVXPLQJ WKDW
ComplexLVDOUHDG\FRPSLOHGLQWRWKHEXLOGGLUHFWRU\ 

366 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
scala -classpath ../lib/scalacheck.jar:build complex-check-script.scala

,WSURGXFHVWKHIROORZLQJRXWSXW
+ Complex.addition with (0,0): OK, passed 100 tests.
+ Complex.addition: OK, passed 100 tests.
+ Complex.subtraction with (0,0): OK, passed 100 tests.
+ Complex.subtraction: OK, passed 100 tests.

1RWHWKDW6FDOD&KHFNWULHGHDFKspecifyFDVHZLWKGLIIHUHQWLQSXWV
,W¦V LPSRUWDQW WR XQGHUVWDQG WKH YDOXH WKDW 6FDOD&KHFN GHOLYHUV 5DWKHU WKDQ JRLQJ
WKURXJKWKHSURFHVVRIZULWLQJHQRXJK£H[DPSOH¤WHVWFDVHVZLWKUHSUHVHQWDWLYHGDWD
ZKLFKLVWHGLRXVDQGHUURUSURQHZHGHILQHUHXVDEOH£JHQHUDWRUV¤OLNHWKHarbitrary
ComplexIXQFWLRQWRSURGXFHDQDSSURSULDWHUDQJHRILQVWDQFHVRIWKHW\SHXQGHUWHVW
7KHQZHZULWHSURSHUW\VSHFLILFDWLRQVWKDWVKRXOGKROGIRUDQ\LQVWDQFHV6FDOD&KHFN
GRHVWKHZRUNRIWHVWLQJWKHSURSHUWLHVDJDLQVWDUDQGRPVDPSOHRIWKHLQVWDQFHVSUR
GXFHGE\WKHJHQHUDWRUV
<RXFDQILQGPRUHH[DPSOHVRI6FDOD&KHFNXVDJHLQWKHRQOLQHFRGHH[DPSOHV6RPH
RIWKHW\SHVXVHGLQWKHSD\UROOH[DPSOHLQ£,QWHUQDO'6/V¤RQSDJHZHUHWHVWHG
ZLWK6FDOD&KHFN7KHVHWHVWVZHUHQRWVKRZQLQ£,QWHUQDO'6/V¤RQSDJH
)LQDOO\QRWHWKDWWKHUHLVDQRWKHUSRUWRI4XLFN&KHFNFDOOHG5HGXFWLR,WLVSDUWRIWKH
)XQFWLRQDO -DYD SURMHFW >)XQFWLRQDO-DYD@  5HGXFWLR LV OHVV ZLGHO\ XVHG WKDQ 6FDOD
&KHFNEXWLWRIIHUVD£QDWLYH¤-DYD$3,DVZHOODVD6FDOD$3,VRLWZRXOGEHPRUH
FRQYHQLHQWIRU£SXUH¤-DYDWHDPV

Other Notable Scala Libraries and Tools


:KLOH6FDODEHQHILWVIURPWKHULFKOHJDF\RI-DYDDQG1(7OLEUDULHVWKHUHLVDJURZLQJ
FROOHFWLRQRIOLEUDULHVZULWWHQVSHFLILFDOO\IRU6FDOD+HUHZHGLVFXVVVRPHRIWKHPRUH
QRWDEOHRQHV

Lift
/LIWLVWKHOHDGLQJZHEDSSOLFDWLRQIUDPHZRUNZULWWHQLQ6FDOD,WUHFHQWO\UHDFKHG£¤
VWDWXV /LIW KDV EHHQ XVHG IRU D QXPEHU RI FRPPHUFLDO ZHEVLWHV <RX FDQ DOVR ILQG
GRFXPHQWDWLRQRQWKH/LIWZHEVLWH
2WKHUZHEIUDPHZRUNVLQFOXGH6ZHHW3LQN\DQG6OLQN\

Scalaz
6FDOD]LVDOLEUDU\WKDWILOOVLQJDSVLQWKHVWDQGDUGOLEUDU\$PRQJLWVIHDWXUHVDUHHQ
KDQFHPHQWVWRVHYHUDOFRUH6FDODW\SHVVXFKDVBooleanUnitStringDQGOptionSOXV
VXSSRUWIRUIXQFWLRQDOFRQWURODEVWUDFWLRQVVXFKDVFoldLeftFoldRightDQGMonadWKDW
H[SDQGXSRQZKDWLVDYDLODEOHLQWKHVWDQGDUGOLEUDU\

Other Notable Scala Libraries and Tools | 367

Download at WoweBook.Com
Scalax
6FDOD[LVDQRWKHUWKLUGSDUW\OLEUDU\HIIRUWWRVXSSOHPHQWWKH6FDODFRUHOLEUDU\

MetaScala
0HWD6FDODLVDQH[SHULPHQWDOPHWDSURJUDPPLQJOLEUDU\IRU6FDOD0HWDSURJUDPPLQJ
IHDWXUHVWHQGWREHZHDNHULQVWDWLFDOO\W\SHGODQJXDJHVWKDQLQG\QDPLFDOO\W\SHGODQ
JXDJHV$OVRWKH-90DQG1(7&/5LPSRVHWKHLURZQFRQVWUDLQWVRQPHWDSURJUDP
PLQJ
0DQ\RIWKHIHDWXUHVRI6FDODREYLDWHWKHQHHGIRUPHWDSURJUDPPLQJFRPSDUHGWR
ODQJXDJHVOLNH5XE\EXWVRPHWLPHVPHWDSURJUDPPLQJLVVWLOOXVHIXO0HWD6FDODDW
WHPSWVWRDGGUHVVWKRVHQHHGVPRUHIXOO\WKDQ6FDOD¦VEXLOWLQUHIOHFWLRQVXSSRUW

JavaRebel
-DYD5HEHOLVDFRPPHUFLDOWRROWKDWSHUPLWVG\QDPLFUHORDGLQJRIFODVVHVLQDUXQQLQJ
-90 ZULWWHQLQDQ\ODQJXDJH EH\RQGWKHOLPLWHGVXSSRUWSURYLGHGQDWLYHO\E\WKH
£+RW6ZDS¤ IHDWXUH RI WKH -90 -DYD5HEHO LV GHVLJQHG WR RIIHU WKH GHYHORSHU IDVWHU
WXUQDURXQGIRUFKDQJHVSURYLGLQJDQH[SHULHQFHPRUHOLNHWKHUDSLGWXUQDURXQGWKDW
XVHUVRIG\QDPLFODQJXDJHVHQMR\-DYD5HEHOFDQEHXVHGZLWK6FDODFRGHDVZHOO

Miscellaneous Smaller Libraries


)LQDOO\7DEOHLVDOLVWRIVHYHUDO6FDODVSHFLILFOLEUDULHV\RXPLJKWILQGXVHIXOIRU
\RXUDSSOLFDWLRQV
7DEOH0LVFHOODQHRXV6FDODOLEUDULHV
Name Description and URL
Kestrel A tiny, very fast queue system (http://github.com/robey/kestrel/tree/master).
ScalaModules Scala DSL to ease OSGi development (http://code.google.com/p/scalamodules/).
Configgy Managing configuration files and logging for “daemons” written in Scala (http://www.lag.net/configgy/).
scouchdb Scala interface to CouchDB (http://code.google.com/p/scouchdb/).
Akka A project to implement a platform for building fault-tolerant, distributed applications based on REST, Actors,
etc. (http://akkasource.org/).
scala-query A type-safe database query API for Scala (http://github.com/szeiger/scala-query/tree/master).

:H¦OOGLVFXVVXVLQJ6FDODZLWKVHYHUDOZHOONQRZQ-DYDOLEUDULHVDIWHUZHGLVFXVV-DYD
LQWHURSHUDELOLW\QH[W

368 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
Java Interoperability
2IDOOWKHDOWHUQDWLYH-90ODQJXDJHV6FDOD¦VLQWHURSHUDELOLW\ZLWK-DYDVRXUFHFRGHLV
DPRQJWKHPRVWVHDPOHVV7KLVVHFWLRQEHJLQVZLWKDGLVFXVVLRQRILQWHURSHUDELOLW\ZLWK
FRGHZULWWHQLQ-DYD2QFH\RXXQGHUVWDQGWKHGHWDLOVWKH\FDQEHJHQHUDOL]HGWRDG
GUHVVLQWHURSHUDELOLW\ZLWKRWKHU-90ODQJXDJHVVXFKDV-5XE\RU*URRY\)RUH[DP
SOHLI\RXDOUHDG\NQRZKRZWRXVH-5XE\DQG-DYDWRJHWKHUDQG\RXNQRZKRZWR
XVH-DYDDQG6FDODWRJHWKHUWKHQ\RXFDQJHQHUDOL]HWRXVLQJ-5XE\DQG6FDODWRJHWKHU
%HFDXVH6FDODV\QWD[LVSULPDULO\DVXSHUVHWRI-DYDV\QWD[LQYRNLQJ-DYDFRGHIURP
6FDODLVXVXDOO\VWUDLJKWIRUZDUG*RLQJWKHRWKHUGLUHFWLRQUHTXLUHVWKDW\RXXQGHUVWDQG
KRZVRPH6FDODIHDWXUHVDUHHQFRGHGLQZD\VWKDWVDWLVI\WKH-90VSHFLILFDWLRQ:H
GLVFXVV VHYHUDO RI WKH LQWHURSHUDELOLW\ LVVXHV KHUH >6SLHZDND@ DQG >2GHU
VN\@SURYLGHDGGLWLRQDOLQIRUPDWLRQ

Java and Scala Generics


:H KDYH VHHQ PDQ\ H[DPSOHV RI 6FDOD FRGH WKDW XVHV -DYD W\SHV VXFK DV
java.lang.StringDQGYDULRXVMDYDFROOHFWLRQFODVVHV,QVWDQWLDWLQJ-DYDJHQHULFW\SHV
LVVWUDLJKWIRUZDUGLQ6FDOD VLQFH6FDODYHUVLRQ &RQVLGHUWKHIROORZLQJYHU\VLP
SOH-DYDJHQHULFFODVVJStack
// code-examples/ToolsLibs/JStack.java

import java.util.*;

public class JStack<T> {


private List<T> stack = new ArrayList<T>();
public void push(T t) {
stack.add(t);
}
public T pop() {
return stack.remove(stack.size() - 1);
}
}

:HFDQLQVWDQWLDWHLWIURP6FDODVSHFLI\LQJWKHW\SHSDUDPHWHUDVVKRZQLQ([DP
SOH
([DPSOH$6FDOD£VSHF¤WRWHVWWKHVLPSOH-DYDVWDFN
// code-examples/ToolsLibs/JStack-spec.scala

import org.specs._

object JStackSpec extends Specification {


"Calling a Java generic type from Scala" should {
"Support parameterization" in {
val js = new JStack[String]
js must notBe(null) // Dummy check...
}

Java Interoperability | 369

Download at WoweBook.Com
"Support invoking the the type's methods" in {
val js = new JStack[String]
js.push("one")
js.push("two")
js.pop() mustEqual "two"
js.pop() mustEqual "one"
}
}
}

6LQFH6FDODYHUVLRQ\RXFDQDOVRXVH6FDODJHQHULFVIURP-DYD&RQVLGHUWKHIRO
ORZLQJ-8QLWWHVWZKLFKVKRZVVRPHRIWKHLGLRV\QFUDVLHV\RXPLJKWHQFRXQWHU
// code-examples/ToolsLibs/SMapTest.java

import org.junit.*;
import static org.junit.Assert.*;
import scala.*;
import scala.collection.mutable.LinkedHashMap;

public class SMapTest {


static class Name {
public String firstName;
public String lastName;

public Name(String firstName, String lastName) {


this.firstName = firstName;
this.lastName = lastName;
}
}

LinkedHashMap<Integer, Name> map;

@Before
public void setup() {
map = new LinkedHashMap<Integer, Name>();
map.update(1, new Name("Dean", "Wampler"));
map.update(2, new Name("Alex", "Payne"));
}

@Test
public void usingMapGetWithWarnings() {
assertEquals(2, map.size());
Option<Name> n1 = map.get(1); // warning
Option<Name> n2 = map.get(2); // warning
assertTrue(n1.isDefined());
assertTrue(n2.isDefined());
assertEquals("Dean", n1.get().firstName);
assertEquals("Alex", n2.get().firstName);
}

@Test
public void usingMapGetWithoutWarnings() {
assertEquals(2, map.size());
Option<?> n1 = map.get(1);

370 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
Option<?> n2 = map.get(2);
assertTrue(n1.isDefined());
assertTrue(n2.isDefined());
assertEquals("Dean", ((Name) n1.get()).firstName);
assertEquals("Alex", ((Name) n2.get()).firstName);
}
}

2Q8QL[OLNHV\VWHPVLWLVFRPSLOHGZLWKWKHIROORZLQJFRPPDQGOLQH
javac -Xlint:unchecked \
-cp $SCALA_HOME/lib/scala-library.jar:$JUNIT_HOME/junit-4.4.jar SMapTest.java

$JDLQZHZUDSSHGWKHORQJOLQHZLWK\ 6&$/$B+20(DQG-81,7B+20(DUHWKH
LQVWDOODWLRQGLUHFWRULHVRI6FDODDQG-8QLWUHVSHFWLYHO\
7KH SMapTest FODVV GHILQHV D QHVWHG Name FODVV WKDW LV XVHG DV WKH £YDOXH¤ W\SH LQ D
scala.collection.mutable.LinkedHashMap )RU VLPSOLFLW\ Name KDV SXEOLF firstName
DQGlastNameILHOGVDQGDFRQVWUXFWRU
7KH setupPHWKRGFUHDWHVDQHZ LinkedHashMap<Integer,Name>DQGLQVHUWVWZRNH\
YDOXHSDLUV7KHWZRWHVWVusingMapGetWithWarningsDQGusingMapGetWithoutWarnings
H[HUFLVHWKH-DYD6FDODLQWHURSHUDELOLW\WKHVDPHZD\+RZHYHUWKHILUVWWHVWKDVWZR
FRPSLOHWLPHZDUQLQJVLQGLFDWHGE\WKH// warningFRPPHQWVZKLOHWKHVHFRQGWHVW
FRPSLOHVZLWKRXWZDUQLQJV
SMapTest.java:29: warning: [unchecked] unchecked conversion
found : scala.Option
required: scala.Option<SMapTest.Name>
Option<Name> n1 = map.get(1); // warning
^
SMapTest.java:30: warning: [unchecked] unchecked conversion
found : scala.Option
required: scala.Option<SMapTest.Name>
Option<Name> n2 = map.get(2); // warning
^
2 warnings

7KHZDUQLQJVRFFXUEHFDXVHRIW\SHHUDVXUH,QWKHFRPSLOHG6FDODOLEUDU\WKHUHWXUQ
W\SHRIMap.getLVOptionZLWKQRW\SHSDUDPHWHURUHIIHFWLYHO\Option<Object>6RZH
JHWZDUQLQJVIRUWKHFRQYHUVLRQWROption<Name>
7KHVHFRQGWHVWusingMapGetWithoutWarningsKDVQRZDUQLQJVEHFDXVHZHDVVLJQWKH
YDOXHVUHWXUQHGE\ Map.getWROption<?>DQGWKHQGRDQH[SOLFLWFDVWWRNameZKHQZH
FDOOOption.getLQWKHILQDOWZRDVVHUWLRQV

Using Scala Functions in Java


&RQWLQXLQJZLWKRXUSUHYLRXVSMapTestH[DPSOHZHFDQH[SORUHLQYRNLQJ6FDODFRGH
IURP-DYDZKHUH6FDODIXQFWLRQVDUHUHTXLUHG
// code-examples/ToolsLibs/SMapTestWithFunctions.java

Java Interoperability | 371

Download at WoweBook.Com
import org.junit.*;
import static org.junit.Assert.*;
import scala.*;
import scala.collection.mutable.LinkedHashMap;
import static scala.collection.Map.Projection;

public class SMapTestWithFunctions {


static class Name {
public String firstName;
public String lastName;

public Name(String firstName, String lastName) {


this.firstName = firstName;
this.lastName = lastName;
}

public static Name emptyName = new Name("","");

public static Function0<Name> empty = new Function0<Name>() {


public Name apply() { return emptyName; }

public int $tag() { return 0; }


};
}

LinkedHashMap<Integer, Name> map;

@Before
public void setup() {
map = new LinkedHashMap<Integer, Name>();
map.update(1, new Name("Dean", "Wampler"));
map.update(2, new Name("Alex", "Payne"));
}

@Test
public void usingMapGetOrElse() {
assertEquals(2, map.size());
assertEquals("Dean", ((Name) map.getOrElse(1, Name.empty)).firstName);
assertEquals("Alex", ((Name) map.getOrElse(2, Name.empty)).firstName);
}

Function1<Integer, Boolean> filter = new Function1<Integer, Boolean>() {


public Boolean apply(Integer i) { return i.intValue() <= 1; }

public <A> Function1<A,Boolean> compose(Function1<A,Integer> g) {


return Function1$class.compose(this, g);
}

public <A> Function1<Integer,A> andThen(Function1<Boolean,A> g) {


return Function1$class.andThen(this, g);
}

public int $tag() { return 0; }


};

372 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
@Test
public void usingFilterKeys() {
assertEquals(2, map.size());
Projection<Integer, Name> filteredMap =
(Projection<Integer, Name>) map.filterKeys(filter);
assertEquals(1, filteredMap.size());
assertEquals("Dean", filteredMap.getOrElse(1, Name.empty).firstName);
assertEquals("", filteredMap.getOrElse(2, Name.empty).firstName);
}
}

7KH SMapTestWithFunctionsFODVVKDVLWVRZQ NameFODVVWKDWDGGVDVWDWLF emptyName


REMHFW DQG D VWDWLF scala.Function0 REMHFW empty ZKLFK GHILQHV apply WR UHWXUQ
emptyName1RWHWKDWLWLVDOVRQHFHVVDU\WRGHILQHWKH$tagPHWKRGWKDWZDVGLVFXVVHG
SUHYLRXVO\LQ£7KHVFDODSMDYDSDQGMDG&RPPDQG/LQH7RROV¤RQSDJH
7KH emptyIXQFWLRQREMHFWLVQHHGHGZKHQZHXVH Map.getOrElseLQWKHWHVWPHWKRG
usingMapGetOrElse7KHVLJQDWXUHRIgetOrElseLVWKHIROORZLQJ
def getOrElse[B2 >: B](key : A, default : => B2) : B2

:KHUHALVWKHNH\W\SHSDUDPHWHUBLVWKHYDOXHW\SHSDUDPHWHUDQGB2LVDVXSHUW\SH
RIBRUWKHVDPHDVB7KHVHFRQGdefaultDUJXPHQWLVDE\QDPHSDUDPHWHUZKLFKZH
GLVFXVVHGLQ&KDSWHU1RWHWKDWE\QDPHSDUDPHWHUVDUHLPSOHPHQWHGDVscala.Func
tion0REMHFWV6RZHFDQ¦WVLPSO\SDVVLQWKHVWDWLFREMHFWemptyName
7KH VHFRQG WHVW usingFilterKeys UHTXLUHV D Function1 REMHFW ZKLFK KDV DQ apply
PHWKRGWKDWWDNHVRQHDUJXPHQW:HXVHWKLV Function1REMHFWDVDILOWHUSDVVHGWR
Map.filterKeys
:HGHILQHWKHfilterEHIRUHWKHWHVW7KH-DYDFRGHKHUHLVFRQVLGHUDEO\PRUHLQYROYHG
WKDQWKHHTXLYDOHQW6FDODFRGHZRXOGEH1RWRQO\GRZHKDYHWRGHILQHWKHapplyDQG
$tagPHWKRGVZHPXVWDOVRGHILQHPHWKRGVXVHGIRUIXQFWLRQFRPSRVLWLRQ compose
DQGandThen)RUWXQDWHO\ZHFDQGHOHJDWHWRREMHFWVWKDWDUHDOUHDG\LQWKH6FDODOLEUDU\
DVVKRZQ1RWHWKDWRWKHU FunctionNW\SHVIRU NHTXDOVWRKDYHRWKHUPHWKRGV
WKDWZRXOGKDYHWREHLPSOHPHQWHGXVLQJVLPLODU£ERLOHUSODWH¤)RUH[DPSOHWKHVH
W\SHVHDFKKDYHDcurryPHWKRG
)LQDOO\UHFDOOWKDWLQ£&RPSDQLRQ2EMHFWVDQG-DYD6WDWLF0HWKRGV¤RQSDJHZH
GLVFXVVHGWKDWPHWKRGVGHILQHGLQFRPSDQLRQREMHFWVDUHQRWYLVLEOHDVstaticPHWKRGV
WR-DYDFRGH)RUH[DPSOHmainPHWKRGVGHILQHGLQFRPSDQLRQREMHFWVFDQ¦WEHXVHG
WRUXQWKHDSSOLFDWLRQ,QVWHDG\RXVKRXOGGHILQHVXFKPHWKRGVLQVLQJOHWRQREMHFWV
6RXVLQJ6FDODIXQFWLRQREMHFWVIURP-DYDFDQEHFKDOOHQJLQJ,I\RXILQGLWQHFHVVDU\
WRXVHWKHPIUHTXHQWO\\RXFRXOGGHILQH-DYDXWLOLW\FODVVHVWKDWKDQGOHWKHERLOHUSODWH
IRUDOOWKHPHWKRGVH[FHSWapply

Java Interoperability | 373

Download at WoweBook.Com
JavaBean Properties
:HVDZLQ&KDSWHUWKDW6FDODGRHVQRWIROORZWKH-DYD%HDQV >-DYD%HDQV6SHF@ FRQ
YHQWLRQVIRUILHOGUHDGHUDQGZULWHUPHWKRGVIRUUHDVRQVGHVFULEHGLQ£:KHQ$FFHVVRU
0HWKRGV DQG )LHOGV $UH ,QGLVWLQJXLVKDEOH 7KH 8QLIRUP $FFHVV 3ULQFL
SOH¤ RQ SDJH  +RZHYHU WKHUH DUH WLPHV ZKHQ \RX QHHG -DYD%HDQV DFFHVVRU
PHWKRGV)RUH[DPSOH\RXQHHGWKHPZKHQ\RXZDQW\RXU6FDODLQVWDQFHVWREHFRQ
ILJXUDEOHE\DGHSHQGHQF\LQMHFWLRQPHFKDQLVPOLNHWKHRQHSURYLGHGE\WKH6SULQJ
)UDPHZRUN >6SULQJ)UDPHZRUN@ <RXPD\DOVRQHHG-DYD%HDQVDFFHVVRUPHWKRGVIRU
VRPH,'(VWKDWGREHDQ£LQWURVSHFWLRQ¤
6FDOD VROYHV WKLV SUREOHP ZLWK DQ DQQRWDWLRQ WKDW \RX FDQ DSSO\ WR D ILHOG
@scala.reflect.BeanProperty ZKLFK WHOOV WKH FRPSLOHU WR JHQHUDWH -DYD%HDQVVW\OH
JHWWHU DQG VHWWHU PHWKRGV :H LQWURGXFHG WKLV DQQRWDWLRQ LQ £$QQRWD
WLRQV¤RQSDJH
5HFDOOWKH ComplexFODVVZHVDZSUHYLRXVO\1RZZHDGGWKHDQQRWDWLRQWRHDFKFRQ
VWUXFWRUDUJXPHQWZKLFKLVDILHOGLQWKHcaseFODVV
// code-examples/ToolsLibs/complex-javabean.scala

case class ComplexBean(


@scala.reflect.BeanProperty real: Double,
@scala.reflect.BeanProperty imaginary: Double) {

def +(that: ComplexBean) =


new ComplexBean(real + that.real, imaginary + that.imaginary)
def -(that: ComplexBean) =
new ComplexBean(real - that.real, imaginary - that.imaginary)
}

,I\RXFRPSLOHWKLVFODVVWKHQGHFRPSLOHLWZLWK javap -classpath ... ComplexBean


\RXJHWWKHIROORZLQJRXWSXW
public class ComplexBean extends java.lang.Object
implements scala.ScalaObject,scala.Product,java.io.Serializable{
public ComplexBean(double, double);
public java.lang.Object productElement(int);
public int productArity();
public java.lang.String productPrefix();
public boolean equals(java.lang.Object);
public java.lang.String toString();
public int hashCode();
public int $tag();
public ComplexBean $minus(ComplexBean);
public ComplexBean $plus(ComplexBean);
public double imaginary();
public double real();
public double getImaginary();
public double getReal();
}

1RZFRPSDUHWKLVRXWSXWZLWKWKHUHVXOWRIGHFRPSLOLQJWKHRULJLQDO&RPSOH[FODVVILOH

374 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
public class Complex extends java.lang.Object
implements scala.ScalaObject,scala.Product,java.io.Serializable{
public Complex(double, double);
public java.lang.Object productElement(int);
public int productArity();
public java.lang.String productPrefix();
public boolean equals(java.lang.Object);
public java.lang.String toString();
public int hashCode();
public int $tag();
public Complex $minus(Complex);
public Complex $plus(Complex);
public double imaginary();
public double real();
}

7KHRUGHURIWKHPHWKRGVVKRZQPD\EHGLIIHUHQWZKHQ\RXUXQjavapRQWKHVHILOHV
:HUHRUGHUHGWKHPVRWKHWZROLVWLQJVZRXOGPDWFKDVFORVHO\DVSRVVLEOH1RWHWKDW
WKHRQO\GLIIHUHQFHVDUHWKHQDPHVRIWKHFODVVHVDQGWKHSUHVHQFHRIgetImaginaryDQG
getRealPHWKRGVLQWKH ComplexBeanFDVH:HZRXOGDOVRKDYHFRUUHVSRQGLQJVHWWHU
PHWKRGVLIWKHrealDQGimaginaryILHOGVZHUHGHFODUHGDVvarVLQVWHDGRIvalV

7KH6FDODGRFSDJHIRU @BeanProperty YHUVLRQ VD\VWKDW\RXFDQ¦W


FDOOWKHEHDQVHWWHUPHWKRGVIURP6FDOD<RXFDQFDOOWKHPEXWDVWKH
6FDODGRFSDJHJRHVRQWRVD\\RXVKRXOGXVHWKH6FDODVW\OHZULWHU DQG
UHDGHU PHWKRGVLQVWHDG

AnyVal Types and Java Primitives


1RWLFHDOVRLQWKHSUHYLRXV ComplexH[DPSOHWKDWWKH DoublesZHUHFRQYHUWHGWR-DYD
SULPLWLYHdoubles$OOWKHAnyValW\SHVDUHFRQYHUWHGWRWKHLUFRUUHVSRQGLQJ-DYDSULP
LWLYHV:HVKRZHGWKHPDSSLQJLQ7DEOH,QSDUWLFXODUQRWHWKDWUnitLVPDSSHGWR
void

Scala Names in Java Code


$V ZH GLVFXVVHG LQ &KDSWHU  6FDOD DOORZV PRUH IOH[LEOH LGHQWLILHUV HJ RSHUDWRU
FKDUDFWHUVOLNH*<HWF7KHVHFKDUDFWHUVDUHHQFRGHG RU£PDQJOHG¤LI\RXSUHIHU WR
VDWLVI\WKHWLJKWHUFRQVWUDLQWVRIWKH-90VSHFLILFDWLRQ7KH\DUHWUDQVODWHGDVVKRZQ
LQ7DEOH DGDSWHGIURP>6SLHZDND@ 
7DEOH(QFRGLQJRIRSHUDWRUFKDUDFWHUV
Operator Encoding
= $eq
> $greater
< $less
+ $plus

Java Interoperability | 375

Download at WoweBook.Com
Operator Encoding
- $minus
* $times
/ $div
\ $bslash
| $bar
! $bang
? $qmark
: $colon
% $percent
^ $up
& $amp
@ $at
# $hash
~ $tilde

<RXFDQVHHWKLVDWZRUNLQWKHIROORZLQJFRQWULYHGWUDLWZKHUHHDFKFKDUDFWHULVXVHG
WRGHFODUHDQDEVWUDFWPHWKRGWKDWWDNHVQRDUJXPHQWVDQGUHWXUQVUnit
// code-examples/ToolsLibs/all-op-chars.scala

trait AllOpChars {
def == : Unit // $eq$eq
def > : Unit // $greater
def < : Unit // $less
def + : Unit // $plus
def - : Unit // $minus
def * : Unit // $times
def / : Unit // $div
def \ : Unit // $bslash
def | : Unit // $bar
def ! : Unit // $bang
def ? : Unit // $qmark
def :: : Unit // $colon$colon
def % : Unit // $percent
def ^ : Unit // $up
def & : Unit // $amp
def @@ : Unit // $at$at
def ## : Unit // $hash$hash
def ~ : Unit // $tilde
}

1RWHWKDWZHGRXEOHGXSVRPHRIWKHFKDUDFWHUVWRJHWWKHPWRFRPSLOHDVPHWKRG
QDPHVZKHUHXVLQJVLQJOHFKDUDFWHUVZRXOGKDYHEHHQDPELJXRXV&RPSLOLQJWKLVILOH
DQGGHFRPSLOLQJWKHUHVXOWLQJFODVVILOHZLWKjavap AllOpChars\LHOGVWKHIROORZLQJ-DYD

376 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
LQWHUIDFH :HKDYHUHDUUDQJHGWKHRXWSXWRUGHURIWKHPHWKRGVWRPDWFKWKHRUGHULQ
WKHRULJLQDO6FDODILOH
Compiled from "all-op-chars.scala"
public interface AllOpChars{
public abstract void $eq$eq();
public abstract void $greater();
public abstract void $less();
public abstract void $plus();
public abstract void $minus();
public abstract void $times();
public abstract void $div();
public abstract void $bslash();
public abstract void $bar();
public abstract void $bang();
public abstract void $qmark();
public abstract void $colon$colon();
public abstract void $percent();
public abstract void $up();
public abstract void $amp();
public abstract void $at$at();
public abstract void $hash$hash();
public abstract void $tilde();
}

7RFRQFOXGHLQWHURSHUDELOLW\EHWZHHQ-DYDDQG6FDODZRUNVYHU\ZHOOEXWWKHUHDUHD
IHZWKLQJV\RXPXVWUHPHPEHUZKHQLQYRNLQJ6FDODFRGHIURP-DYD,I\RX¦UHXQFHUWDLQ
DERXWKRZD6FDODLGHQWLILHULVHQFRGHGRUD6FDODPHWKRGLVWUDQVODWHGWRYDOLGE\WH
FRGHXVHjavapWRILQGRXW

Java Library Interoperability


7KLVVHFWLRQVSHFLILFDOO\FRQVLGHUVLQWHURSHUDELOLW\ZLWKVHYHUDOLPSRUWDQW-DYDIUDPH
ZRUNV $VSHFW- WKH 6SULQJ )UDPHZRUN 7HUUDFRWWD DQG +DGRRS %HFDXVH WKH\ DUH
ZLGHO\XVHGLQ£HQWHUSULVH¤DQG,QWHUQHW-DYDDSSOLFDWLRQVVXFFHVVIXOLQWHURSHUDELOLW\
ZLWK6FDODLVLPSRUWDQW

AspectJ
$VSHFW- >$VSHFW-@  LV DQ H[WHQVLRQ RI -DYD WKDW VXSSRUWV DVSHFWRULHQWHG SURJUDP
PLQJ $23 DOVRNQRZQDVDVSHFWRULHQWHGVRIWZDUHGHYHORSPHQW >$26'@ 7KHJRDO
RI$23LVWRHQDEOHV\VWHPLFFKDQJHVRIWKHVDPHNLQGDFURVVPDQ\PRGXOHVZKLOH
DYRLGLQJFRS\LQJDQGSDVWLQJWKHVDPHFRGHRYHUDQGRYHULQWRHDFKORFDWLRQ$YRLGLQJ
WKLVGXSOLFDWLRQQRWRQO\LPSURYHVSURGXFWLYLW\LWJUHDWO\UHGXFHVEXJV
)RUH[DPSOHLI\RXZDQWDOOILHOGFKDQJHVWRDOO£GRPDLQPRGHO¤REMHFWVWREHSHUVLVWHG
DXWRPDWLFDOO\ DIWHU WKH FKDQJHV RFFXU \RX FDQ ZULWH DQ DVSHFW WKDW REVHUYHV WKRVH
FKDQJHVDQGWULJJHUVDSHUVLVWHQFHZULWHDIWHUHDFKFKDQJH

Java Library Interoperability | 377

Download at WoweBook.Com
$VSHFW-VXSSRUWV$23E\SURYLGLQJDSRLQWFXWODQJXDJHIRUVSHFLI\LQJLQDGHFODUDWLYH
ZD\DOOWKH£H[HFXWLRQSRLQWV¤LQDSURJUDPIRUZKLFKDSDUWLFXODUEHKDYLRUPRGLILFD
WLRQ FDOOHGDGYLFH LVUHTXLUHG,Q$VSHFW-SDUODQFHHDFKH[HFXWLRQSRLQWLVFDOOHGD
MRLQ SRLQW DQG D SDUWLFXODU TXHU\ RYHU MRLQ SRLQWV LV D SRLQWFXW +HQFH WKH SRLQWFXW
ODQJXDJHLVDTXHU\ODQJXDJHRIVRUWV)RUDJLYHQSRLQWFXW$VSHFW-LQFRUSRUDWHVWKH
GHVLUHGEHKDYLRUPRGLILFDWLRQVLQWRHDFKMRLQSRLQW0DQXDOLQVHUWLRQRIWKHVHFKDQJHV
LVQRWUHTXLUHG$QDVSHFWHQFDSVXODWHVSRLQWFXWVDQGDGYLFHVPXFKWKHZD\DFODVV
HQFDSVXODWHVPHPEHUILHOGVDQGPHWKRGV
)RUDGHWDLOHGLQWURGXFWLRQWR$VSHFW-ZLWKPDQ\SUDFWLFDOH[DPSOHVUHIHUWR>/DG
GDG@
7KHUHDUHWZRLVVXHVWKDWPXVWEHFRQVLGHUHGZKHQXVLQJ$VSHFW-ZLWK6FDOD7KHILUVW
LVVXHLVKRZWRUHIHUHQFH6FDODH[HFXWLRQSRLQWVXVLQJ$VSHFW-¦VSRLQWFXWODQJXDJHHJ
6FDODW\SHVDQGPHWKRGV7KHVHFRQGLVVXHLVKRZWRLQYRNH6FDODFRGHDVDGYLFH
/HW¦VORRNDWDQDVSHFWWKDWORJVPHWKRGFDOOVWRWKH ComplexFODVVZHXVHGSUHYLRXVO\
LQWKLVFKDSWHU:H¦OODGGDSDFNDJHGHFODUDWLRQWKLVWLPHWRSURYLGHVRPHVFRSH
// code-examples/ToolsLibs/aspectj/complex.scala

package example.aspectj

case class Complex(real: Double, imaginary: Double) {


def +(that: Complex) =
new Complex(real + that.real, imaginary + that.imaginary)
def -(that: Complex) =
new Complex(real - that.real, imaginary - that.imaginary)
}

+HUHLVDQobjectWKDWXVHVComplex
// code-examples/ToolsLibs/aspectj/complex-main.scala

package example.aspectj

object ComplexMain {
def main(args: Array[String]) {
val c1 = Complex(1.0, 2.0)
val c2 = Complex(3.0, 4.0)
val c12 = c1 + c2
println(c12)
}
}

1H[WKHUHLVDQ$VSHFW-DVSHFWWKDWGHILQHVRQHSRLQWFXWIRUWKHFUHDWLRQRI Complex
LQVWDQFHVDQGDQRWKHUSRLQWFXWIRULQYRFDWLRQVRIWKH+PHWKRG

378 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
// code-examples/ToolsLibs/aspectj/LogComplex.aj

package example.aspectj;

public aspect LogComplex {


public pointcut newInstances(double real, double imag):
execution(Complex.new(..)) && args(real, imag);

public pointcut plusInvocations(Complex self, Complex other):


execution(Complex Complex.$plus(Complex)) && this(self) && args(other);

before(double real, double imag): newInstances(real, imag) {


System.out.println("new Complex(" + real + "," + imag + ") called.");
}

before(Complex self, Complex other): plusInvocations(self, other) {


System.out.println("Calling " + self + ".+(" + other + ")");
}

after(Complex self, Complex other) returning(Complex c):


plusInvocations(self, other) {
System.out.println("Complex.+ returned " + c);
}
}

:HZRQ¦WH[SODLQDOOWKHGHWDLOVRI$VSHFW-V\QWD[KHUH6HHWKH$VSHFW-GRFXPHQWDW
>$VSHFW-@DQG>/DGGDG@IRUWKRVHGHWDLOV:H¦OOOLPLWRXUVHOYHVWRD£FRQFHSWXDO¤
RYHUYLHZRIWKLVDVSHFW
7KHILUVWpointcutnewInstancesPDWFKHVRQH[HFXWLRQVRIWKHFRQVWUXFWRUFDOOVXVLQJ
WKHV\QWD[Complex.newWRUHIHUWRWKHFRQVWUXFWRU:HH[SHFWdoubleDUJXPHQWVWRWKH
FRQVWUXFWRUFDOO$VZHVDZSUHYLRXVO\scala.DoubleRFFXUUHQFHVDUHFRQYHUWHGWR-DYD
SULPLWLYHdoublesZKHQJHQHUDWLQJE\WHFRGH7KHargsFODXVH£ELQGV¤WKHYDOXHVRIWKH
DUJXPHQWVSDVVHGLQVRZHFDQUHIHUWRWKHPLQDGYLFH
7KH VHFRQG pointcut plusInvocations PDWFKHV RQ £H[HFXWLRQV¤ RI WKH + PHWKRG
ZKLFKLVDFWXDOO\ $plusLQWKHE\WHFRGH7KHselfDQGotherSDUDPHWHUVDUHERXQGWR
WKHREMHFWRQZKLFKWKH+PHWKRGLVLQYRNHG XVLQJWKHthisFODXVH DQGWKHDUJXPHQW
WRLW XVLQJWKHargsFODXVH UHVSHFWLYHO\
7KHILUVW beforeDGYLFHLVH[HFXWHGIRUWKH newInstancesSRLQWFXWWKDWLVEHIRUHZH
DFWXDOO\HQWHUWKHFRQVWUXFWRU:H£ORJ¤WKHFDOOGLVSOD\LQJWKHDFWXDOUHDODQGLPDJL
QDU\YDOXHVSDVVHGLQ
7KHQH[WbeforeDGYLFHLVH[HFXWHGIRUWKHplusInvocationsSRLQWFXWWKDWLVEHIRUHWKH
+ PHWKRG LV H[HFXWHG :H ORJ WKH YDOXH RI self LH this LQVWDQFH  DQG WKH RWKHU
QXPEHU
)LQDOO\DQ after returningDGYLFHLVDOVRH[HFXWHGIRUWKH plusInvocationsSRLQWFXW
WKDWLVDIWHUWKH +PHWKRGUHWXUQV:HFDSWXUHWKHUHWXUQYDOXHLQWKHYDULDEOH cDQG
ZHORJLW

Java Library Interoperability | 379

Download at WoweBook.Com
,I\RXKDYH$VSHFW-LQVWDOOHGLQDQaspectj-homeGLUHFWRU\\RXFDQFRPSLOHWKLVILOHDV
IROORZV
ajc -classpath .:aspectj-home/lib/aspectjrt.jar:../lib/scala-library.jar \
aspectj/LogComplex.aj

7KLV LV RQH OLQH ZH XVHG WKH \ WR LQGLFDWH D OLQH ZUDS 7R UXQ WKLV FRGH ZLWK WKH
LogComplex DVSHFW ZH XVH ORDGWLPH ZHDYLQJ :H¦OO LQYRNH -DYD ZLWK DQ DJHQW WKDW
£ZHDYHV¤WKHDGYLFHIURPLogComplexLQWRComplex7RXVHORDGWLPHZHDYLQJZHDOVR
QHHGWKHIROORZLQJFRQILJXUDWLRQILOHMETA-INF/aop.xml
<!-- code-examples/ToolsLibs/META-INF/aop.xml -->

<aspectj>
<aspects>
<aspect name="example.aspectj.LogComplex" />
<include within="example.aspectj.*" />
</aspects>

<weaver options="-verbose">
<dump within="example.aspectj.*" beforeandafter="true">
<include within="example.aspectj.*" />
</dump>
</weaver>
</aspectj>

7KH0(7$,1)GLUHFWRU\VKRXOGEHRQWKHFODVVSDWKZH¦OODVVXPHLW¦VLQWKHFXUUHQW
ZRUNLQJGLUHFWRU\ 7KLVILOHWHOOVWKHZHDYHUZKLFKDVSHFWVWRXVH WKHaspectWDJ DQG
ZKLFKFODVVHVWRWDUJHWIRUZHDYLQJ WKHincludeWDJ DQGLWDOVRHQDEOHVYHUERVHRXWSXW
ZKLFKLVXVHIXOIRUGHEXJJLQJSXUSRVHV)LQDOO\ZHFDQUXQWKHDSSOLFDWLRQZLWKWKH
IROORZLQJFRPPDQG
java -classpath .:aspectj-home/lib/aspectjrt.jar:../lib/scala-library.jar \
-javaagent:aspectj-home/lib/aspectjweaver.jar example.aspectj.ComplexMain

<RXJHWVHYHUDOOLQHVRIPHVVDJHVORJJLQJWKHZHDYLQJSURFHVV7KHRXWSXWHQGVZLWK
WKHVHOLQHV
new Complex(1.0,2.0) called.
new Complex(3.0,4.0) called.
Calling Complex(1.0,2.0).+(Complex(3.0,4.0))
new Complex(4.0,6.0) called.
Complex.+ returned Complex(4.0,6.0)
Complex(4.0,6.0)

$OO EXW WKH ODVW OLQH ZHUH RXWSXW E\ LogComplex :H DGGHG WKLV DGGLWLRQDO EHKDYLRU
ZLWKRXWPDQXDOO\LQVHUWLQJWKHVHVWDWHPHQWVLQComplexLWVHOI
5HFDOOZHVDLGWKDWWKHVHFRQGLVVXH\RXPLJKWHQFRXQWHUZKHQXVLQJ$VSHFW-LVKRZ
WRLQYRNH6FDODFRGHIURPDGYLFH,QRXULogComplexDVSHFWWKHVWDWHPHQWVLQVLGHRXU
GLIIHUHQW beforeDQG afterDGYLFHVDUHUHDOO\MXVW-DYDFRGH7KHUHIRUHZHFDQMXVWDV
HDVLO\LQYRNH6FDODFRGHDSSO\LQJWKHVDPHOHVVRQVZHKDYHDOUHDG\OHDUQHGIRULQYRNLQJ
6FDODIURP-DYD

380 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
6FDODWUDLWVDOPRVWUHSODFHDVSHFWV:HVDZLQ&KDSWHUVDQGKRZ\RXFDQFRQVWUXFW
WUDLWVWKDWPRGLI\WKHEHKDYLRURIRWKHUWUDLWVWKHQPL[WKHEHKDYLRUVWRJHWKHUZKHQ
\RXFUHDWHQHZFODVVHVRULQVWDQFHV7KLVSRZHUIXOWHFKQLTXHOHWV\RXLPSOHPHQWDIRUP
RIDVSHFWDGYLFH+RZHYHU6FDODGRHVQ¦WKDYHDSRLQWFXWODQJXDJHOLNH$VSHFW-:KHQ
\RXQHHGWRDIIHFWDVHWRIMRLQSRLQWVWKDWGRQ¦WVKDUHDFRPPRQVXSHUW\SH\RX¦OOQHHG
WKHFDSDELOLWLHVRI$VSHFW-+RZHYHULI\RXILQG\RXUVHOILQWKDWVLWXDWLRQ\RXVKRXOG
FRQVLGHU LI \RX FDQ UHIDFWRU \RXU FRGH WR H[WUDFW D FRPPRQ WUDLW WKDW SURYLGHV WKH
£KRRNV¤\RXQHHGIRUDGYLFHLPSOHPHQWHGXVLQJWUDLWV

The Spring Framework


7KH 6SULQJ )UDPHZRUN VHH >6SULQJ)UDPHZRUN@  LV DQ RSHQ VRXUFH PRGXODU -DYD
HQWHUSULVH IUDPHZRUN WKDW SURYLGHV D £SXUH¤ -DYD $23 $3, LQWHJUDWHG VXSSRUW IRU
$VSHFW- D GHSHQGHQF\ LQMHFWLRQ ',  FRQWDLQHU XQLIRUP DQG ZHOOGHVLJQHG $3,V IRU
LQYRNLQJ D YDULHW\ RI RWKHU -DYD WKLUGSDUW\ $3,V DQG DGGLWLRQDO FRPSRQHQWV IRU
VHFXULW\ZHEGHYHORSPHQWHWF
+HUHZHIRFXVRQGHSHQGHQF\LQMHFWLRQDVLQWHURSHUDELOLW\LVVXHVZLWKWKHRWKHUSDUWV
RIWKH6SULQJ)UDPHZRUNERLOGRZQWRHLWKHU-DYDRU$VSHFW-LVVXHVZKLFKZHFRYHUHG
HDUOLHU
:H GLVFXVVHG WKH FRQFHSW RI ', LQ £'HSHQGHQF\ ,QMHFWLRQ LQ 6FDOD 7KH &DNH 3DW
WHUQ¤RQSDJHZKHUHZHVKRZHGHOHJDQWSDWWHUQVIRULQMHFWLQJGHSHQGHQFLHVXVLQJ
6FDODLWVHOI+RZHYHULI\RXDUHLQDPL[HG-DYD6FDODHQYLURQPHQWLWPLJKWEHQHFHV
VDU\WRXVHD',IUDPHZRUNOLNHWKHRQHSURYLGHGE\6SULQJWRPDQDJHGHSHQGHQFLHV
,Q6SULQJ',GHSHQGHQFLHVDUHVSHFLILHGXVLQJDFRPELQDWLRQRI;0/FRQILJXUDWLRQ
ILOHV DQG VRXUFHFRGH DQQRWDWLRQV 7KH 6SULQJ $3, UHVROYHV WKHVH GHSHQGHQFLHV DV
FODVVHVDUHLQVWDQWLDWHG6SULQJH[SHFWVWKHVHFODVVHVWRIROORZ-DYD%HDQFRQYHQWLRQV
VHH>-DYD%HDQV6SHF@ :HOOGHVLJQHGFODVVHVZLOORQO\GHSHQGRQDEVWUDFWLRQVLH-DYD
LQWHUIDFHVRU6FDODWUDLWVDQGWKHFRQFUHWHLQVWDQFHVVDWLVI\LQJWKRVHGHSHQGHQFLHVZLOO
EHJLYHQWRWKHEHDQWKURXJKFRQVWUXFWRUDUJXPHQWVRUWKURXJK-DYD%HDQVHWWHUPHWK
RGV +HQFH LI \RX XVH 6SULQJ ', ZLWK 6FDOD FODVVHV \RX ZLOO QHHG WR XVH WKH
@scala.reflect.BeanPropertyDQQRWDWLRQZKHQ\RXXVHVHWWHULQMHFWLRQ7KHDQQRWD
WLRQLVQRWQHHGHGZKHQ\RXXVHFRQVWUXFWRULQMHFWLRQ

3UHIHUFRQVWUXFWRULQMHFWLRQZKHQSRVVLEOH1RWRQO\GRHVWKLVFKRLFH
HOLPLQDWHWKHQHHGWRXVHWKH @BeanPropertyDQQRWDWLRQLWOHDYHVHDFK
LQVWDQFHV LQ D NQRZQ JRRG VWDWH ZKHQ WKH FRQVWUXFWLRQ SURFHVV LV
ILQLVKHG

+RZHYHULI\RXLQMHFWGHSHQGHQFLHVLQWR6FDODobjects\RXPXVWXVHVHWWHULQMHFWLRQ
DV\RXKDYHQRZD\WRGHILQHFRQVWUXFWRUSDUDPHWHUVDQG\RXKDYHQRFRQWURORYHUWKH
FRQVWUXFWLRQSURFHVV

Java Library Interoperability | 381

Download at WoweBook.Com
2QHRWKHUSRLQWUHPHPEHUWKDW6SULQJZLOOH[SHFW-DYDFRPSDWLEOHQDPHVVR\RXPXVW
XVHHQFRGHGQDPHVIRUPHWKRGVDQGobjectsDVQHHGHG
+HUHLVDQH[DPSOHWKDWLOOXVWUDWHV£ZLULQJWRJHWKHU¤REMHFWVZLWK6SULQJ
// code-examples/ToolsLibs/spring/object-bean.scala

package example.spring

case class NamedObject(name: String)

trait Factory {
@scala.reflect.BeanProperty
var nameOfFactory = "unknown"

def make(name: String): AnyRef


}

object NamedObjectFactory extends Factory {


def make(name: String) = NamedObject(name)
}

case class FactoryUsingBean(factory: Factory)

7KHFDVHFODVV FactoryUsingBeanLVDVLPSOHW\SHZLWKDGHSHQGHQF\RQD FactoryDE


VWUDFWLRQWKDWZHZDQWWRLQMHFWXVLQJFRQVWUXFWRULQMHFWLRQ
7KHWUDLWFactoryGHILQHVWKHIDFWRU\DEVWUDFWLRQ,WKDVDmakePHWKRGWRFUHDWHLQVWDQFHV
RI VRPH NLQG 7R GHPRQVWUDWH VHWWHU LQMHFWLRQ RQ objects ZH DOVR JLYH LW D nameOf
FactoryILHOG7KLVZLOOGHPRQVWUDWHobjectGHSHQGHQF\LQMHFWLRQEHFDXVHWKHFRQFUHWH
VXEW\SHZHZLOODFWXDOO\XVHNamedObjectFactoryLVDQobject
6FDODUHTXLUHVXVWRLQLWLDOL]HnameOfFactoryZLWKDYDOXHEXWZHZLOOXVH6SULQJWRVHW
WKHUHDOYDOXH:HKDYHWRXVHWKH@BeanPropertyDQQRWDWLRQWRJHQHUDWHWKHsetNameOf
FactoryPHWKRG6SULQJZLOOH[SHFWWRILQG
7KH FRQFUHWH make PHWKRG LQ NamedObjectFactory FUHDWHV D QHZ NamedObject ,W LV D
VLPSOHFDVHFODVVZLWKDnameILHOG
1RWHWKDWQRQHRIWKHVHW\SHVGHSHQGRQWKH6SULQJ$3,<RXFDQFRPSLOHWKLVILOH
ZLWKRXWDQ\6SULQJ-$5ILOHV
1H[WZHGHILQHWKHGHSHQGHQF\£ZLULQJ¤XVLQJDVWDQGDUG6SULQJ;0/FRQILJXUDWLRQ
ILOH
<!-- code-examples/ToolsLibs/spring/scala-spring.xml -->

<beans xmlns=""
xmlns:xsi=""
xsi:schemaLocation="
">

<bean id="factory" class="example.spring.NamedObjectFactory$">


<property name="nameOfFactory" value="Factory for Named Objects" />
</bean>

382 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
<bean id="factoryUsingBean" class="example.spring.FactoryUsingBean">
<constructor-arg ref="factory" />
</bean>
</beans>

:HGHILQHWZR beans2XUIDFWRU\LVJLYHQWKH,' factory7KH£FODVV¤LVDFWXDOO\WKH


object NamedObjectFactory1RWHWKDWZHKDYHWRDSSHQGD $WRWKHHQGRIWKHQDPH
WKHDFWXDOQDPHRIWKHobjectLQWKHE\WHFRGH
7KH property WDJ VHWV WKH YDOXH RI nameOfFactory :H FDQ¦W FRQWURO LQVWDQWLDWLRQ RI
objectsVRZHKDYHWRLQMHFWWKHFRUUHFWGHSHQGHQF\DIWHUFRQVWUXFWLRQFRPSOHWHV
7KH VHFRQG EHDQ LV RXU VLPSOH FactoryUsingBean 6LQFH WKLV LV D class ZH FDQ XVH
FRQVWUXFWRULQMHFWLRQ7KH constructorWDJVSHFLILHVWKDWWKH factoryEHDQLVXVHGWR
VDWLVI\WKHGHSHQGHQF\DWFRQVWUXFWLRQWLPH
)LQDOO\KHUHLVDVFULSWWKDWXVHVWKHVHW\SHVWRGHPRQVWUDWH6SULQJ',ZLWK6FDOD
// code-examples/ToolsLibs/spring/object-bean-script.scala

import example.spring._
import org.springframework.context.support._

val context = new ClassPathXmlApplicationContext("spring/scala-spring.xml");

val bean = context.getBean("factoryUsingBean").asInstanceOf[FactoryUsingBean]


println("Factory Name: " + bean.factory.nameOfFactory)

val obj = bean.factory.make("Dean Wampler")


println("Object: " + obj)

:HFUHDWHDQLQVWDQFHRI ClassPathXmlApplicationContextVSHFLI\LQJRXU;0/ILOH
7KLVFRQWH[WREMHFWLVRXUJDWHZD\WRWKH',FRQWDLQHU:HDVNLWIRURXUfactoryUsing
Bean:HKDYHWRFDVWWKHUHWXUQHG AnyRef LH-DYD Object WRWKHFRUUHFWW\SH:H
SULQWRXWWKHIDFWRU\¦VQDPHWRVHHLILWLVFRUUHFW
1H[WZHDVNWKHEHDQ¦VIDFWRU\WRPDNH£VRPHWKLQJ¤ZLWKWKHVWULQJ"Dean Wampler"
:KHQZHSULQWWKHUHWXUQHGREMHFWLWVKRXOGEHDNamedObject
,I\RXKDYH6SULQJLQVWDOOHGLQDspring-homeGLUHFWRU\\RXFDQUXQWKLVVFULSWZLWKWKH
IROORZLQJFRPPDQG
scala -cp \
spring-home/dist/spring.jar:spring-home/.../commons-logging.jar:. \
spring/object-bean-script.scala

7KHFXUUHQWZRUNLQJGLUHFWRU\£¤LVQHHGHGLQWKHFODVVSDWKWRILQGWKH;0/ILOH
7KHUHDUHPDQ\OLQHVRIORJJLQJRXWSXW7KHODVWWZROLQHVDUHZKDWZHFDUHDERXW
...
Factory Name: Factory for Named Objects
Object: NamedObject(Dean Wampler)

Java Library Interoperability | 383

Download at WoweBook.Com
7KLVH[DPSOHUHTXLUHGDQXPEHURIILOHVDQGFRQILJXUDWLRQGHWDLOVWRJHWZRUNLQJ)RU
DPRGHUDWHO\ODUJH-DYDDSSOLFDWLRQWKHHIIRUWLVMXVWLILHG+RZHYHU6FDODJLYHV\RXQHZ
DQGVLPSOHUZD\VWRLPSOHPHQWGHSHQGHQF\LQMHFWLRQLQ6FDODFRGHZLWKRXWFRQILJX
UDWLRQILOHVDQGD',FRQWDLQHU

Terracotta
7HUUDFRWWD VHH>7HUUDFRWWD@ LVDQRSHQVRXUFHFOXVWHULQJSURGXFWWKDWGLVWULEXWHVDQ
DSSOLFDWLRQRYHUVHYHUDOVHUYHUVE\FOXVWHULQJ-90VXSRQZKLFKWKHDSSOLFDWLRQH[H
FXWHV)RUHIILFLHQF\QRWDOORIWKHDSSOLFDWLRQ¦VKHDSREMHFWVDUHGLVWULEXWHG,QVWHDG
WKH SURJUDPPHU VSHFLILHV ZKLFK GDWD VWUXFWXUHV WR GLVWULEXWH WKURXJK FRQILJXUDWLRQ
ILOHV$EHQHILWRI7HUUDFRWWDLVWKDWWKHDSSOLFDWLRQGRHVQRWUHTXLUHFRGHFKDQJHVWR
VXSSRUWWKLVFOXVWHULQJ DWOHDVWLQSULQFLSOHVRPHOLPLWHGFXVWRPL]DWLRQFDQEHXVHIXO
IRUSHUIRUPDQFHUHDVRQV ,QVWHDGWKHE\WHFRGHLVLQVWUXPHQWHGWRSURYLGHWKHFOXV
WHULQJ7HUUDFRWWDLVDQDOWHUQDWLYHWRGLVWULEXWHGFDFKHVWKDWUHTXLUHFRGHFKDQJHV
>%RQpUD@SURYLGHVDGHWDLOHGZULWHXSRIKRZWRXVH7HUUDFRWWDZLWK6FDOD$FWRUV
$6FDODVSHFLILF7HUUDFRWWD,QWHJUDWLRQ0RGXOH 7,0 PXVWEHLQVWDOOHG:KHQFRQ
ILJXULQJZKLFKREMHFWVWRGLVWULEXWH\RXKDYHWRXVHWKHHQFRGHGQDPHVIRUFRPSDQLRQ
REMHFWVPHWKRGQDPHVHWFDVWKH\H[LVWDWWKHE\WHFRGHOHYHO:HGLVFXVVHGWKHVH
HQFRGLQJVLQ£6FDOD1DPHVLQ-DYD&RGH¤RQSDJH)LQDOO\\RXKDYHWRDGGVRPH
PRUHSDUDPHWHUVWRWKHjavaLQYRFDWLRQFRPPDQGLQVLGHWKHscalaVFULSW2WKHUZLVH
FOXVWHULQJ 6FDOD DSSOLFDWLRQV ZLWK 7HUUDFRWWD ZRUNV MXVW OLNH LW GRHV IRU -DYD
DSSOLFDWLRQV

Hadoop
0DS5HGXFHLVDGLYLGHDQGFRQTXHUSURJUDPPLQJPRGHOIRUSURFHVVLQJODUJHGDWDVHWV
LQSDUDOOHO,QWKH£PDS¤SKDVHDGDWDVHWLVGLYLGHGLQWR1VXEVHWVRIDSSUR[LPDWHO\
HTXDOVL]HZKHUH1LVFKRVHQWRRSWLPL]HWKHDPRXQWRIZRUNWKDWFDQEHGRQHLQ
SDUDOOHO)RUH[DPSOH1PLJKWEHFORVHWRWKHWRWDOQXPEHURISURFHVVRUFRUHVDYDLODEOH
$IHZFRUHVPLJKWEHOHIWLGOHDV£EDFNXSV¤RUIRUGRLQJRWKHUSURFHVVLQJ 7KHGHVLUHG
FRPSXWDWLRQLVSHUIRUPHGRQHDFKVXEVHW7KH£UHGXFH¤SKDVHFRPELQHVWKHUHVXOWVRI
WKHVXEVHWFDOFXODWLRQVLQWRDILQDOUHVXOW
1RWH WKDW PDSSLQJ DQG UHGXFLQJ DUH HVVHQWLDOO\ IXQFWLRQDO RSHUDWLRQV 7KHUHIRUH D
IXQFWLRQDOODQJXDJHOLNH6FDODLVLGHDOO\VXLWHGIRUZULWLQJ0DS5HGXFHDSSOLFDWLRQV

384 | Chapter 14:—Scala Tools, Libraries, and IDE Support

Download at WoweBook.Com
0DS5HGXFHIUDPHZRUNVSURYLGHWRROVIRUPDSSLQJDQGUHGXFLQJGDWDVHWVPDQDJLQJ
DOOSKDVHVRIWKHFRPSXWDWLRQLQFOXGLQJWKHSURFHVVLQJQRGHVUHVWDUWLQJRSHUDWLRQV
WKDWIDLOIRUVRPHUHDVRQHWF7KHXVHURID0DS5HGXFHIUDPHZRUNRQO\KDVWRZULWH
WKHDOJRULWKPVIRUPDSSLQJ VXEGLYLGLQJ WKHLQSXWGDWDWKHFRPSXWDWLRQVZLWKWKH
GDWDVXEVHWVDQGUHGXFLQJWKHUHVXOWV6HH>0DS5HGXFH7XWRULDO@IRUDVXFFLQFWRYHU
YLHZDQG>0DS5HGXFH@IRUDGHVFULSWLRQRI*RRJOH¦V0DS5HGXFHIUDPHZRUN7KHQDPH
RIWKH*RRJOHIUDPHZRUNKDVEHFRPHDGHIDFWRVWDQGDUGIRUWKHVHIUDPHZRUNV
+DGRRS VHH>+DGRRS@ LVDQRSHQVRXUFH0DS5HGXFHIUDPHZRUNFUHDWHGDQGPDLQ
WDLQHGE\<DKRR7KHUHDUHWZR6FDODZUDSSHUVDURXQGWKH+DGRRS$3,6+DGRRS VHH
>6+DGRRS@ DQG605 VHH>605D@DQG >605E@ %RWKH[DPSOHVGHPRQVWUDWHWKHJUHDW
UHGXFWLRQ LQ FRGH VL]H ZKHQ XVLQJ 6FDOD >605D@ DWWULEXWHV WKLV FRGH UHGXFWLRQ WR
6FDOD¦VVXSSRUWIRUKLJKHURUGHUDQGDQRQ\PRXVIXQFWLRQVLWVVRSKLVWLFDWHGW\SHV\V
WHPDQGW\SHLQIHUHQFHDQGWKHDELOLW\RIforFRPSUHKHQVLRQVWRJHQHUDWHPDSVLQDQ
HOHJDQWDQGVXFFLQFWZD\

Recap and What’s Next


7KLVFKDSWHUILOOHGLQWKHGHWDLOVRIWKH6FDODFRPPDQGOLQHWRROVWKDW\RXZLOOXVHHYHU\
GD\:HDOVRVXUYH\HGWKHDYDLODEOHVXSSRUWIRU6FDODLQYDULRXVWH[WHGLWRUVDQG,'(V
:HGLVFXVVHGDQXPEHURILPSRUWDQWOLEUDULHVVXFKDVWHVWLQJ$3,V)LQDOO\ZHGLV
FXVVHGLQWHURSHUDELOLW\EHWZHHQ6FDODDQGRWKHU-90ODQJXDJHVDQGOLEUDULHV
7KLVFRPSOHWHVRXUVXUYH\RIWKHZRUOGRI6FDODSURJUDPPLQJ7KHQH[WFKDSWHULVD
OLVWRIUHIHUHQFHVIRUIXUWKHUH[SORUDWLRQIROORZHGE\DJORVVDU\RIWHUPVWKDWZHKDYH
XVHGWKURXJKRXWWKHERRN

Recap and What’s Next | 385

Download at WoweBook.Com
Download at WoweBook.Com
APPENDIX
References

>$EHOVRQ@+DUROG$EHOVRQ*HUDOG-D\6XVVPDQDQG-XOLH6XVVPDQ6WUXFWXUHDQG
,QWHUSUHWDWLRQRI&RPSXWHU3URJUDPV7KH0,73UHVV
>$JKD@*XO$JKD$FWRUV7KH0,73UHVV
>$NND@$NND5(67IXO'LVWULEXWHG3HUVLVWHQW7UDQVDFWLRQDO$FWRUVKWWSDNNDVRXUFH
RUJ
>$QW@7KH$SDFKH$QW3URMHFWKWWSDQWDSDFKHRUJ
>$QWOU@$QWOUKWWSZZZDQWOURUJ
>$26'@$VSHFW2ULHQWHG6RIWZDUH'HYHORSPHQWKWWSDRVGQHW
>$VSHFW-@7KH$VSHFW-3URMHFWKWWSZZZHFOLSVHRUJDVSHFWM
>%''@%HKDYLRU'ULYHQ'HYHORSPHQWKWWSEHKDYLRXUGULYHQRUJ
>%ORFK@-RVKXD%ORFK(IIHFWLYH-DYD 6HFRQG(GLWLRQ $GGLVRQ:HVOH\
>%RQpUD@-RQDV%RQpU&OXVWHULQJ6FDOD$FWRUVZLWK7HUUDFRWWDKWWSMRQDVERQHU
FRPFOXVWHULQJVFDODDFWRUVZLWKWHUUDFRWWDKWPO
>%RQpUE@-RQDV%RQpU5HDO:RUOG6FDOD'HSHQGHQF\,QMHFWLRQ ', KWWSMRQDVE
RQHUFRPUHDOZRUOGVFDODGHSHQGHQF\LQMHFWLRQGLKWPO
>%UXFH@.LP%UXFH0DUWLQ2GHUVN\DQG3KLOLS:DGOHU$6WDWLFDOO\6DIH$OWHU
QDWLYH WR 9LUWXDO 7\SHV 3URF (&223 ¦ ( -XO (G  /1&6  SS ¡
6SULQJHU9HUODJ
>%XLOGU@%XLOGUKWWSEXLOGUDSDFKHRUJ
>&RQWUDFW-@&RQWUDFW-'HVLJQE\&RQWUDFWIRU-DYDKWWSFRQWUDFWMRUJ
>&XFXPEHU@&XFXPEHU0DNLQJ%'')XQKWWSFXNHVLQIR
>'HVLJQ%\&RQWUDFW@%XLOGLQJEXJIUHH22VRIWZDUH$QLQWURGXFWLRQWR'HVLJQE\&RQ
WUDFWŒKWWSDUFKLYHHLIIHOFRPGRFPDQXDOVWHFKQRORJ\FRQWUDFW

387

Download at WoweBook.Com
>'HXUVHQ@$ULHYDQ'HXUVHQ3DXO.OLQWDQG-RRVW9LVVHU'RPDLQ6SHFLILF/DQJXDJHV
$Q$QQRWDWHG%LEOLRJUDSK\KWWSKRPHSDJHVFZLQOaDULHSDSHUVGVOELE
>(%1)@ ([WHQGHG %DFNXV1DXU )RUP KWWSHQZLNLSHGLDRUJZLNL([WHQGHGB%DFNXV¡
1DXUB)RUP
>(LIIHO@(LIIHO6RIWZDUHKWWSHLIIHOFRP
>)RUG@%U\DQ)RUG7KH3DFNUDW3DUVLQJDQG3DUVLQJ([SUHVVLRQ*UDPPDUV3DJHKWWS
SGRVFVDLOPLWHGXaEDIRUGSDFNUDW
>)RUG@ 1HDO )RUG $GYDQFHG '6/V LQ 5XE\ KWWSJLWKXEFRPQHDOIRUGSUHVHQWD
WLRQVWUHHPDVWHU
>)RZOHU@0DUWLQ)RZOHU'RPDLQ6SHFLILF/DQJXDJHV IRUWKFRPLQJ KWWSPDUWLQ
IRZOHUFRPGVOZLS
>)XQFWLRQDO-DYD@)XQFWLRQDO-DYDKWWSIXQFWLRQDOMDYDRUJ
>*KRVKD@'HEDVLVK*KRVK([WHUQDO'6/VPDGHHDV\ZLWK6FDOD3DUVHU&RPELQD
WRUVKWWSGHEDVLVKJEORJVSRWFRPH[WHUQDOGVOVPDGHHDV\ZLWKVFDODKWPO
>*KRVKE@'HEDVLVK*KRVK'HVLJQLQJ,QWHUQDO'6/VLQ6FDODKWWSGHEDVLVKJEORJ
VSRWFRPGHVLJQLQJLQWHUQDOGVOVLQVFDODKWPO
>*2)@(ULFK*DPPD5LFKDUG+HOP5DOSK-RKQVRQDQG-RKQ9OLVVLGHV £*DQJ
RI)RXU¤ 'HVLJQ3DWWHUQV(OHPHQWVRI5HXVDEOH2EMHFW2ULHQWHG6RIWZDUH$GGLVRQ
:HVOH\
>*XLFH@*XLFHKWWSFRGHJRRJOHFRPSJRRJOHJXLFH
>+DGRRS@+DGRRSKWWSKDGRRSDSDFKHRUJ
>+DOOHU@ 3KLOLSS +DOOHU DQG 0DUWLQ 2GHUVN\ $FWRUV 7KDW 8QLI\ 7KUHDGV DQG
(YHQWVKWWSODPSHSIOFKaSKDOOHUGRFKDOOHUFRRUGSGI
>+HZLWW@ &DUO +HZLWW 3HWHU %LVKRS DQG 5LFKDUG 6WHLJHU $ 8QLYHUVDO 0RGXODU
$FWRU)RUPDOLVPIRU$UWLILFLDO,QWHOOLJHQFHKWWSGOLLLLWDFLQLMFDL,-&$,3')%
SGI
>+RDUH@7RQ\+RDUH1XOO5HIHUHQFHV7KH%LOOLRQ'ROODU0LVWDNHKWWSTFRQORQ
GRQFRPORQGRQVSHDNHU7RQ\+RDUH
>+RIHU@&KULVWLDQ+RIHU.ODXV2VWHUPDQQ7LOOPDQQ5HQGHODQG$GULDDQ0RRUV
3RO\PRUSKLF(PEHGGLQJRI'6/V*3&(¦2FWREHU¡1DVKYLOOH7HQQHV
VHHKWWSZZZGDLPLDXGNaNRSDSHUVJSFHBKRIHUSGI
>+773@ +\SHUWH[W 7UDQVIHU 3URWRFRO ¢ +773 KWWSZZZZRUJ3URWRFROV
UIFUIFKWPO
>+XQW@$QGUHZ+XQWDQG'DYH7KRPDV7KH3UDJPDWLF3URJUDPPHU$GGLVRQ
:HVOH\
>-$'@-$YD'HFRPSLOHU -$' KWWSZZZYDUDQHFNDVFRPMDG

388 | Appendix:—References

Download at WoweBook.Com
>-DYD$3,@-DYD3ODWIRUP6($3,KWWSMDYDVXQFRPMDYDVHGRFVDSL
>-DYD%HDQV6SHF@ -DYD%HDQV 6SHFLILFDWLRQ KWWSMDYDVXQFRPMDYDVHWHFKQRORJLHVGHVN
WRSMDYDEHDQVGRFVVSHFKWPO
>-3$6FDOD@8VLQJ-3$ZLWK6FDODKWWSZZZKDUVGHMSDZLWKVFDODKWPO
>-5XE\@-5XE\KWWSMUXE\FRGHKDXVRUJ
>-8QLW@-8QLWKWWSMXQLWRUJ
>/DGGDG@5DPQLYDV/DGGDG$VSHFW-LQ$FWLRQ 6HFRQG(GLWLRQ 0DQQLQJ3UHVV

>0DLOVORW@0DLOVORWKWWSJLWKXEFRPVWHYHMPDLOVORW
>0DS5HGXFH@0DS5HGXFHKWWSODEVJRRJOHFRPSDSHUVPDSUHGXFHKWPO
>0DS5HGXFH7XWRULDO@ ,QWURGXFWLRQ WR 3DUDOOHO 3URJUDPPLQJ DQG 0DS5HGXFH KWWS
FRGHJRRJOHFRPHGXSDUDOOHOPDSUHGXFHWXWRULDOKWPO
>0DUWLQ@5REHUW&0DUWLQ$JLOH6RIWZDUH'HYHORSPHQW3ULQFLSOHV3DWWHUQVDQG
3UDFWLFHV3UHQWLFH+DOO
>0DYHQ@7KH$SDFKH0DYHQ3URMHFWKWWSPDYHQDSDFKHRUJ
>0F%HDWK@-LP0F%HDWK6FDOD6\QWD[3ULPHUKWWSMLPPFEHDWKEORJVSRWFRP
VFDODV\QWD[SULPHUKWPO
>0F,YHU@'DYLG50DF,YHU6FDODWULYLDRIWKHGD\7UDLWVFDQH[WHQGFODVVHVKWWS
ZZZGUPDFLYHUFRPVFDODWULYLDRIWKHGD\WUDLWVFDQH[WHQGFODVVHV
>0H\HU@ %HUWUDQG 0H\HU 2EMHFW2ULHQWHG 6RIWZDUH &RQVWUXFWLRQ 6HFRQG (GL
WLRQ 3UHQWLFH+DOO
>0,1$@$SDFKH0,1$KWWSPLQDDSDFKHRUJ
>0RQH\,Q-DYD@7KRPDV3DXO:RUNLQJZLWK0RQH\LQ-DYDKWWSZZZMDYDUDQFKFRP
MRXUQDO0RQH\,Q-DYDKWPO
>1DIWDOLQ@ 0DXULFH 1DIWDOLQ DQG 3KLOLS :DGOHU -DYD *HQHULFV DQG &ROOHFWLRQV
2¦5HLOO\0HGLD
>1DJJDWL@1DJJDWLKWWSJLWKXEFRPUREH\QDJJDWL
>2GHUVN\@0DUWLQ2GHUVN\DQG0DWWKLDV=HQJHU 6FDODEOH&RPSRQHQW$EVWUDF
WLRQV2236/$¦2FWREHU¡6DQ'LHJR&DOLIRUQLD86$
>2GHUVN\@ 0DUWLQ 2GHUVN\ 3LPS 0\ /LEUDU\ KWWSZZZDUWLPDFRPZHEORJV
YLHZSRVWMVS"WKUHDG 
>2GHUVN\@0DUWLQ2GHUVN\/H[6SRRQDQG%LOO9HQQHUV3URJUDPPLQJLQ6FDOD
$UWLPD3UHVV
>2GHUVN\@0DUWLQ2GHUVN\/H[6SRRQDQG%LOO9HQQHUV+RZWR:ULWHDQ(TXDOLW\
0HWKRGLQ-DYDKWWSZZZDUWLPDFRPOHMDYDDUWLFOHVHTXDOLW\KWPO

References | 389

Download at WoweBook.Com
>2NDVDNL@&KULV2NDVDNL3XUHO\)XQFWLRQDO'DWD6WUXFWXUHV&DPEULGJH8QLYHU
VLW\3UHVV
>2UWL]@-RUJH2UWL])XQZLWK3URMHFW(XOHUDQG6FDODKWWSVFDODEORJVRUJ
SURMHFWHXOHUIXQLQVFDODKWPO
>2UWL]@-RUJH2UWL]0DQLIHVWV5HLILHG7\SHVKWWSVFDODEORJVRUJPDQL
IHVWVUHLILHGW\SHVKWPO
>26XOOLYDQ@%U\DQ2¦6XOOLYDQ-RKQ*RHU]HQDQG'RQ6WHZDUG5HDO:RUOG+DV
NHOO2¦5HLOO\0HGLD
>3(*@ 3DUVLQJ ([SUHVVLRQ *UDPPDU KWWSHQZLNLSHGLDRUJZLNL3DUVLQJBH[SUHVVLRQ
BJUDPPDU
>3LHUFH@%HQMDPLQ&3LHUFH7\SHVDQG3URJUDPPLQJ/DQJXDJHV7KH0,73UHVV

>3ROODN@'DYLG3ROODN7KH6FDOD2SWLRQFODVVDQGKRZOLIWXVHVLWKWWSEORJORVWODNH
RUJLQGH[SKS"DUFKLYHV7KH6FDOD2SWLRQFODVVDQGKRZOLIWXVHVLWKWPO
>4XLFN&KHFN@ 4XLFN&KHFN $XWRPDWHG 6SHFLILFDWLRQ%DVHG 7HVWLQJ KWWSZZZFV
FKDOPHUVVHaUMPK4XLFN&KHFN
>5DEKL@)HWKL5DEKLDQG*X\/DSDOPH$OJRULWKPV$)XQFWLRQDO3URJUDPPLQJ
$SSURDFK$GGLVRQ:HVOH\
>56SHF@56SHFKWWSUVSHFLQIR
>6%7@6LPSOH%XLOG7RROKWWSFRGHJRRJOHFRPSVLPSOHEXLOGWRRO
>6FDOD@7KH6FDOD3URJUDPPLQJ/DQJXDJHKWWSZZZVFDODODQJRUJ
>6FDOD$3,@7KH6FDOD/LEUDU\KWWSZZZVFDODODQJRUJGRFXILOHVDSLLQGH[KWPO
>6FDOD&KHFN7RRO@6FDOD&KHFNKWWSFRGHJRRJOHFRPSVFDODFKHFN
>6FDOD6SHF@ 7KH 6FDOD /DQJXDJH 6SHFLILFDWLRQ KWWSZZZVFDODODQJRUJVLWHVGH
IDXOWILOHVOLQX[VRIWBDUFKLYHVGRFXILOHV6FDOD5HIHUHQFHSGI
>6FDOD6SHFV7RRO@6SHFVKWWSFRGHJRRJOHFRPSVSHFV
>6FDOD7HVW7RRO@6FDOD7HVWKWWSZZZDUWLPDFRPVFDODWHVW
>6FDOD7LSV@6FDOD7LSV%ORJKWWSVFDODWLSVWXPEOUFRP
>6FDOD7RROV@6FDOD7RROVKWWSZZZVFDODWRROVRUJ
>6FDOD:LNL@6FDOD:LNLKWWSVFDODV\JQHFDFRP
>6FDOD:LNL3DWWHUQV@ 6FDOD :LNL 6FDOD 'HVLJQ 3DWWHUQV KWWSVFDODV\JQHFDFRPSDW
WHUQVVWDUW
>6FDOD=@6FDOD]KWWSFRGHJRRJOHFRPSVFDOD]

390 | Appendix:—References

Download at WoweBook.Com
>6+DGRRS@-RQKQQ\:HVOOH\ VLF 6+DGRRS:KDWLV6FDODDQG+DGRRS"KWWSMRQKQQ\
ZHVOOH\EORJVSRWFRPVKDGRRSKWPO
>6OHHSLQJ%DUEHU3UREOHP@ 6OHHSLQJ EDUEHU SUREOHP KWWSHQZLNLSHGLDRUJZLNL6OHHS
LQJBEDUEHUBSUREOHP
>605D@'DYLG+DOO$6FDODEOH/DQJXDJHDQGD6FDODEOH)UDPHZRUNKWWSVFDODEORJV
RUJVFDODEOHODQJXDJHDQGVFDODEOHKWPO
>605E@6FDOD0DS5HGXFHKWWSJLWKXEFRPGOZKVPU
>6PLWKD@(LVKD\6PLWK%HZDUHRI6FDOD¦V7\SH,QIHUHQFHKWWSZZZHLVKD\FRP
EHZDUHRIVFDODVW\SHLQIHUHQFHKWPO
>6PLWKE@(LVKD\6PLWK8QH[SHFWHGUHSHDWHGH[HFXWLRQLQ6FDODKWWSZZZHLVKD\
FRPXQH[SHFWHGUHSHDWHGH[HFXWLRQLQVFDODKWPO
>6SLHZDN@'DQLHO6SLHZDN:KDWLV+LQGOH\0LOQHU" DQGZK\LVLWFRRO" KWWS
ZZZFRGHFRPPLWFRPEORJVFDODZKDWLVKLQGOH\PLOQHUDQGZK\LVLWFRRO
>6SLHZDND@'DQLHO6SLHZDN,QWHURS%HWZHHQ-DYDDQG6FDODKWWSZZZFRGHFRP
PLWFRPEORJMDYDLQWHURSEHWZHHQMDYDDQGVFDOD
>6SLHZDNE@'DQLHO6SLHZDN7KH0DJLF%HKLQG3DUVHU&RPELQDWRUVKWWSZZZ
FRGHFRPPLWFRPEORJVFDODWKHPDJLFEHKLQGSDUVHUFRPELQDWRUV
>6SLHZDNF@'DQLHO6SLHZDN3UDFWLFDOO\)XQFWLRQDOWDONDWWKH&KLFDJR$UHD6FDOD
(QWKXVLDVWV0D\
>6SULQJ)UDPHZRUN@7KH6SULQJ)UDPHZRUNKWWSVSULQJIUDPHZRUNRUJ
>6;5@$6FDODVRXUFHFRGHEURZVHUKWWSJLWKXEFRPKDUUDKEURZVHWUHHPDVWHU
>6]\SHUVNL@ &OHPHQV 6]\SHUVNL &RPSRQHQW 6RIWZDUH %H\RQG 2EMHFW2ULHQWHG
3URJUDPPLQJ$GGLVRQ:HVOH\/RQJPDQ/LPLWHG
>7''@ 7HVW'ULYHQ 'HYHORSPHQW KWWSHQZLNLSHGLDRUJZLNL7HVWGULYHQBGHYHORS
PHQW
>7HUUDFRWWD@7HUUDFRWWDKWWSWHUUDFRWWDRUJ
>7HVW1*@7HVW1*KWWSWHVWQJRUJ
>7XUEDN@)UDQNO\Q7XUEDN'DYLG*LIIRUGDQG0DUN$6KHOGRQ'HVLJQ&RQFHSWV
RI3URJUDPPLQJ/DQJXDJHV7KH0,73UHVV
>7\SH,QIHUHQFH@7\SHLQIHUHQFHKWWSHQZLNLSHGLDRUJZLNL7\SHBLQIHUHQFH
>9DQ5R\@ 3HWHU 9DQ 5R\ DQG 6HLI +DULGL &RQFHSWV 7HFKQLTXHV DQG 0RGHOV RI
&RPSXWHU3URJUDPPLQJ7KH0,73UHVV
>:DPSOHU@ 'HDQ :DPSOHU 7UDLWV YV $VSHFWV LQ 6FDOD KWWSEORJREMHFWPHQWRU
FRPDUWLFOHVWUDLWVYVDVSHFWVLQVFDOD

References | 391

Download at WoweBook.Com
>:LUIV%URFN@5HEHFFD:LUIV%URFNDQG$ODQ0F.HDQ2EMHFW'HVLJQ5ROHV5H
VSRQVLELOLWLHVDQG&ROODERUDWLRQV3HDUVRQ(GXFDWLRQ

392 | Appendix:—References

Download at WoweBook.Com
Glossary

$tag Actor Model of Concurrency


$PHWKRGGHFODUHGE\WKHScalaObjectWUDLW $ FRQFXUUHQF\ PRGHO ZKHUH DXWRQRPRXV
DQGXVHGLQWHUQDOO\E\6FDOD,WWDNHVQRDU $FWRUV FRRUGLQDWH ZRUN E\ H[FKDQJLQJ
JXPHQWV DQG UHWXUQV DQ LQWHJHU ,W LV FXU PHVVDJHV$Q$FWRU¦VPHVVDJHVDUHVWRUHGLQ
UHQWO\ XVHG WR RSWLPL]H SDWWHUQ PDWFKLQJ DPDLOER[XQWLOWKH$FWRUSURFHVVHVWKHP
EXWLWPD\EHUHPRYHGLQDIXWXUHUHOHDVHRI
6FDOD:KLOHQRUPDOO\LQYLVLEOHWR6FDODFRGH
Annotated Type
LW LV JHQHUDWHG DXWRPDWLFDOO\ E\ WKH FRP $Q\W\SHWKDWKDVRQHRUPRUH@DQQRWDWLRQV
SLOHU  -DYD FRGH WKDW H[WHQGV VRPH 6FDOD DSSOLHGWRLW
WUDLWV DQG FODVVHV PD\ QHHG WR LPSOHPHQW Annotation
WKLVPHWKRG $ZD\RIDWWDFKLQJ£PHWDGDWD¤WRDGHFODUD
Abstraction WLRQWKDWFDQEHH[SORLWHGE\WKHFRPSLOHU
7KHRXWZDUGO\YLVLEOHVWDWHVWDWHWUDQVIRU DQGRWKHUWRROVIRUFRGHJHQHUDWLRQYHULIL
PDWLRQVDQGRWKHURSHUDWLRQVVXSSRUWHGE\ FDWLRQ DQG YDOLGDWLRQ HWF ,Q 6FDOD DQG
DW\SH7KLVLVVHSDUDWHIURPWKHHQFDSVXOD -DYD DQDQQRWDWLRQLVDFODVV:KHQXVHG
WHGLPSOHPHQWDWLRQ ILHOGVDQGPHWKRGV RI LWLVSUHIL[HGZLWKWKH@FKDUDFWHU
WKH DEVWUDFWLRQ 6FDOD WUDLWV DQG DEVWUDFW $Q\H[SOLFLWW\SHGHFODUDWLRQVDUHDOVRFDOOHG
FODVVHVDUHRIWHQXVHGWRGHILQHDEVWUDFWLRQV W\SHDQQRWDWLRQV
DQG RSWLRQDOO\ LPSOHPHQW WKHP &RQFUHWH
2QHRUPRUHDGGLWLRQVWRDW\SHGHFODUDWLRQ
W\SHVSURYLGHFRPSOHWHLPSOHPHQWDWLRQV
WKDW VSHFLI\ EHKDYLRUV OLNH YDULDQFH XQGHU
Abstract Type LQKHULWDQFHERXQGVDQGYLHZV
L $FODVVRUWUDLWZLWKRQHRUPRUHPHWK Application
RGV ILHOGV RU W\SHV GHFODUHG EXW ,Q6FDODDQ\objectZLWKDmainURXWLQHWKDW
XQGHILQHG$EVWUDFWW\SHVFDQ¦WEHLQ LVLQYRNHGE\WKH-90RU1(7&/5DWWKH
VWDQWLDWHG &RQWUDVW ZLWK FRQFUHWH VWDUWRIDQHZSURFHVV
W\SHV
Arity
LL $ type GHFODUDWLRQ ZLWKLQ DQ FODVV RU 7KHQXPEHURIDUJXPHQWVWRDIXQFWLRQ
WUDLWWKDWLVDEVWUDFW
Aspect-Oriented Programming
Actor 6RPHWLPHV FDOOHG DVSHFWRULHQWHG VRIWZDUH
$QDXWRQRPRXVVHQGHUDQGUHFHLYHURIPHV GHYHORSPHQW $QDSSURDFKWRFURVVFXWWLQJ
VDJHVLQWKH$FWRUPRGHORIFRQFXUUHQF\ FRQFHUQVZKHUHWKHFRQFHUQVDUHGHVLJQHG
DQGLPSOHPHQWHGLQD£PRGXODU¤ZD\ WKDW
LVZLWKDSSURSULDWHHQFDSVXODWLRQODFNRI

393

Download at WoweBook.Com
AspectJ

GXSOLFDWLRQ HWF  WKHQ LQWHJUDWHG LQWR DOO FDWLRQDQGOHVVOLNHDWHVWRIWKHFRGH¦VFRQ


WKHUHOHYDQWH[HFXWLRQSRLQWVLQDVXFFLQFW IRUPDQFHWRWKHUHTXLUHPHQWV+RZHYHUWKH
DQGUREXVWZD\HJWKURXJKGHFODUDWLYHRU VSHFLILFDWLRQIRUPDWLVVWLOOH[HFXWDEOHDQGLW
SURJUDPPDWLFPHDQV,Q$23WHUPVWKHH[ VWLOO SURYLGHV WKH YHULILFDWLRQ YDOLGDWLRQ
HFXWLRQSRLQWVDUHFDOOHGMRLQSRLQWVDSDU DQGUHJUHVVLRQWHVWLQJVHUYLFHWKDW7''WHVWV
WLFXODUVHWRIWKHPLVFDOOHGDSRLQWFXWDQG SURYLGH
WKH QHZ EHKDYLRU WKDW LV H[HFXWHG EHIRUH
DIWHURU£DURXQG¤DMRLQSRLQWLVFDOOHGDG
Bound Variable
YLFH$VSHFW-LVWKHEHVWNQRZQ$23WRRONLW $YDULDEOHWKDWLVGHFODUHGDVDQDUJXPHQWWR
6FDODWUDLWVFDQEHXVHGWRLPSOHPHQWVRPH D IXQFWLRQ OLWHUDO ,W LV £ERXQG¤ WR D YDOXH
DVSHFWOLNHIXQFWLRQDOLW\ ZKHQWKHFORVXUHFUHDWHGIURPWKHIXQFWLRQ
OLWHUDOLVLQYRNHG
AspectJ
$QH[WHQVLRQRI-DYDWKDWVXSSRUWV$VSHFW
By-Name Parameter
2ULHQWHG3URJUDPPLQJ$VSHFW- >$VSHFW-@ $E\QDPHSDUDPHWHUORRNVOLNHDIXQFWLRQ
VXSSRUWVWZRIRUPVRIV\QWD[DQH[WHQGHG YDOXHWKDWWDNHVQRSDUDPHWHUVEXWUDWKHU
-DYDEDVHGV\QWD[DQGD£SXUH¤-DYDV\QWD[ WKDQEHLQJGHFODUHGZLWKWKHVLJQDWXUHp: ()
ºRZKHUHRLVWKHUHWXUQW\SHLWLVGHFODUHG
WKDW XVHV -DYD DQQRWDWLRQV WR LQGLFDWH WKH
SRLQWFXWVDQGDGYLFHVRIDQDVSHFW7KHDV ZLWKWKHVLJQDWXUHp: ºR%\QDPHSDUDP
SHFWEHKDYLRUV DGYLFHV FDQEHLQFRUSRUD HWHUVDUHHYDOXDWHGHYHU\WLPHWKH\DUHUHI
WHGLQWRWKHWDUJHWFRGHDWFRPSLOHWLPHDV HUHQFHG LQ WKH IXQFWLRQ UDWKHU WKDQ EHLQJ
D SRVWFRPSLOH £ZHDYLQJ¤ VWHS RU DW ORDG HYDOXDWHGRQFHMXVWEHIRUHWKHIXQFWLRQFDOO
WLPH OLNHDE\YDOXHSDUDPHWHU)RUH[DPSOHWKH\
DUHXVHIXOIRUDIXQFWLRQWKDWLVGHVLJQHGWR
Attribute ORRN OLNH D FRQWURO FRQVWUXFW WKDW WDNHV D
$QRWKHU QDPH IRU D ILHOG XVHG E\ £EORFN¤QRWDIXQFWLRQZLWKH[SOLFLWSDUDP
FRQYHQWLRQ LQ PDQ\ REMHFWRULHQWHG SUR HWHU DUJXPHQWV WKLQN RI KRZ while ORRSV
JUDPPLQJ ODQJXDJHV 6FDOD IROORZV -DYD¦V ORRNIRUH[DPSOH 7KHIXQFWLRQDUJXPHQW
FRQYHQWLRQRISUHIHUULQJWKHWHUPILHOGRYHU WKDWKDVEORFNOLNHEHKDYLRUZRXOGEHDE\
DWWULEXWH QDPHSDUDPHWHU
Auxiliary Constructor By-Value Parameter
$VHFRQGDU\FRQVWUXFWRURIDFODVVGHFODUHG $ E\YDOXH SDUDPHWHU LV WKH XVXDO NLQG RI
DVDPHWKRGQDPHGthisZLWKQRUHWXUQW\SH PHWKRGSDUDPHWHUWKDWLVHYDOXDWHGEHIRUH
$Q DX[LOLDU\ FRQVWUXFWRU PXVW LQYRNH WKH LWLVSDVVHGWRWKHPHWKRG&RQWUDVWZLWKE\
SULPDU\FRQVWUXFWRURUDSUHYLRXVO\GHILQHG QDPHSDUDPHWHU
DX[LOLDU\ FRQVWUXFWRU DV WKH ILUVW RU RQO\
VWDWHPHQWLQLWVPHWKRGERG\
Call By Name
6HHE\QDPHSDUDPHWHU
Base Type
$V\QRQ\PIRUSDUHQWW\SH
Call By Value
6HHE\YDOXHSDUDPHWHU
Behavior-Driven Development
$VW\OHRI7HVW'ULYHQ'HYHORSPHQW 7''
Call Site
WKDWHPSKDVL]HV7''¦VUROHLQGULYLQJWKH 6HHGHFODUDWLRQVLWH
XQGHUVWDQGLQJRIUHTXLUHPHQWVIRUWKHFRGH Case
<RX IROORZ WKH VDPH SURFHVV DV LQ 7'' 7KHNH\ZRUGXVHGLQSDWWHUQPDWFKLQJH[
ZKHUH WKH £WHVWV¤ DUH ZULWWHQ EHIRUH WKH SUHVVLRQV IRU WHVWLQJ DQ REMHFW DJDLQVW DQ
FRGH7KHGLIIHUHQFHLVWKDWWKHDXWRPDWHG H[WUDFWRUW\SHFKHFNHWF
WHVWVDUHZULWWHQLQDIRUPDWWKDWORRNVPRUH
OLNHDUHTXLUHPHQWV RUEHKDYLRUDO VSHFLIL

394 | Glossary

Download at WoweBook.Com
Context-Free Grammar

Case Class Companion Class


$FODVVGHFODUHGZLWKWKHNH\ZRUGcase7KH $classGHFODUHGZLWKWKHVDPHQDPHDVDQ
6FDOD FRPSLOHU DXWRPDWLFDOO\ GHILQHV REMHFWDQGGHILQHGLQWKHVDPHVRXUFHILOH
equals hashCodeDQG toStringPHWKRGVIRU 6HHDOVRFRPSDQLRQREMHFW
WKHFODVVDQGFUHDWHVDFRPSDQLRQREMHFWZLWK
DQapplyIDFWRU\PHWKRGDQGDQunapplyH[
Companion Object
WUDFWRUPHWKRG&DVHFODVVHVDUHSDUWLFXODUO\ $Q objectGHFODUHGZLWKWKHVDPHQDPHDV
FRQYHQLHQW IRU XVH ZLWK SDWWHUQ PDWFKLQJ D FODVV FDOOHG LWV FRPSDQLRQ FODVV  DQG
FDVH H[SUHVVLRQV GHILQHGLQWKHVDPHVRXUFHILOH&RPSDQLRQ
REMHFWVDUHZKHUHPHWKRGVDQGILHOGVDUHGH
Child Type ILQHGWKDWZRXOGEHVWDWLFVLQ-DYDFODVVHV
$FODVVRUWUDLWWKDWLQKHULWVIURPD parent VXFK DV IDFWRU\ PHWKRGV apply DQG
FODVVRUWUDLW6RPHWLPHVFDOOHGDVXEW\SHRU unapplyIRUSDWWHUQPDWFKLQJHWF
GHULYHGW\SH6HHLQKHULWDQFH
Component
Client )RURXUSXUSRVHVDQDJJUHJDWLRQRIFRKH
$QLQIRUPDOWHUPXVHGWKURXJKRXWWKHERRN VLYHW\SHVWKDWH[SRVHVHUYLFHVWKURXJKZHOO
WR LQGLFDWH D VHFWLRQ RI VRIWZDUH WKDW XVHV GHILQHG DEVWUDFWLRQV ZKLOH HQFDSVXODWLQJ
DQRWKHUDVDQ$3,HWF LPSOHPHQWDWLRQ GHWDLOV DQG PLQLPL]LQJ
FRXSOLQJWRRWKHUFRPSRQHQWV 7KHUHLVD
Class ZLGHUDQJHRIGHILQLWLRQVIRUFRPSRQHQWLQ
$WHPSODWHIRULQVWDQFHVWKDWZLOOKDYHWKH FRPSXWHUVFLHQFHDQGLQGXVWU\
VDPH ILHOGV UHSUHVHQWLQJ VWDWH YDOXHV DQG
WKHVDPHPHWKRGV6FDODFODVVHVVXSSRUWVLQ Compound Type
JOHLQKHULWDQFHDQG]HURRUPRUHPL[LQWUDLWV 7KHDFWXDOW\SHRIDGHFODUDWLRQRIWKHIRUP
&RQWUDVWZLWKW\SH T1 extends T2 with T3 with ... TN { R }
ZKHUHRLVWKHUHILQHPHQW ERG\ 'HILQLWLRQV
Closure LQRDIIHFWWKHW\SH
,Q6FDODDQLQVWDQFHWKDWKDVEHHQFUHDWHG
IURPDIXQFWLRQOLWHUDOZLWKDOOWKHIUHHYDUL Concrete Type
DEOHV UHIHUHQFHG LQ WKH IXQFWLRQ OLWHUDO $ FODVV WUDLW RU REMHFW ZLWK DOO PHWKRGV
ERXQGWRYDULDEOHVRIWKHVDPHQDPHLQWKH ILHOGV DQG W\SHV GHILQHG ,QVWDQFHV FDQ EH
HQFORVLQJ VFRSH ZKHUH WKH IXQFWLRQ OLWHUDO FUHDWHGIURPFRQFUHWHW\SHV&RQWUDVWZLWK
ZDVGHILQHG,QRWKHUZRUGVWKHLQVWDQFHLV DEVWUDFWW\SHV
£FORVHG¤LQWKHVHQVHWKDWWKHIUHHYDULDEOHV
DUHERXQG%HFDXVHWKH\DUHLQVWDQFHVFOR
Contract
VXUHV DUH ILUVWFODVV YDOXHV 7KH\ FDQ EH 7KH SURWRFRO DQG UHTXLUHPHQWV WKDW H[LVW
SDVVHGWRRWKHUIXQFWLRQVWRFXVWRPL]HWKHLU EHWZHHQDPRGXOH HJFODVVWUDLWREMHFW
EHKDYLRU)RUH[DPSOH List.foreachWDNHV RUHYHQIXQFWLRQRUPHWKRG DQGFOLHQWVRI
DFORVXUHWKDWLVDSSOLHGWRHDFKHOHPHQWLQ WKHPRGXOH0RUHVSHFLILFDOO\VHH'HVLJQE\
WKHOLVW6HHDOVRERXQGYDULDEOHVDQGIXQF &RQWUDFW
WLRQOLWHUDOV Context-Free Grammar
Comments $NLQGRIODQJXDJHJUDPPDUIRUZKLFKHDFK
6FDOD IROORZV WKH VDPH FRPPHQW FRQYHQ QRQWHUPLQDO FDQ EH VSHFLILHG DV D SURGXF
WLRQVDV-DYD&&HWF$ // comment WLRQZLWKRXWUHIHUHQFHWRDGGLWLRQDOFRQWH[W
JRHV WR WKH HQG RI D OLQH ZKLOH D /* LQIRUPDWLRQ7KDWLVHDFKQRQWHUPLQDOFDQ
comment */FDQFURVVOLQHERXQGDULHV
DSSHDUE\LWVHOIRQWKHOHIWKDQGVLGHRIWKH
SURGXFWLRQWKHVSHFLILHVLW

Glossary | 395

Download at WoweBook.Com
Contravariance or Contravariant

Contravariance or Contravariant Declarative Programming


,Q WKH FRQWH[W RI WKH YDULDQFH EHKDYLRU RI 7KH TXDOLW\ RI PDQ\ IXQFWLRQDO SURJUDPV
SDUDPHWHUL]HGW\SHVXQGHULQKHULWDQFHLID DQG 'RPDLQ6SHFLILF /DQJXDJHV ZKHUH WKH
SDUDPHWHUALVFRQWUDYDULDQWLQDSDUDPHWHU FRGHFRQVLVWVRIVWDWHPHQWVWKDWGHFODUHUH
L]HG W\SH T[-A] WKHQ WKH - LV WKH YDULDQFH ODWLRQVKLSVEHWZHHQYDOXHVDQGW\SHVUDWKHU
DQQRWDWLRQDQGDW\SHT[B]LVDVXSHUW\SHRI WKDQGLUHFWLQJWKHV\VWHPWRWDNHDSDUWLFXODU
T[A] LI B LV D VXEW\SH RI A 6HH DOVR FRYD VHTXHQFH RI DFWLRQ &RQWUDVW ZLWK LPSHUD
ULDQFHDQGLQYDULDQFH WLYHSURJUDPPLQJ
Covariance or Covariant Default Argument Value
,Q WKH FRQWH[W RI WKH YDULDQFH EHKDYLRU RI 6FDOD YHUVLRQ   7KH DELOLW\ WR GHILQH D
SDUDPHWHUL]HGW\SHVXQGHULQKHULWDQFHLID GHIDXOW YDOXH IRU D PHWKRG DUJXPHQW WKDW
SDUDPHWHUALVFRYDULDQWLQDSDUDPHWHUL]HG ZLOOEHXVHGLIWKHFDOOHUGRHVQRWVSHFLI\D
W\SH T[+A]WKHQWKH +LVWKHYDULDQFHDQQR YDOXH6HHDOVRLPSOLFLWDUJXPHQWDQGQDPHG
WDWLRQDQGDW\SHT[B]LVDVXEW\SHRIT[A]LI DUJXPHQW
BLVDVXEW\SHRI A6HHDOVRFRQWUDYDULDQFH
DQGLQYDULDQFH
Dependency Injection
$IRUPRILQYHUVLRQRIFRQWUROZKHUHDQRE
Cross-Cutting Concerns MHFW¦VH[WHUQDOGHSHQGHQFLHVDUHJLYHQWRLW
£&RQFHUQV¤ NLQGVRIUHTXLUHPHQWVGHVLJQ HLWKHU SURJUDPPDWLFDOO\ RU WKURXJK D ',
RUFRGLQJLVVXHV WKDWGRQ¦WILWLQWKHVDPH IUDPHZRUN WKDW LV GULYHQ E\ FRQILJXUDWLRQ
ERXQGDULHV DV WKH SULPDU\ PRGXODULW\ GH LQIRUPDWLRQ +HQFH WKH REMHFW UHPDLQV
FRPSRVLWLRQ7KHVDPHEHKDYLRUVPXVWEH £SDVVLYH¤UDWKHUWKDQWDNLQJDQDFWLYHUROH
LQYRNHG FRQVLVWHQWO\ DW VSHFLILF H[HFXWLRQ LQ UHVROYLQJ GHSHQGHQFLHV 7KH LQMHFWLRQ
SRLQWVRYHUDUDQJHRIREMHFWVDQGIXQFWLRQV PHFKDQLVPXVHVFRQVWUXFWRUDUJXPHQWVRU
)RU H[DPSOH WKH VDPH 250 2EMHFW ILHOGVHWWHUVSURYLGHGE\WKHREMHFW',PLQ
5HODWLRQDO 0DSSLQJ  SHUVLVWHQFH VWUDWHJ\ LPL]HV WKH FRXSOLQJ RI REMHFWV WKH\ RQO\
QHHGV WR EH XVHG FRQVLVWHQWO\ IRU D VHW RI QHHGWRNQRZDERXWWKHDEVWUDFWLRQVRIWKHLU
FODVVHVQRWMXVWDVLQJOHFODVV+HQFHVXFK GHSHQGHQFLHV
FRQFHUQVDUHVDLGWREHFURVVFXWWLQJ6XS
SRUWLQJ WKHVH FRQFHUQV VKRXOG QRW LQYROYH
Derived Type
GXSOLFDWLRQ RI FRGH HWF 6HH DOVR DVSHFW $V\QRQ\PIRUFKLOGW\SH
RULHQWHGSURJUDPPLQJ Design By Contract
Currying $QDSSURDFKWRFODVVDQGPRGXOHGHVLJQLQ
&RQYHUWLQJDQ1DUJXPHQWIXQFWLRQLQWRD YHQWHGE\%HUWUDQG0H\HUIRUWKH(LIIHOODQ
VHTXHQFHRI1IXQFWLRQVRIRQHDUJXPHQW JXDJH)RUHDFKHQWU\SRLQWYDOLGLQSXWVDUH
ZKHUH HDFK IXQFWLRQ H[FHSW IRU WKH ODVW VSHFLILHGLQDSURJUDPPDWLFZD\VRWKH\FDQ
UHWXUQV D QHZ IXQFWLRQ WKDW WDNHV D VLQJOH EHYDOLGDWHGGXULQJWHVWLQJ7KHVHVSHFLILFD
DUJXPHQWWKDWUHWXUQVDQHZIXQFWLRQHWF WLRQV DUH FDOOHG SUHFRQGLWLRQV 6LPLODUO\
XQWLO WKH ODVW IXQFWLRQ WKDW WDNHV D VLQJOH DVVXPLQJ WKH SUHFRQGLWLRQV DUH VSHFLILHG
DUJXPHQWDQGUHWXUQVDYDOXH VSHFLILFDWLRQVRQWKHJXDUDQWHHGUHVXOWVDUH
FDOOHGSRVWFRQGLWLRQVDQGDUHDOVRVSHFLILHG
Declaration Site LQDQH[HFXWDEOHZD\,QYDULDQWVFDQDOVREH
,QUHIHUHQFHWRKRZWKHYDULDQFHEHKDYLRURI VSHFLILHGWKDWVKRXOGEHWUXHRQHQWU\DQG
SDUDPHWHUL]HG W\SHV LV VSHFLILHG LQ 6FDOD RQH[LW
WKLVLVGRQHZKHQW\SHVDUHGHFODUHGLHDW
WKHGHFODUDWLRQVLWH,Q-DYDLWLVGRQHZKHQ
Design Pattern
W\SHVDUHFDOOHG WKDWLVXVHG LHDWWKHFDOO $VROXWLRQWRDSUREOHPLQDFRQWH[W$FRGH
VLWH LGLRPRUGHVLJQVWUXFWXUHWKDWVDWLVILHVWKH

396 | Glossary

Download at WoweBook.Com
Free Variable

QHHGV RI D IUHTXHQWO\ RFFXUULQJ SUREOHP Existential Types


FRQVWUDLQWUHTXLUHPHQWHWF $ZD\RIH[SUHVVLQJWKHSUHVHQFHRIDW\SH
ZLWKRXWNQRZLQJLWVFRQFUHWHYDOXHVRPH
Domain-Specific Language
WLPHVEHFDXVHLWFDQ¦WEHNQRZQ,WLVXVHG
$ FXVWRP SURJUDPPLQJ ODQJXDJH WKDW UH
SULPDULO\WRVXSSRUWDVSHFWVRI-DYD¦VW\SH
VHPEOHVWKHWHUPVLGLRPVDQGH[SUHVVLRQV
V\VWHPZLWKLQ6FDOD¦VW\SHV\VWHPLQFOXGLQJ
RIDSDUWLFXODUGRPDLQ$QLQWHUQDO'6/LV
W\SH HUDVXUH £UDZ¤ W\SHV HJ SUH-DYD 
DQLGLRPDWLFIRUPRIDJHQHUDOSXUSRVHSUR
FROOHFWLRQV DQGFDOOVLWHW\SHYDULDQFH
JUDPPLQJ ODQJXDJH 7KDW LV QR VSHFLDO
SXUSRVHSDUVHULVFUHDWHGIRUWKHODQJXDJH Extractor
,QVWHDG'6/FRGHLVZULWWHQLQWKHJHQHUDO $QunapplyPHWKRGGHILQHGLQDFRPSDQLRQ
SXUSRVHODQJXDJHDQGSDUVHGMXVWOLNHDQ\ REMHFWWKDWLVXVHGWRH[WUDFWWKHFRQVWLWXHQW
RWKHUFRGH$QH[WHUQDO'6/LVDODQJXDJH YDOXHVIRUILHOGVLQDQREMHFW7KH\DUHPRVW
ZLWKLWVRZQJUDPPDUDQGSDUVHU FRPPRQO\ XVHG LQ SDWWHUQ PDWFKLQJ
H[SUHVVLRQV
Duck Typing
$WHUPXVHGLQODQJXDJHVZLWKG\QDPLFW\S Field
LQJIRUWKHZD\PHWKRGUHVROXWLRQZRUNV$V $valRUvarLQDW\SHWKDWUHSUHVHQWVSDUWLI
ORQJDVDQREMHFWDFFHSWVDPHWKRGFDOO PHV QRWDOORIWKHVWDWHRIDFRUUHVSRQGLQJLQ
VDJH VHQG  WKH UXQWLPH LV VDWLVILHG £,I LW VWDQFHRIWKHW\SH
ZDONVOLNHDGXFNDQGWDONVOLNHDGXFNLW¦V
DGXFN¤&RQWUDVWZLWKWKHXVHRIVWUXFWXUDO Final
W\SHVLQVRPHVWDWLFDOO\W\SHGODQJXDJHVOLNH .H\ZRUGIRUGHFODUDWLRQV)RUW\SHV final
6FDOD SUHYHQWV XVHUV IURP VXEFODVVLQJ WKH W\SH
)RU W\SH PHPEHUV final SUHYHQWV XVHUV
Dynamic Typing IURPRYHUULGLQJWKHPHPEHUV
/RRVHO\VSHDNLQJODWHELQGLQJRIW\SHLQIRU
PDWLRQVRPHWLPHVUHIHUUHGWRDVELQGLQJWR First Class
WKHYDOXHDUHIHUHQFHLVDVVLJQHGWRUDWKHU $QDGMHFWLYHLQGLFDWLQJWKDWWKHDSSOLFDEOH
WKDQ WR WKH UHIHUHQFH LWVHOI &RQWUDVW ZLWK £WKLQJ¤LVDILUVWFODVVYDOXHLQWKHODQJXDJH
VWDWLFW\SLQJ PHDQLQJ\RXFDQDVVLJQLQVWDQFHVWRYDULD
EOHVSDVVWKHPDVIXQFWLRQSDUDPHWHUVDQG
Encapsulation UHWXUQWKHPIURPIXQFWLRQV2IWHQXVHGWR
5HVWULFWLQJ WKH YLVLELOLW\ RI PHPEHUV RI D UHIHUWRIXQFWLRQVZKLFKDUHILUVWFODVVYDOXHV
W\SHVRWKH\DUHQRWYLVLEOHWRFOLHQWVRIWKH LQ6FDODDQGRWKHUIXQFWLRQDOSURJUDPPLQJ
W\SHZKHQWKH\VKRXOGQ¦WEH7KLVLVDZD\ ODQJXDJHV
RIH[SRVLQJRQO\WKHDEVWUDFWLRQVXSSRUWHG
E\ WKH W\SH ZKLOH KLGLQJ LPSOHPHQWDWLRQ For Comprehension
GHWDLOVZKLFKSUHYHQWVXQZDQWHGDFFHVVWR $QRWKHUQDPHIRU6FDOD¦VforH[SUHVVLRQ
WKHP IURP FOLHQWV DQG NHHSV WKH DEVWUDF Formal Parameter
WLRQ H[SRVHG E\ WKH W\SH FRQVLVWHQW DQG $QRWKHUQDPHIRUDIXQFWLRQDUJXPHQWXVHG
PLQLPDO LQWKHFRQWH[WRIELQGLQJWKHIUHHYDULDEOHV
Event LQWKHIXQFWLRQ
7KHQRWLILFDWLRQRIDVWDWHFKDQJHLQHYHQW Free Variable
EDVHGFRQFXUUHQF\ $YDULDEOHWKDWLVUHIHUHQFHGLQDIXQFWLRQOLW
Event-Based Concurrency HUDO EXW LV QRW SDVVHG LQ DV DQ DUJXPHQW
$ KLJKSHUIRUPDQFH IRUP RI FRQFXUUHQF\ 7KHUHIRUHLWPXVWEH£ERXQG¤WRDGHILQHG
ZKHUH HYHQWV DUH XVHG WR VLJQDO LPSRUWDQW YDULDEOH RI WKH VDPH QDPH LQ WKH FRQWH[W
VWDWH FKDQJHV DQG KDQGOHUV DUH XVHG WR ZKHUHWKHIXQFWLRQOLWHUDOLVGHILQHGWRIRUP
UHVSRQGWRWKHHYHQWV DFORVXUH

Glossary | 397

Download at WoweBook.Com
Function

Function WDNHDSDUWLFXODUVHTXHQFHRIDFWLRQV&RQ
,Q6FDODWKHWHUPIXQFWLRQLVXVHGIRUDIXQF WUDVWZLWKGHFODUDWLYHSURJUDPPLQJ
WLRQWKDWLVQRWWLHGWRDSDUWLFXODUREMHFWRU
Implicit
FODVV&RQWUDVWZLWKPHWKRG)XQFWLRQVDUH
$6FDODNH\ZRUGXVHGWRPDUNDPHWKRGRU
LQVWDQFHVRIFunctionNW\SHVZKHUHNLVWKH
IXQFWLRQYDOXHDVHOLJLEOHIRUXVHDVDQLP
DULW\RIWKHIXQFWLRQ
SOLFLWW\SHFRQYHUVLRQ7KHNH\ZRUGLVDOVR
Function Literal XVHGWRPDUNDQLPSOLFLWDUJXPHQW
6FDOD¦VWHUPIRUDQDQRQ\PRXVIXQFWLRQH[
Implicit Type Conversion
SUHVVLRQIURPZKLFKFORVXUHVDUHFUHDWHG
$PHWKRGRUIXQFWLRQYDOXHWKDWLVPDUNHG
Function Type ZLWKWKHLPSOLFLWNH\ZRUGPDUNLQJLWDVHO
,Q 6FDOD DOO IXQFWLRQV DUH LQVWDQFHV RI LJLEOHIRUXVHDVDQLPSOLFLWW\SHFRQYHUVLRQ
FunctionN[-T1, T2, ..., TN, +R] W\SHV ZKHQHYHU LW LV LQ VFRSH DQG FRQYHUVLRQ LV
ZKHUH N LV WKH QXPEHU RI DUJXPHQWV  QHHGHG HJ IRU WKH 3LPS 0\ /LEUDU\
WKURXJKDUHVXSSRUWHG 7KHW\SHVLJQD SDWWHUQ 
WXUHV\QWD[ (T1, T2, ..., TN) ºRLVXVHG
Implicit Argument
IRUGHFODULQJFRQFUHWHLQVWDQFHVLHIXQF
0HWKRGDUJXPHQWVWKDWDUHRSWLRQDOIRUWKH
WLRQOLWHUDOV
XVHU WR VSHFLI\ DQG LQGLFDWHG ZLWK WKH
Functional Programming implicitNH\ZRUG,IWKHXVHUGRHVQRWVSHF
$IRUPRISURJUDPPLQJWKDWPLPLFVWKHZD\ LI\DYDOXHIRUWKHDUJXPHQWDGHIDXOWYDOXH
PDWKHPDWLFDOIXQFWLRQVDQGYDULDEOHVZRUN LVXVHGLQVWHDGZKLFKLVHLWKHUDQLQVFRSH
0DWKHPDWLFDOIXQFWLRQVDUHVLGHHIIHFWIUHH YDOXHRIWKHVDPHW\SHRUWKHUHVXOWRIFDOOLQJ
DQGWKH\DUHFRPSRVDEOHIURPRWKHUIXQF DQ LQVFRSH QRDUJXPHQW PHWKRG WKDW UH
WLRQV 9DULDEOHV DUH DVVLJQHG RQFH )XQF WXUQVDQLQVWDQFHRIWKHVDPHW\SH6HHDOVR
WLRQV FDQ EH DVVLJQHG WR YDULDEOHV DQG GHIDXOWDUJXPHQWYDOXH
UHWXUQHGIURPRWKHUIXQFWLRQV
Infinite Data Structure
Generator $ GDWD VWUXFWXUH WKDW UHSUHVHQWV D QRQ
([SUHVVLRQVOLNHi <- listOfIntsLQforH[ WHUPLQDWLQJFROOHFWLRQRIYDOXHVEXWZKLFK
SUHVVLRQV(DFKSDVVWKURXJKWKHORRSJHQ LV FDSDEOH RI GRLQJ VR ZLWKRXW H[KDXVWLQJ
HUDWHVDQHZvaliWDNHQIURPWKHOLVWlistO V\VWHPUHVRXUFHV7KHYDOXHVDUHQRWFRP
fIntsLQWKLVH[DPSOH SXWHG XQWLO WKH GDWD VWUXFWXUH LV DVNHG WR
SURGXFHWKHP$VORQJDVRQO\DILQLWHVXEVHW
Generics RI WKH YDOXHV DUH UHTXHVWHG UHVRXUFH H[
$QRWKHUWHUPIRUSDUDPHWHUL]HGW\SHVXVHG KDXVWLRQLVDYRLGHG
PRUHRIWHQLQ-DYDWKDQ6FDOD
Infix Notation
Higher-Order Functions $ V\QWD[ VXSSRUWHG E\ WKH FRPSLOHU IRU
)XQFWLRQVWKDWWDNHRWKHUIXQFWLRQVDVDUJX PHWKRGV ZLWK RQH DUJXPHQW 7KH PHWKRG
PHQWVRUUHWXUQDIXQFWLRQYDOXH FDQEHLQYRNHGZLWKRXWWKHSHULRGEHWZHHQ
Immutable Value WKHREMHFWDQGWKHPHWKRGQDPHDQGZLWK
$ YDOXH WKDW FDQ¦W EH FKDQJHG DIWHU LW KDV RXW WKH SDUHQWKHVHV DURXQG WKH DUJXPHQW
EHHQ LQLWLDOL]HG &RQWUDVW ZLWK PXWDEOH :KHQXVHGIRUPHWKRGVQDPHGZLWKRSHU
YDOXH DWRUFKDUDFWHUVWKHV\QWD[SURYLGHVDIRUP
RI RSHUDWRU RYHUORDGLQJ 6RPHWLPHV DOVR
Imperative Programming FDOOHG RSHUDWRU QRWDWLRQ 6HH DOVR SRVWIL[
7KH TXDOLW\ RI PDQ\ REMHFWRULHQWHG DQG QRWDWLRQ
£SURFHGXUDO¤SURJUDPVZKHUHWKHFRGHFRQ
VLVWV RI VWDWHPHQWV GLUHFWLQJ WKH V\VWHP WR

398 | Glossary

Download at WoweBook.Com
Main

Infix Type SHQGHQFLHV QRW VSHFLILF FRQFUHWH LPSOH


:KHQ D SDUDPHWHUL]HG W\SH RI WKH IRUP PHQWHUV RI WKHP $ ZHDN IRUP RI ,R& LV
Op[A,B]LVXVHGWRLQVWDQWLDWHDW\SHLWFDQ ZKHQDQREMHFWFDOOVDIDFWRU\VHUYLFHORFD
DOVR EH ZULWWHQ DV A Op B )RU H[DPSOH WRUHWFWRREWDLQWKHGHSHQGHQWV+HQFH
Or[Throwable,Boolean] FDQ EH ZULWWHQ WKHREMHFWVWLOOKDVDQDFWLYHUROHDQGLWKDVD
Throwable Or Boolean GHSHQGHQF\RQWKH£SURYLGHU¤7KHVWURQ
JHVW IRUP RI ,R& LV GHSHQGHQF\ LQMHFWLRQ
Inheritance ZKHUHWKHREMHFWUHPDLQV£SDVVLYH¤
$VWURQJUHODWLRQVKLSEHWZHHQRQHFODVVRU
WUDLW DQG DQRWKHU FODVV RU WUDLW 7KH Lazy
LQKHULWLQJ GHULYHG  FODVV RU WUDLW LQFRUSR ,PPXWDEOHYDULDEOHV valV FDQEHGHFODUHG
UDWHVWKHPHPEHUVRIWKHSDUHQWFODVVRUWUDLW lazy PHDQLQJ WKH\ ZLOO RQO\ EH HYDOXDWHG
DVLIWKH\ZHUHGHILQHGZLWKLQWKHGHULYDWLYH ZKHQWKH\DUHUHDG7KLVIHDWXUHLVXVHIXOIRU
7KHGHULYDWLYHPD\RYHUULGHLQKHULWHGPHP H[SHQVLYH HYDOXDWLRQV WKDW PD\ QRW EH
EHUV LQPRVWFDVHV ,QVWDQFHVRIDGHULYDWLYH QHHGHG
DUHVXEVWLWXWDEOHIRULQVWDQFHVRIWKHSDUHQW /D]\ GDWD VWUXFWXUHV FDQ DOVR EH XVHG WR
Instance or Instantiate GHILQHLQILQLWHGDWDVWUXFWXUHVWKDWZRQ¦WH[
$Q REMHFW FUHDWHG E\ LQYRNLQJ D FODVV FRQ KDXVWV\VWHPUHVRXUFHVDVORQJDVRQO\DIL
VWUXFWRU7KHZRUGREMHFWLVV\QRQ\PRXVLQ QLWHVXEVHWRIWKHVWUXFWXUHLVHYDOXDWHG7KH
PRVWREMHFWRULHQWHGODQJXDJHVEXWZHXVH Stream DQG Range FODVVHV DUH ERWK OD]\
WKH WHUP REMHFW WR UHIHU WR DQ H[SOLFLWO\ &RQWUDVWZLWKVWULFW
GHFODUHG6FDODREMHFWDQGZHXVHWKHWHUP Linearization
LQVWDQFH DQG WKH YHUE LQVWDQWLDWH  IRU WKH 7KH DOJRULWKP XVHG IRU D W\SH WR UHVROYH
PRUHJHQHUDOFDVH PHPEHUORRNXSVXFKDVRYHUULGGHQPHWK
,QVWDQWLDWLRQ FDQ DOVR UHIHU WR FUHDWLQJ D RGVLQFOXGLQJFDOOVWRsuper
FRQFUHWH W\SH IURP D SDUDPHWHUL]HG W\SH
Literal
E\ VSHFLI\LQJ FRQFUHWH W\SHV IRU WKH
8VHGWRUHIHUWR£OLWHUDO¤YDOXHH[SUHVVLRQV
SDUDPHWHUV
VXFKDVQXPEHUV HJ13.14 VWULQJV HJ
Invariance and Invariant £+HOOR6FDOD¤ WXSOHV HJ(1, 2, 3) DQG
,Q WKH FRQWH[W RI WKH YDULDQFH EHKDYLRU RI IXQFWLRQOLWHUDOV HJ(x) ºx + x 
SDUDPHWHUL]HGW\SHVXQGHULQKHULWDQFHLID
Lower Type Bounds
SDUDPHWHU ALVLQYDULDQWLQDSDUDPHWHUL]HG
6HHW\SHERXQGV
W\SHT[A]WKHQWKHUHLVQRYDULDQFHDQQRWD
WLRQDQGDW\SH T[B]LVDVXEW\SHRI T[A]LI Mailbox
DQGRQO\LIBHTXDOVA7KDWLVWKHW\SHFDQ¦W 7KH TXHXH ZKHUH DQ $FWRU¦V PHVVDJHV DUH
EH FKDQJHG 6HH DOVR FRYDULDQFH DQG VWRUHGXQWLOWKH$FWRUSURFHVVHVWKHPLQWKH
FRQWUDYDULDQFH $FWRUPRGHORIFRQFXUUHQF\
,QWKHFRQWH[WRI'HVLJQE\&RQWUDFWDQDV Main
VHUWLRQWKDWVKRXOGEHWUXHEHIRUHDQGDIWHU 7KHHQWU\IXQFWLRQIRUDQDSSOLFDWLRQWKDWLV
DPHWKRGLVH[HFXWHG LQYRNHGE\WKHUXQWLPHLVFDOOHG main7KH
Inversion of Control QDPHGDWHVEDFNWRWKH&ODQJXDJH,Q6FDOD
7KHLGHDWKDWDQREMHFWVKRXOGQRWLQVWDQWL D main PHWKRG PXVW EH GHILQHG LQ DQ
object-DYDE\ZD\RIFRQWUDVWUHTXLUHVD
DWHLWVRZQFRSLHVRIH[WHUQDOGHSHQGHQFLHV
mainPHWKRGWREHGHILQHGDVDVWDWLFPHWKRG
EXWUDWKHUUHO\RQRWKHUPHFKDQLVPVWRVXS
SO\WKRVHGHSHQGHQFLHV,R&SURPRWHVEHW RIDclass
WHUGHFRXSOLQJDQGWHVWDELOLW\DVWKHREMHFW
RQO\NQRZVDERXWWKHDEVWUDFWLRQVRILWVGH

Glossary | 399

Download at WoweBook.Com
MapReduce

MapReduce Multiple Inheritance


$GLYLGHDQGFRQTXHUVWUDWHJ\IRUSURFHVV ,QVRPHODQJXDJHVEXWQRW6FDODDW\SHFDQ
LQJODUJHGDWDVHWVLQSDUDOOHO,QWKH£PDS¤ H[WHQG PRUH WKDQ RQH SDUHQW FODVV &RP
SKDVHWKHGDWDVHWVDUHVXEGLYLGHG7KHGH SDUHWRVLQJOHLQKHULWDQFH
VLUHG FRPSXWDWLRQ LV SHUIRUPHG RQ HDFK
VXEVHW 7KH £UHGXFH¤ SKDVH FRPELQHV WKH
Mutable Value
UHVXOWVRIWKHVXEVHWFDOFXODWLRQVLQWRDILQDO $YDOXHWKDWFDQEHFKDQJHGDIWHULWKDVEHHQ
UHVXOW0DS5HGXFHIUDPHZRUNVKDQGOHWKH LQLWLDOL]HG&RQWUDVWZLWKLPPXWDEOHYDOXH
GHWDLOVRIPDQDJLQJWKHRSHUDWLRQVDQGWKH Named Argument
QRGHV WKH\ UXQ RQ LQFOXGLQJ UHVWDUWLQJ 6FDODYHUVLRQ 7KHDELOLW\WRUHIHUWRD
RSHUDWLRQV WKDW IDLO IRU VRPH UHDVRQ 7KH PHWKRGDUJXPHQWE\QDPHZKHQFDOOLQJWKH
XVHURIWKHIUDPHZRUNRQO\KDVWRZULWHWKH PHWKRG,WLVXVHIXOLQFRPELQDWLRQZLWKGH
DOJRULWKPV IRU PDSSLQJ DQG UHGXFLQJ IDXOW DUJXPHQW YDOXHV IRU PLQLPL]LQJ WKH
WKH GDWD VHWV DQG FRPSXWLQJ ZLWK WKH QXPEHURIDUJXPHQWVWKDWKDYHWREHVSHFL
VXEVHWV ILHGE\WKHFDOOHU
Member Nonterminal
$ JHQHULF WHUP IRU D W\SH ILHOG RU PHWKRG $QLWHPLQDJUDPPDUWKDWUHTXLUHVIXUWKHU
GHFODUHGLQDFODVVRUWUDLW GHFRPSRVLWLRQLQWRRQHRUPRUHQRQWHUPL
Memoization QDOV LQFOXGLQJ SRVVLEO\ D UHFXUVLYH UHIHU
$IRUPRIFDFKLQJWKDWRSWLPL]HVIXQFWLRQ HQFHWRLWVHOI DQGWHUPLQDOV
LQYRFDWLRQV 7KH UHVXOWV IURP D IXQFWLRQ¦V Object
LQYRFDWLRQVDUHVDYHGVRWKDWZKHQUHSHDWHG $FRKHVLYHXQLWZLWKDSDUWLFXODUVWDWHSRV
LQYRFDWLRQVZLWKWKHVDPHLQSXWVDUHPDGH VLEOH VWDWH WUDQVLWLRQV DQG EHKDYLRUV ,Q
WKHFDFKHGUHVXOWVFDQEHUHWXUQHGLQVWHDGRI 6FDODWKHNH\ZRUGobjectLVXVHGWRGHFODUH
UHLQYRNLQJWKHIXQFWLRQ DVLQJOHWRQH[SOLFLWO\XVLQJWKHVDPHV\QWD[
Message DVFODVVGHFODUDWLRQVH[FHSWIRUWKHODFNRI
,QWKH$FWRUPRGHORIFRQFXUUHQF\PHVVDJHV FRQVWUXFWRU SDUDPHWHUV DQG DX[LOLDU\ SD
DUHH[FKDQJHGEHWZHHQ$FWRUVWRFRRUGLQDWH UDPHWHUV EHFDXVH objects DUH LQVWDQWLDWHG
WKHLUZRUN E\WKH6FDODUXQWLPHQRWE\XVHUFRGH 7R
DYRLG FRQIXVLRQ ZLWK objects ZH XVH WKH
,Q REMHFWRULHQWHG SURJUDPPLQJ PHWKRG WHUPLQVWDQFHWRUHIHUWRLQVWDQFHVRIFODVVHV
LQYRFDWLRQ LV VRPHWLPHV UHIHUUHG WR DV DQGobjectsJHQHULFDOO\
£VHQGLQJDPHVVDJHWRDQREMHFW¤HVSHFLDOO\
LQFHUWDLQODQJXDJHVOLNH6PDOOWDONDQGWR Object-Oriented Programming
VRPHH[WHQW5XE\ $ IRUP RI SURJUDPPLQJ WKDW HQFDSVXODWHV
VWDWH YDOXHV DQG RSHUDWLRQV RQ WKDW VWDWH
Method H[SRVLQJDFRKHVLYHDEVWUDFWLRQWRFOLHQWVRI
$IXQFWLRQWKDWLVDVVRFLDWHGH[FOXVLYHO\ZLWK WKHREMHFWZKLOHKLGLQJLQWHUQDOLPSOHPHQ
DQLQVWDQFHHLWKHUGHILQHGLQDFODVVWUDLW WDWLRQGHWDLOV223DOVRVXSSRUWVVXEW\SLQJ
RU REMHFW GHILQLWLRQ 0HWKRGV FDQ RQO\ EH WRGHILQHVSHFLDOL]DWLRQVDQG£IDPLO\¤UHOD
LQYRNHGXVLQJWKHobject.methodV\QWD[ WLRQVKLSVEHWZHHQW\SHV
Mixin Operator Characters
$ QDUURZO\ IRFXVHG HQFDSVXODWLRQ RI VWDWH &KDUDFWHUVOLNH<*HWFWKDWDUHQRWOHWWHUV
DQGEHKDYLRUWKDWLVPRUHXVHIXODVDQDG QRUGLJLWVQRUUHVHUYHGFKDUDFWHUVOLNHOHIW
MXQFWWRDQRWKHUREMHFW¦VVWDWHDQGEHKDYLRU DQGULJKWSDUHQWKHVHVFXUO\EUDFHVVTXDUH
UDWKHUWKDQVWDQGLQJRQLWVRZQ0L[LQVLQ EUDFNHWVWKHVHPLFRORQFRORQRUFRPPD
6FDODDUHLPSOHPHQWHGXVLQJWUDLWV 7KHVH FKDUDFWHUV FDQ EH XVHG LQ PHWKRG

400 | Glossary

Download at WoweBook.Com
Precondition

QDPHV WR LPSOHPHQW D IRUP RI RSHUDWRU Parent Type


RYHUORDGLQJ $FODVVRUWUDLWIURPZKLFKDQRWKHUFODVVRU
WUDLW LV GHULYHG $OVR FDOOHG D VXSHUW\SH RU
Operator Notation
EDVHW\SH6HHLQKHULWDQFH
6HHLQIL[QRWDWLRQ
Parsing expression grammars (PEGs)
Operator Overloading
$QDOWHUQDWLYHWRFRQWH[WIUHHJUDPPDUVWKDW
7KHIHDWXUHLQVRPHODQJXDJHVZKHUHVWDQG
SURYLGH JXDUDQWHHG OLQHDUWLPH SDUVLQJ
DUGPDWKHPDWLFDORSHUDWRUVOLNH*/<HWF
XVLQJ PHPRL]DWLRQ DQG XQDPELJXRXV
FDQEHGHILQHGE\XVHUVIRUFXVWRPW\SHV,Q
JUDPPDUV >3(*@ 
6FDODDIRUPRIRSHUDWRURYHUORDGLQJLVVXS
SRUWHGE\DOORZLQJRSHUDWRUFKDUDFWHUVWREH Partial Application
XVHG DV QRUPDO PHWKRG QDPHV DQG E\ DO $VVRFLDWHGZLWKFXUU\LQJZKHUHDVXEVHWRI
ORZLQJ PHWKRGV ZLWK RQH DUJXPHQW WR EH DFXUULHGIXQFWLRQ¦VDUJXPHQWVDUHDSSOLHG
LQYRNHGZLWKLQIL[QRWDWLRQ7KH£RSHUDWRU \LHOGLQJ D QHZ IXQFWLRQ WKDW WDNHV WKH UH
SUHFHGHQFH¤ IRU WKHVH PHWKRGV LV GHWHU PDLQLQJDUJXPHQWV
PLQHG E\ WKH ILUVW FKDUDFWHU HJ PHWKRG
*<ZLOOKDYHKLJKHUSUHFHGHQFHWKDQPHWKRG Partial Function
+< $IXQFWLRQWKDWLVQRWYDOLGRYHUWKHZKROH
UDQJHRILWVDUJXPHQWV3DWWHUQPDWFKLQJH[
Overloaded Functions SUHVVLRQVFDQEHFRQYHUWHGWRSDUWLDOIXQF
7ZRRUPRUHIXQFWLRQVGHILQHGLQWKHVDPH WLRQVE\WKHFRPSLOHULQVRPHFRQWH[WV
VFRSH HJDVPHWKRGVLQDW\SHRUDV£EDUH¤
IXQFWLRQV WKDWKDYHWKHVDPHQDPHEXWGLI Path-Dependent Type
IHUHQWVLJQDWXUHV $ QHVWHG W\SH 7 LV XQLTXH EDVHG RQ LWV
£SDWK¤ WKH KLHUDUFKLFDO SHULRGGHOLPLWHG
Package Objects OLVWRIWKHHQFORVLQJSDFNDJHVWKHHQFORVLQJ
$VSHFLDONLQGRIREMHFWGHFODUDWLRQWKDWGH W\SHVDQGILQDOO\WKHW\SH7LWVHOI,QVWDQFHV
FODUHVPHPEHUVWKDWVKRXOGEHYLVLEOHDWWKH RI7FDQKDYHGLIIHUHQWLQFRPSDWLEOHW\SHV
VFRSHRIWKHQDPHGSDFNDJH)RUH[DPSOH )RUH[DPSOHLI7LVQHVWHGLQDWUDLWDQGWKH
IRU WKH GHFODUDWLRQ package object math WUDLWDSSHDUVLQWKHOLQHDUL]DWLRQVRIGLIIHUHQW
{ type Complex = ... }WKH ComplexW\SH W\SHV WKHQ WKH LQVWDQFHV LQ WKRVH 7V ZLOO
FDQ EH UHIHUHQFHG DV math.Complex 6FDOD KDYHGLIIHUHQWW\SHV
YHUVLRQ
Pattern Matching
Packrat Parsers &DVHH[SUHVVLRQVXVXDOO\LQDPDWFKH[SUHV
3DUVHUV IRU SDUVLQJ H[SUHVVLRQ JUDPPDUV VLRQ WKDW FRPSDUH DQ REMHFW DJDLQVW
3(*VVHH>)RUG@ 7KH\KDYHVHYHUDOEHQH SRVVLEOH W\SHV W\SH H[WUDFWRUV UHJXODU H[
ILWVVXFKDVODFNRIDPELJXLW\DQGJRRGSHU SUHVVLRQVHWFWRGHWHUPLQHWKHDSSURSULDWH
IRUPDQFH FKDUDFWHULVWLFV 7KH IRUWKFRPLQJ KDQGOLQJ
6FDODYHUVLRQSDUVHUFRPELQDWRUOLEUDU\
ZLOO DGG VXSSRUW IRU FUHDWLQJ SDFNUDW Pimp My Library
SDUVHUV 7KHQDPHRIDGHVLJQSDWWHUQWKDWDSSHDUV
WR DGG QHZ PHWKRGV WR D W\SH ,W XVHV DQ
Parameterized Types LPSOLFLW W\SH FRQYHUVLRQ WR DXWRPDWLFDOO\
6FDOD¦VDQDORJRIJHQHULFVLQ-DYD3DUDPH ZUDSWKHW\SHLQDZUDSSHUW\SHZKHUHWKH
WHUL]HG W\SHV DUH GHILQHG ZLWK SODFHKROGHU ZUDSSHUW\SHKDVWKHGHVLUHGPHWKRGV
SDUDPHWHUVIRUW\SHVWKH\XVH:KHQDQLQ
VWDQFH RI D SDUDPHWHUL]HG W\SH LV FUHDWHG Precondition
VSHFLILF W\SHV PXVW EH VSHFLILHG WR UHSODFH $QDVVHUWLRQWKDWVKRXOGEHWUXHRQHQWU\WR
DOO WKH W\SH SDUDPHWHUV 6HH DOVR W\SH DPHWKRGRURWKHUHQWU\SRLQW6HH'HVLJQE\
FRQVWUXFWRU &RQWUDFW

Glossary | 401

Download at WoweBook.Com
Postcondition

Postcondition Referential Transparency


$QDVVHUWLRQWKDWVKRXOGEHWUXHRQH[LWIURP 7KH SURSHUW\ RI DQ H[SUHVVLRQ VXFK DV D
DPHWKRGRURWKHUERXQGDU\SRLQW6HH'H IXQFWLRQZKHUHLWFDQEHUHSODFHGZLWKLWV
VLJQE\&RQWUDFW YDOXHZLWKRXWFKDQJLQJWKHEHKDYLRURIWKH
FRGH7KLVFDQEHGRQHZLWKVLGHHIIHFWIUHH
Postfix Notation IXQFWLRQVZKHQWKHLQSXWVDUHWKHVDPH7KH
$ V\QWD[ VXSSRUWHG E\ WKH FRPSLOHU IRU SULPDU\EHQHILWRIUHIHUHQWLDOWUDQVSDUHQF\
PHWKRGV ZLWK QR DUJXPHQW VRPHWLPHV LVWKDWLWLVHDV\WRUHDVRQDERXWWKHEHKDYLRU
FDOOHGQXOODU\PHWKRGV7KHPHWKRGFDQEH RIDIXQFWLRQZLWKRXWKDYLQJWRXQGHUVWDQG
LQYRNHG ZLWKRXW WKH SHULRG EHWZHHQ WKH WKH FRQWH[W LQ ZKLFK LW LV LQYRNHG 7KDW
REMHFWDQGWKHPHWKRGQDPH6HHDOVRLQIL[ PDNHVWKHIXQFWLRQHDVLHUWRWHVWUHIDFWRU
QRWDWLRQ DQGUHXVH
Primary Constructor Refinement
7KHPDLQFRQVWUXFWRURIDFODVVFRQVLVWLQJ 7KH WHUP XVHG IRU DGGLQJ RU RYHUULGLQJ
RI WKH FODVV ERG\ ZLWK WKH SDUDPHWHU OLVW PHPEHUV LQ D W\SH ERG\ IRU D FRPSRXQG
VSHFLILHGDIWHUWKHQDPHRIWKHFODVV6HHDOVR W\SH
DX[LOLDU\FRQVWUXFWRU
Reified Types
Primitive Type :KHUHWKHVSHFLILFW\SHVXVHGZKHQLQVWDQ
$ QRQREMHFW W\SH RQ WKH XQGHUO\LQJ UXQ WLDWLQJDJHQHULFW\SHDUHUHWDLQHGLQWKHE\WH
WLPHSODWIRUP HJ-90DQG1(7 6FDOD FRGHVRWKHLQIRUPDWLRQLVDYDLODEOHDWUXQ
GRHVQRWKDYHSULPLWLYHW\SHVDWWKHVRXUFH WLPH7KLVLVDSURSHUW\RI1(7E\WHFRGH
FRGHOHYHO5DWKHULWXVHVYDOXHW\SHVZKLFK EXWQRW-90E\WHFRGHZKLFKXVHVW\SHHUD
DUH VXEFODVVHV RI AnyVal WR ZUDS UXQWLPH VXUH 7R PLQLPL]H LQFRPSDWLELOLWLHV ERWK
SULPLWLYHVSURYLGLQJREMHFWVHPDQWLFVDWWKH WKH-DYDDQG1(76FDODYHUVLRQVXVHW\SH
FRGHOHYHOZKLOHXVLQJER[LQJDQGXQER[LQJ HUDVXUH
RISULPLWLYHVDWWKHE\WHFRGHOHYHOWRRSWL
PL]HSHUIRUPDQFH REPL
$QDPHJLYHQWRLQWHUDFWLYHODQJXDJHLQWHU
Production SUHWHUV OLNH WKH scala FRPPDQG LQ LQWHU
$WHUPXVHGIRUHDFKSDUWRIDJUDPPDUWKDW SUHWHUPRGH5(3/LVDQDFURQ\PIRU5HDG
GHFRPSRVHV D VSHFLILF QRQWHUPLQDO LQWR (YDOXDWH3ULQW/RRS
RWKHU QRQWHUPLQDOV SHUKDSV LQFOXGLQJ D
UHFXUVLYHUHIHUHQFHWRWKHRULJLQDOQRQWHUPL Scaladocs
QDO DQGWHUPLQDOV 7KH $3, GRFXPHQWDWLRQ JHQHUDWHG IURP
6FDODVRXUFHFRGHXVLQJWKH scaladocWRRO
Pure DQDORJRXVWR-DYD¦V-DYDGRFV
8VHG LQ WKH FRQWH[W RI IXQFWLRQV WR PHDQ
WKDWWKH\DUHVLGHHIIHFWIUHH6HHDOVRUHIHU Scope
HQWLDOWUDQVSDUHQF\ $GHILQHGERXQGDU\RIYLVLELOLW\FRQVWUDLQ
LQJZKDWW\SHVDQGWKHLUPHPEHUVDUHYLVLEOH
Recursion ZLWKLQLW
:KHQ D IXQFWLRQ FDOOV LWVHOI DV SDUW RI LWV
FRPSXWDWLRQ$WHUPLQDWLRQFRQGLWLRQLVUH Sealed
TXLUHGWRSUHYHQWDQLQILQLWHUHFXUVLRQ6HH .H\ZRUGIRUSDUHQWFODVVHVZKHQDOOWKHGL
DOVRWDLOFDOOUHFXUVLRQ UHFW VXEFODVVHV DOORZHG DUH GHILQHG LQ WKH
VDPHVRXUFHILOH
Reference Type
$W\SHZKRVHLQVWDQFHVDUHLPSOHPHQWHGDV Self-Type Annotation
REMHFWVRQWKHUXQWLPHSODWIRUP$OOUHIHU $GHFODUDWLRQLQDWUDLWRUFODVVWKDWFKDQJHV
HQFHW\SHVVXEW\SHAnyRef LWV W\SH VRPHWLPHV ZLWK DQ DOLDV IRU this

402 | Glossary

Download at WoweBook.Com
Terminal

GHILQHG self LV FRQYHQWLRQDO  $ VHOI W\SH Static Typing


FDQ EH XVHG WR LQGLFDWH GHSHQGHQFLHV RQ /RRVHO\VSHDNLQJHDUO\ELQGLQJRIW\SHLQ
RWKHUWUDLWVWKDWZLOOKDYHWREHPL[HGLQWRD IRUPDWLRQVRPHWLPHVUHIHUUHGWRDVELQGLQJ
FRQFUHWH LQVWDQFH WR UHVROYH WKH GHSHQG WRDUHIHUHQFHUDWKHUWKDQWKHYDOXHWRZKLFK
HQF\,QVRPHFDVHVWKHVHGHSHQGHQFLHVDUH WKHUHIHUHQFHLVDVVLJQHG
XVHGWRHQVXUHWKDWDQLQVWDQFHRIWKHFXU
UHQWW\SHFDQEHXVHGDVDQLQVWDQFHRIDGH Strict
SHQGHQW W\SH LQ FHUWDLQ FRQWH[WV HJ DV 8VHGWRUHIHUWRGDWDVWUXFWXUHVWKDWDUHQRW
XVHGLQWKH2EVHUYHU3DWWHUQLQ£6HOI7\SH OD]\LHWKH\DUHGHILQHG£HDJHUO\¤E\WKH
$QQRWDWLRQV DQG $EVWUDFW 7\SH 0HP H[SUHVVLRQVXVHGWRFRQVWUXFWWKHP
EHUV¤RQSDJH  Structural Type
Side-Effect-Free $VWUXFWXUDOW\SHLVOLNHDQDQRQ\PRXVW\SH
)XQFWLRQVRUH[SUHVVLRQVWKDWKDYHQRVLGH ZKHUHRQO\WKH£VWUXFWXUH¤DFDQGLGDWHW\SH
HIIHFWV PHDQLQJ WKH\ PRGLI\ QR JOREDO RU PXVWVXSSRUWLVVSHFLILHGVXFKDVPHPEHUV
£REMHFW¤VWDWH WKDWPXVWEHSUHVHQW6WUXFWXUDOW\SHVGRQRW
QDPH WKH FDQGLGDWH W\SHV WKDW FDQ PDWFK
Signature QRUGRDQ\PDWFKLQJW\SHVQHHGWRVKDUHD
)RU D IXQFWLRQ WKH QDPH SDUDPHWHU OLVW FRPPRQSDUHQWWUDLWRUFODVVZLWKWKHVWUXF
W\SHVDQGUHWXUQYDOXH)RUDPHWKRGDOVR WXUDO W\SH +HQFH VWUXFWXUDO W\SHV DUH D
LQFOXGHVWKHW\SHWKDWGHILQHVWKHPHWKRG W\SHVDIHDQDORJWRGXFNW\SLQJLQG\QDPL
FDOO\W\SHGODQJXDJHVOLNH5XE\
Single Inheritance
$FODVVREMHFWRUWUDLWFDQH[WHQGRQHSD Subtype
UHQWFODVV&RPSDUHWRPXOWLSOHLQKHULWDQFH $V\QRQ\PIRUGHULYHGW\SH
Singleton Supertype
$FODVVWKDWKDVRQO\RQHLQVWDQFH,Q6FDOD $V\QRQ\PIRUSDUHQWW\SH
VLQJOHWRQV DUH GHFODUHG XVLQJ WKH NH\ZRUG
objectLQVWHDGRIclass Symbol
$QLQWHUQHGVWULQJ/LWHUDOV\PEROVDUHZULW
Singleton Types WHQVWDUWLQJZLWKDVLQJOH£ULJKWTXRWH¤HJ
7KH XQLTXH W\SH GHVLJQDWRU WKDW H[FOXGHV 'name
SDWKGHSHQGHQFLHV,Ip1DQGp2DUHWZRGLI
IHUHQWSDWKGHSHQGHQWW\SHVWKHLUVLQJOHWRQ Tail-Call Recursion
W\SHVDUH p1.typeDQG p2.typeZKLFKPD\ $IRUPRIUHFXUVLRQZKHUHDIXQFWLRQFDOOV
EHWKHVDPH&RQWUDVWZLWKVLQJOHWRQREMHFWV LWVHOIDVWKHODVWWKLQJLWGRHVLHLWGRHVQR
6LQJOHWRQW\SHVDUHQRWVSHFLILFDOO\WKHW\SHV DGGLWLRQDOFRPSXWDWLRQVZLWKWKHUHVXOWRI
RIVLQJOHWRQREMHFWVEXWVLQJOHWRQREMHFWVGR WKH UHFXUVLYH FDOO 7KH 6FDOD FRPSLOHU ZLOO
KDYHVLQJOHWRQW\SHV RSWLPL]HWDLOFDOOUHFXUVLRQVLQWRDORRS

Stable Types Test-Driven Development


8VHG LQ WKH FRQWH[W RI SDWKGHSHQGHQW $ GHYHORSPHQW GLVFLSOLQH ZKHUH QR QHZ
W\SHVDOOEXWWKHODVWHOHPHQWVLQWKHSDWK IXQFWLRQDOLW\LVLPSOHPHQWHGXQWLODWHVWKDV
PXVW EH VWDEOH ZKLFK URXJKO\ PHDQV WKDW EHHQ ZULWWHQ WKDW ZLOO SDVV RQFH WKH IXQF
WKH\DUHHLWKHUSDFNDJHVVLQJOHWRQREMHFWV WLRQDOLW\LVLPSOHPHQWHG6HHDOVR%HKDYLRU
RUW\SHGHFODUDWLRQVWKDWDOLDVWKHVDPH 'ULYHQ'HYHORSPHQW

State Terminal
$VLQ£WKHVWDWHRIDQREMHFW¤ZKHUHLWLQ $WRNHQLQDJUDPPDUVXFKDVDNH\ZRUG
IRUPDOO\PHDQVWKHVHWRIDOOWKHFXUUHQWYDO WKDWUHTXLUHVQRIXUWKHUGHFRPSRVLWLRQ6HH
XHVRIDQREMHFW¦VILHOGV DOVRQRQWHUPLQDO

Glossary | 403

Download at WoweBook.Com
Test Double

Test Double FODVV RU WUDLWV DUH SDUDPHWHUL]HG W\SHV ,Q


:KHQWHVWLQJWKHEHKDYLRURIRQHREMHFWD 6FDODtypeLVDOVRDNH\ZRUG:KHQLQGLFD
WHVWGRXEOHLVDQRWKHUREMHFWWKDWVDWLVILHVD WHGLQWKHWH[WZHVRPHWLPHVXVHWKHWHUP
GHSHQGHQF\ LQ WKH REMHFW XQGHU WHVW 7KH W\SHWRUHIHUWRDFODVVREMHFWRUWUDLWJHQHU
WHVWGRXEOHPD\DVVLVWLQWKHWHVWLQJSURFHVV LFDOO\
SURYLGHFRQWUROOHGWHVWGDWDDQGEHKDYLRUV
Type Annotation
DQGPRGLI\WKHLQWHUDFWLRQEHWZHHQWKHRE
$QH[SOLFLWGHFODUDWLRQRIWKHW\SHRIDYDOXH
MHFWXQGHUWHVWDQGWKHWHVWGRXEOH6SHFLILF
HJcount: IntZKHUHIntLVWKHW\SHDQQR
W\SHV RI WHVW GRXEOHV LQFOXGH £IDNHV¤
WDWLRQ$W\SHDQQRWDWLRQLVUHTXLUHGZKHQ
£PRFNV¤DQG£VWXEV¤
W\SHLQIHUHQFHFDQ¦WEHXVHG,Q6FDODIXQF
Trait WLRQ SDUDPHWHUV UHTXLUH W\SH DQQRWDWLRQV
$ FODVVOLNH HQFDSVXODWLRQ RI VWDWH ILHOGV DQGDQQRWDWLRQVDUHUHTXLUHGLQVRPHRWKHU
DQG EHKDYLRU PHWKRGV  WKDW LV XVHG IRU FRQWH[WV ZKHUH WKH W\SH FDQ¦W EH LQIHUUHG
PL[LQFRPSRVLWLRQ=HURRUPRUHWUDLWVFDQ HJIRUUHWXUQYDOXHVRIVRPHIXQFWLRQV
EH PL[HG LQWR FODVV GHFODUDWLRQV RU ZKHQ
Type Bounds
FUHDWLQJLQVWDQFHVGLUHFWO\HIIHFWLYHO\FUHDW
&RQVWUDLQWVRQWKHDOORZHGW\SHVWKDWFDQEH
LQJDQDQRQ\PRXVFODVV
XVHG IRU D SDUDPHWHU LQ D SDUDPHWHUL]HG
Trampoline W\SHRUDVVLJQHGWRDQDEVWUDFWW\SH,Q6FDOD
$ORRSWKDWLWHUDWHVWKURXJKDOLVWRIIXQF WKH H[SUHVVLRQ A <: B GHILQHV DQ XSSHU
WLRQVLQYRNLQJHDFKLQWXUQ7KHPHWDSKRU ERXQGRQALWPXVWEHDVXEW\SHRUWKHVDPH
RIERXQFLQJWKHIXQFWLRQVRIIDWUDPSROLQH DVB7KHH[SUHVVLRQA >: BGHILQHVDORZHU
LVWKHVRXUFHRIWKHQDPH,WFDQEHXVHGWR ERXQG RQ A LW PXVW EH D VXSHUW\SH RU WKH
UHZULWHDIRUPRIUHFXUVLRQZKHUHDIXQFWLRQ VDPHDVB
GRHVQ¦WFDOOLWVHOIEXWUDWKHUFDOOVDGLIIHUHQW
Type Constructor
IXQFWLRQWKDWLQYRNHVWKHRULJLQDOIXQFWLRQ
,QIRUPDOO\ D SDUDPHWHUL]HG W\SH LV VRPH
DQGVRIRUWKEDFNDQGIRUWK7KHUHLVDSUR
WLPHVFDOOHGDW\SHFRQVWUXFWRUDOWKRXJKD
SRVDOIRUWKH6FDODYHUVLRQFRPSLOHUWR
£QRQSDUDPHWHUL]HG¤ W\SH LV UHDOO\ D W\SH
LQFOXGHDWUDPSROLQHLPSOHPHQWDWLRQ
FRQVWUXFWRUWRRMXVWZLWK]HURSDUDPHWHUV
Tuple 7KHDQDORJ\ZLWKDQLQVWDQFHFRQVWUXFWRULV
$JURXSLQJRIWZRRUPRUHLWHPVRIDUELWUDU\ WKDW\RXVSHFLI\VSHFLILFFRQFUHWHW\SHVIRU
W\SHV LQWR D £&DUWHVLDQ SURGXFW¤ ZLWKRXW WKH SDUDPHWHUV WR FUHDWH D QHZ FRQFUHWH
ILUVW GHILQLQJ D FODVV WR KROG WKHP /LWHUDO W\SHMXVWDV\RXVSHFLI\YDOXHVWRDQLQVWDQFH
WXSOHYDOXHVDUHZULWWHQLQSDUHQWKHVHVDQG FRQVWUXFWRUWRFUHDWHDQLQVWDQFH
VHSDUDWHGE\FRPPDVHJ (x1, x2, ...)
Type Designators
7KH\DUHILUVWFODVVYDOXHVVR\RXFDQDVVLJQ
7KHFRQYHQWLRQDOW\SH,'VFRPPRQO\XVHG
WKHPWRYDULDEOHVSDVVWKHPDVYDOXHVDQG
HJ class Person object O { type t }
UHWXUQWKHPIURPIXQFWLRQV7XSOHVDUHUHS
7KH\ DUH DFWXDOO\ D VKRUWKDQG V\QWD[ IRU
UHVHQWHGE\TupleNFODVVHVIRU1EHWZHHQ
W\SHSURMHFWLRQV
DQGLQFOXVLYH
Type Erasure
Type
$SURSHUW\RIWKHJHQHULFVW\SHPRGHORQWKH
$FDWHJRUL]DWLRQRIDOORZHGVWDWHVDQGRS
-90:KHQDW\SHLVFUHDWHGIURPDJHQHULF
HUDWLRQVRQWKRVHVWDWHVLQFOXGLQJWUDQVIRU
WKHLQIRUPDWLRQDERXWWKHVSHFLILFW\SHVVXE
PDWLRQVIURPRQHVWDWHWRDQRWKHU7KHW\SH
VWLWXWHGIRUWKHW\SHSDUDPHWHUVLVQRWVWRUHG
RIDQLQVWDQFHLVWKHFRPELQDWLRQRILWVGH
LQWKHE\WHFRGHDQGLVWKHUHIRUHQRWDYDLOD
FODUHG FODVV H[SOLFLWO\ QDPHG RU DQRQ\
EOHDWUXQWLPH6FDODPXVWIROORZWKHVDPH
PRXV  PL[HGLQ WUDLWV DQG WKH VSHFLILF
PRGHO 6R IRU H[DPSOH LQVWDQFHV RI
W\SHVXVHGWRUHVROYHDQ\SDUDPHWHUVLIWKH

404 | Glossary

Download at WoweBook.Com
Visibility

List[String] DQG List[Int] DUH LQGLVWLQ KDQGOHV LQVWDQWLDWLRQ $OO WKH LQVWDQFHV RI
JXLVKDEOH&RQWUDVWZLWKUHLILHGW\SHV YDOXHW\SHVDUHLPPXWDEOHYDOXHREMHFWV
Type Inference 7KHWHUPYDOXHW\SHLVDOVRXVHGWRPHDQWKH
,QIHUULQJ WKH W\SH RI D YDOXH EDVHG RQ WKH FDWHJRULHVRIW\SHVIRULQVWDQFHV7KDWLVWKH
FRQWH[W LQ ZKLFK LW LV XVHG UDWKHU WKDQ W\SH RI HYHU\ LQVWDQFH PXVW IDOO LQWR RQH
UHO\LQJRQH[SOLFLWW\SHDQQRWDWLRQV6RPH RI VHYHUDO FDWHJRULHV DQQRWDWHG W\SHV
WLPHVFDOOHGLPSOLFLWW\SLQJ FRPSRXQGW\SHVIXQFWLRQW\SHVLQIL[W\SHV
SDUDPHWHUL]HG W\SHV WXSOHV W\SH GHVLJQD
Type Projections WRUVW\SHSURMHFWLRQVDQGVLQJOHWRQW\SHV
$ZD\WRUHIHUWRDW\SHQHVWHGZLWKLQDQ
RWKHU W\SH )RU H[DPSOH LI D W\SH t LV GH Variable
FODUHGLQDFODVV CWKHQWKHW\SHSURMHFWLRQ $QDPHGUHIHUHQFHWRDYDOXH,IWKHYDULDEOH
IRUtLVC#t LV GHFODUHG ZLWK WKH val NH\ZRUG D QHZ
YDOXHFDQ¦WEHDVVLJQHGWRWKHYDULDEOH,IWKH
Type Variance YDULDEOHLVGHFODUHGZLWKWKHvarNH\ZRUGD
:KHQDSDUDPHWHUL]HGW\SHLVGHFODUHGWKH QHZYDOXHFDQEHDVVLJQHGWRWKHYDULDEOH
YDULDQFHEHKDYLRUXQGHULQKHULWDQFHRIHDFK 7KHYDOXHDYDULDEOHUHIHUHQFHVPXVWEHW\SH
W\SHSDUDPHWHUFDQEHVSHFLILHGXVLQJDW\SH FRPSDWLEOH ZLWK WKH GHFODUHG RU LQIHUUHG
YDULDQFHDQQRWDWLRQRQWKHW\SHV\PERO W\SHRIWKHYDULDEOH
Type Variance Annotation View
2Q D W\SH SDUDPHWHU LQ D SDUDPHWHUL]HG $QLPSOLFLWYDOXHRIIXQFWLRQW\SHWKDWFRQ
W\SHVD+SUHIL[HGWRWKHW\SHV\PEROLVXVHG YHUWVDW\SHAWRB7KHIXQFWLRQKDVWKHW\SH
WRLQGLFDWHFRYDULDQFH$-SUHIL[RQWKHW\SH A => BRU(=> A) => B ,QWKHODWHUFDVHWKH
V\PERO LV XVHG WR LQGLFDWH FRQWUDYDULDQFH (=> A)LVDE\QDPHSDUDPHWHU $QLQVFRSH
1RYDULDQFHDQQRWDWLRQLVXVHGWRLQGLFDWH LPSOLFLW W\SH FRQYHUVLRQ PHWKRG ZLWK WKH
LQYDULDQFH WKHGHIDXOW  VDPHVLJQDWXUHFDQDOVREHXVHGDVDYLHZ
Upper Type Bounds View Bounds
6HHW\SHERXQGV $ W\SH VSHFLILFDWLRQ RI WKH IRUP A <% B
Value ZKLFKVD\VWKDWDQ\W\SHFDQEHXVHGIRU A
7KHDFWXDOVWDWHRIDQLQVWDQFHXVXDOO\LQWKH DVORQJDVDQLQVFRSHYLHZH[LVWVWKDWFDQ
FRQWH[W RI D YDULDEOH WKDW UHIHUV WR WKH LQ FRQYHUWDQAWRDB
VWDQFH6HHDOVRYDOXHW\SH Visibility
Value Object 7KHVFRSHLQZKLFKDGHFODUHGW\SHRUW\SH
$QLPPXWDEOHLQVWDQFHRUREMHFW PHPEHU LV YLVLEOH WR RWKHU W\SHV DQG
PHPEHUV
Value Type
$ VXEFODVV RI AnyVal WKDW ZUDSV D FRUUH
VSRQGLQJ QRQREMHFW £SULPLWLYH¤ W\SH RQ
WKHUXQWLPHSODWIRUP HJ-90DQG1(7 
7KH YDOXH W\SHV DUH Boolean Char Byte
DoubleFloatLongIntDQGShort UnitLV
DOVRDYDOXHW\SH $OODUHGHFODUHGabstract
finalVRWKH\FDQ¦WEHXVHGLQnew VH[SUHV
VLRQV,QVWHDGSURJUDPVVSHFLI\OLWHUDOYDO
XHVHJ 3.14IRUD DoubleRUXVHPHWKRGV
WKDWUHWXUQQHZYDOXHV7KH6FDODUXQWLPH

Glossary | 405

Download at WoweBook.Com
Download at WoweBook.Com
Index

RPLWWLQJLQPHWKRGLQYRFDWLRQV
Symbols VXEVWLWXWLQJFXUO\EUDFHVIRULQPHWKRGFDOO
 H[FODPDWLRQSRLQW 
PHWKRGVHQGLQJPHVVDJHVWR$FWRUV  DVWHULVN
 PXOWLSOLFDWLRQRSHUDWRUHQFRGLQJLQ-DYD
PHWKRGVHQGLQJPHVVDJHVWR$FWRUV LGHQWLILHUV
  QRWHTXDO PHWKRG RSHUDWRUSUHFHGHQFH
  QRWHTXDO RSHUDWRU ]HURRUPRUHUHSHWLWLRQVLQSURGXFWLRQUXOH
HQFRGLQJLQ-DYDLGHQWLILHUV 
RSHUDWRUSUHFHGHQFH  SOXVVLJQ
 TXRWDWLRQPDUNVGRXEOH PHWKRGDSSHQGLQJWROLVWV
HQFORVLQJVWULQJOLWHUDOV HQFRGLQJLQ-DYDLGHQWLILHUV
HVFDSLQJLQFKDUDFWHUOLWHUDOV RSHUDWRUSUHFHGHQFH
WULSOHVRIGRXEOHTXRWHVERXQGLQJPXOWL VSHFLI\LQJDWOHDVWRQHUHSHWLWLRQLQ
OLQHVWULQJOLWHUDOV SURGXFWLRQUXOH
 SRXQGVLJQ YDULDQFHDQQRWDWLRQV
HQFRGLQJLQ-DYDLGHQWLILHUV  PLQXVVLJQ
XVHLQW\SHSURMHFWLRQV HQFRGLQJLQ-DYDLGHQWLILHUV
 GROODUVLJQ LQLGHQWLILHUV RSHUDWRUSUHFHGHQFH
 SHUFHQWVLJQ YDULDQFHDQQRWDWLRQV
HQFRGLQJLQ-DYDLGHQWLILHUV ! ULJKWDUURZ RSHUDWRU
RSHUDWRUSUHFHGHQFH  GRW
 DPSHUVDQG LQIL[RSHUDWRUQRWDWLRQ
 DQG RSHUDWRU RPLWWLQJLQPHWKRGFDOOV
HQFRGLQJLQ-DYDLGHQWLILHUV SHULRGGHOLPLWHGSDWKH[SUHVVLRQV
RSHUDWRUSUHFHGHQFH  VODVK


 TXRWDWLRQPDUNVVLQJOH   LQPXOWLOLQHFRPPHQWV
HQFORVLQJFKDUDFWHUOLWHUDOV LQVLQJOHOLQHFRPPHQWV
LQV\PEROOLWHUDOV GLYLVLRQRSHUDWRUHQFRGLQJLQ-DYD
  SDUHQWKHVHV LGHQWLILHUV
FDSWXUHJURXSVLQUHJXODUH[SUHVVLRQV RSHUDWRUSUHFHGHQFH
LQPHWKRGLQYRFDWLRQVGURSSLQJ  FRORQ
RPLWWLQJIRUE\QDPHIXQFWLRQSDUDPHWHU  FRQVWUXFWRU PHWKRG
 H[WUDFWLQJKHDGDQGWDLORIOLVW
RPLWWLQJLQPHWKRGGHILQLWLRQV SUHSHQGLQJWRDOLVW

:H¦GOLNHWRKHDU\RXUVXJJHVWLRQVIRULPSURYLQJRXULQGH[HV6HQGHPDLOWRLQGH[#RUHLOO\FRP

407

Download at WoweBook.Com
FODVV HQFRGLQJLQ-DYDLGHQWLILHUV
? IROG5LJKW DQG IROG/HIW  HVFDSLQJGRXEOHTXRWHVLQVWULQJOLWHUDOV
HQFRGLQJLQ-DYDLGHQWLILHUV SURMHFWLRQIXQFWLRQV
PHWKRGVHQGLQJLQULJKWDVVRFLDWLYH ?DQG??RSHUDWRUVIRUGRFXPHQWVWUXFWXUHV
LQYRFDWLRQ 
RSHUDWRUSUHFHGHQFH A FDUHW
VHSDUDWRUEHWZHHQLGHQWLILHUVDQGW\SH HQFRGLQJLQ-DYDLGHQWLILHUV
DQQRWDWLRQV RSHUDWRUSUHFHGHQFH
 VHPLFRORQ B XQGHUVFRUH
HQGLQJSURGXFWLRQUXOHGHILQLWLRQV LQLGHQWLILHUV
HQGLQJVWDWHPHQWVLQ6FDODFRGH PHWKRGFKDLQLQJDQGIXQFWLRQOLWHUDO
VHSDUDWRUVLQIRUH[SUHVVLRQ VKRUWKDQGV
! DQJOHEUDFNHWV SODFHKROGHULQLPSRUWVIXQFWLRQOLWHUDOV
 OHVVWKDQ RSHUDWRU HWF
HQFRGLQJLQ-DYDLGHQWLILHUV UHVHUYHGZRUG
LQGLFDWLQJYLHZERXQGLQW\SH ZLOGFDUGFKDUDFWHULQ6FDOD
GHFODUDWLRQ CC EDFNTXRWHV LQOLWHUDOV
 OHIWDUURZ RSHUDWRUJHQHUDWRUV ^` FXUO\EUDFHV
 HQFORVLQJFODVVERG\
XVHLQSDUDPHWHUL]HGDQGDEVWUDFWW\SH HQFORVLQJIRUH[SUHVVLRQV
GHFODUDWLRQV LQPHWKRGGHFODUDWLRQV
! JUHDWHUWKDQ RSHUDWRU VXEVWLWXWLQJIRUSDUHQWKHVHVLQPHWKRGFDOO
HQFRGLQJLQ-DYDLGHQWLILHUV 
!FRQVWUDLQLQJDOORZHGW\SHVLQ ^LQGLFDWLQJPRUHFRGHRQQH[WOLQH
SDUDPHWHUL]HGDQGDEVWUDFWW\SH _ YHUWLFDOEDU
GHFODUDWLRQV HQFRGLQJLQ-DYDLGHQWLILHUV
LQPHWKRGQDPHV RSHUDWRUSUHFHGHQFH
RSHUDWRUSUHFHGHQFH RUFDVHLQSDUVHUJUDPPDU
 HTXDOVVLJQ __ RU RSHUDWRU
 HTXDOV PHWKRG a WLOGH
 HTXDOV RSHUDWRU FDVHFODVVGHILQHGE\3DUVHUVWUDLW
!LQIXQFWLRQOLWHUDOV HQFRGLQJLQ-DYDLGHQWLILHUV
DVVLJQPHQWRSHUDWRU aa!DQGaFRPELQDWRURSHUDWRUV
HQFRGLQJLQ-DYDLGHQWLILHUV
LQPHWKRGGHILQLWLRQV
PLVVLQJ
A
RSHUDWRUSUHFHGHQFH DEVWUDFWFODVVHV
" TXHVWLRQPDUN DEVWUDFWNH\ZRUG
HQFRGLQJLQ-DYDLGHQWLILHUV DEVWUDFWW\SHPHPEHUV
# DWVLJQ RYHUULGLQJDEVWUDFWPHWKRGV
HQFRGLQJLQ-DYDLGHQWLILHUV DEVWUDFWW\SHV¡
H[WUDFWLQJYDOXHRI;0/DWWULEXWHV FRPELQHGZLWKVHOIW\SHDQQRWDWLRQV
PDUNLQJDQQRWDWLRQV GHILQHG
>@ VTXDUHEUDFNHWV RYHUULGLQJ¡
HQFORVLQJRSWLRQDOLWHPVLQSDUVHUJUDPPDU SDUDPHWHUL]HGW\SHVYHUVXV
 DEVWUDFWLRQ
XVHZLWKSDUDPHWHUL]HGW\SHV DFFHVVPRGLILHUNH\ZRUGV
? EDFNVODVK $FWRUV¡
LQFKDUDFWHUHVFDSHVHTXHQFHV LQDEVWUDFW
$FWRUFODVV

408 | Index

Download at WoweBook.Com
$FWRUFODVVDQGREMHFW $23 VHHDVSHFWRULHQWHGSURJUDPPLQJ
$FWRUPRGHORIFRQFXUUHQF\ $SDFKH0,1$
GHILQHG DSSOLFDWLRQGHVLJQ¡
HIIHFWLYHXVHRI DQQRWDWLRQV¡
H[DPSOH¡ 'HVLJQE\&RQWUDFW
H[DPSOHXVLQJVOHHSLQJEDUEHUSUREOHP GHVLJQSDWWHUQV¡
¡ HIIHFWLYHWUDLWGHVLJQ¡
IDFWRU\PHWKRGIRUFUHDWLQJ HQXPHUDWLRQVYHUVXVFDVHFODVVHVDQG
PDLOER[ SDWWHUQPDWFKLQJ
PHWKRGVOLVWHG HQXPHUDWLRQVYHUVXVSDWWHUQPDWFKLQJ
VHQGLQJPHVVDJHVWR ¡
VKRUWFXWRSHUDWRUVXVHGZLWK H[FHSWLRQVDQGDOWHUQDWLYHV
XVLQJZLWK0,1$1,2DQG1DJJDWLOLEUDU\ QXOOVYHUVXV2SWLRQV
IRU6073VHUYHU¡ VFDODEOHDEVWUDFWLRQV
DFWRUVPD[3RRO6L]HV\VWHPSURSHUW\ DSSOLFDWLRQV
DGYLFH LQ$23  DSSO\PHWKRG¡
DOWHUQDWLYHFRPSRVLWLRQ IRUFROOHFWLRQV
DQGRSHUDWRU  REMHFWVZLWKFRQVLGHUHGDVIXQFWLRQV
DQQRWDWHGW\SHV DULW\
$QQRWDWLRQFODVV $UUD\FODVV
6FDODDQQRWDWLRQVGHULYHGIURP DSSO\PHWKRG
DQQRWDWLRQV¡ VDPH(OHPHQWVPHWKRG
DGYDQWDJHVDQGGLVDGYDQWDJHVRI $UUD\REMHFWDSSO\PHWKRGRYHUORDGHGIRU
DYDLODEOHRQO\LQ6FDODYHUVLRQRUODWHU $Q\9DODQG$Q\5HIW\SHV
 $UUD\%XIIHUREMHFW
GHILQHG DUUD\VFRPSDULQJIRUHTXDOLW\
QHVWLQJ DUURZRSHUDWRU  
6FDODDQQRWDWLRQVGHULYHGIURP$QQRWDWLRQ $UURZ$VVRFFODVV
 DVSHFWRULHQWHGSURJUDPPLQJ $23 
6FDODDQQRWDWLRQVGHULYHGIURP GHILQHG
6WDWLF$QQRWDWLRQ $VSHFW-OLEUDU\¡
#VFDODUHIOHFW%HDQ3URSHUW\ $WRP)HHGFODVV H[DPSOH 
DQRQ\PRXVFODVVHV DWWULEXWHV
FUHDWLQJ DX[LOLDU\FRQVWUXFWRUV
$QW6FDODSOXJLQIRU
$Q\FODVV
  QRWHTXDO PHWKRG
B
 HTXDOV PHWKRG EDQJPHWKRG VHH H[FODPDWLRQSRLQW XQGHU
$Q\REMHFW 6\PEROV
$Q\5HIFODVV EDVHFODVVHV
 HTXDOV PHWKRG EDVHW\SH
HTDQGQHPHWKRGV %'' %HKDYLRU'ULYHQ'HYHORSPHQW 
$Q\5HIREMHFW %''V\QWD[SURYLGHGE\6FDOD7HVW
GLUHFWDQGLQGLUHFWVXEW\SHV GHILQHG
UHIOHFWLRQPHWKRGV VSHFLILFDWLRQH[HUFLVLQJFRPELQHG%XWWRQ
$Q\9DOREMHFW DQG6XEMHFWW\SHV
GLUHFWVXEW\SHV 6SHFVOLEUDU\¡
$Q\9DOW\SHVFRQYHUVLRQWR-DYDSULPLWLYHV %LJ'HFLPDOFODVV
 EORJJLQJV\VWHP H[DPSOH ¡
$WRP)HHGFODVV

Index | 409

Download at WoweBook.Com
ERROHDQOLWHUDOV DEVWUDFW
ERXQGYDULDEOHV DGGLQJQHZPHWKRGVWR
EUHDNPHWKRG EDVLFVRI
EXLOGWRROV GHFODUDWLRQRIFODVVHVDVVLQJOHWRQV
%XLOGUWRRO GHILQHG
E\QDPHSDUDPHWHUV GHULYHGRYHUULGLQJYDOVGHFODUHGLQSDUHQW
GHILQHG FODVVHV
E\YDOXHSDUDPHWHUV -'.DQG1(7XVHLQ6FDOD
GHILQHG QHVWHG
RYHUULGLQJDEVWUDFWDQGFRQFUHWHILHOGVLQ

C RYHUULGLQJDEVWUDFWDQGFRQFUHWHPHWKRGV
& 
DEVWUDFWPHWKRGV SDUHQW
RYHUULGHNH\ZRUGIRUFRQFUHWHPHWKRGV VHDOHGFODVVKLHUDUFKLHV¡
WKLVNH\ZRUG WUDLWVYHUVXV
& 8SSHUFODVV H[DPSOH 
PXOWLSOHLQKHULWDQFH &ODVVILOH$QQRWDWLRQFODVV
WHPSODWHV &OLFNDEOHWUDLW H[DPSOH 
&VXSHUW\SH FOLHQWV
&WKLVW\SH FORVXUHV
&DNH3DWWHUQ¡ GHILQHG
FDOOVLWH VHHGHFODUDWLRQVLWH &/5 &RPPRQ/DQJXDJH5XQWLPH 6FDOD
FDOOE\QDPHSDUDPHWHUV UXQQLQJRQ
FDSWXUHJURXSVGHILQLQJLQUHJXODUH[SUHVVLRQV FRGHH[DPSOHVLQWKLVERRN[L[
 FRGHRUJDQL]LQJLQILOHVDQGQDPHVSDFHV
FDVHFODVVHV¡ FRGHFIRU6073 H[DPSOH 
ELQDU\RSHUDWLRQV FROOHFWLRQV
FRS\PHWKRGLQ6FDOD DSSO\DQGXQDSSO\6HTPHWKRGV
GHILQHG PXWDEOHDQGLPPXWDEOH
GHILQLQJIRUSDWWHUQPDWFKLQJ FRPPDQGOLQHWRROV¡
HQXPHUDWLRQVDVDOWHUQDWLYHWR LQIRUPDWLRQRQ
HQXPHUDWLRQVYHUVXV VED]
LQKHULWDQFH VFDOD¡
SDWWHUQPDWFKLQJRQ VFDODF
FDVHFODXVHVELQGLQJQHVWHGYDULDEOHVLQ VFDODGRF
FDVHNH\ZRUG VFDODSMDYDSDQGMDG
FDVHFODVVH[DPSOH FRPPHQWV
FDVHREMHFWV FRPSDQLRQFODVVHV
FDVHVWDWHPHQWV GHILQHG
SDWWHUQPDWFKLQJYHUVXV FRPSDQLRQREMHFWV¡
FDVHVLQSDWWHUQPDWFKLQJ DSSO\DQGXQDSSO\6HTPHWKRGVIRU
XQUHDFKDEOHFDVH FROOHFWLRQV
FKDUDFWHUOLWHUDOV DSSO\PHWKRG¡
FKDUDFWHUV FRQYHUVLRQPHWKRGVGHILQHGLQ
RSHUDWRUFKDUDFWHUVHQFRGLQJLQ-DYD FUHDWLRQIRUFDVHFODVVHV
XVHGLQLGHQWLILHUV GHILQHG
FKLOGW\SHV -DYDVWDWLFPHWKRGVDQG
FODVVNH\ZRUG 0DSDQG6HW
FODVVHV

410 | Index

Download at WoweBook.Com
PHWKRGVGHILQHGLQYLVLELOLW\WR-DYDFRGH FRQWUDYDULDQWVXEFODVVLQJ
 FRYDULDQFHRUFRYDULDQW
3DLUREMHFWIRU3DLUFODVV FRYDULDQWVSHFLDOL]DWLRQ
XQDSSO\PHWKRG¡ FRYDULDQWVXEFODVVLQJ
FRPSLOHGFRPPDQGOLQHWRROFRQYHUWLQJ #FSV FRQWLQXDOSDVVLQJVW\OH DQQRWDWLRQ
VFULSWWR 
FRPSLOHU VHHVFDODFFRPSLOHU FURVVFXWWLQJFRQFHUQV
FRPSLOLQJYHUVXVLQWHUSUHWLQJ FURVVSODWIRUPLQVWDOOHU O]3DFN 
FRPSRQHQWPRGHOIXQFWLRQDOSURJUDPPLQJ FXUULHGIXQFWLRQV
DQG FXUU\LQJ
FRPSRQHQWV
GHILQHG
ILQHJUDLQHGYLVLELOLW\UXOHVLQ6FDOD
D
LPSOHPHQWLQJDVWUDLWV GDWDW\SHV¡
FRPSRXQGW\SHV DEVWUDFW
GHILQHG SDUDPHWHUL]HGW\SHVYHUVXV
FRPSUHKHQVLRQV $Q\9DOW\SHVFRQYHUVLRQWR-DYDSULPLWLYHV
FRQFUHWHW\SHV 
FRQFXUUHQF\¡ GHILQHG
$FWRUPRGHORI GRFXPHQWDWLRQIRU6FDODW\SHV\VWHP
HYHQWEDVHG H[LVWHQWLDOW\SHV
-DYDDQG LPSRUWLQJW\SHVDQGWKHLUPHPEHUV
SUREOHPVRIVKDUHGV\QFKURQL]HGVWDWH LQIHUULQJW\SHLQIRUPDWLRQ¡
 LQILQLWHGDWDVWUXFWXUHVDQGOD]\YDOV
WUDGLWLRQDOXVLQJWKUHDGLQJDQGHYHQWV 1RWKLQJDQG1XOO
¡ SDUDPHWHUL]HGW\SHV
HYHQWV¡ SDWKGHSHQGHQWW\SHV
RQHRIIWKUHDGV SDWWHUQPDWFKLQJRQW\SH
XVLQJMDYDXWLOFRQFXUUHQW UHIOHFWLRQ
XVLQJ$FWRUV¡ 6FDOD¦VVRSKLVWLFDWHGW\SHV\VWHP
$FWRUVLQDEVWUDFW VHOIW\SHDQQRWDWLRQV¡
$FWRUVLQ6FDOD¡ VWDWLFYHUVXVG\QDPLFW\SLQJ
FRQGLWLRQDORSHUDWRUV VWUXFWXUDOW\SHV
&RQVROHSULQWOQ  PHWKRG W\SHERXQGV¡
FRQVWDQWLGHQWLILHUV W\SHKLHUDUFK\LQ6FDOD
FRQVWDQWV YDOXHW\SHV¡
GHIDXOWDUJXPHQWYDOXHV YDULDQFHXQGHULQKHULWDQFH
GHILQLQJ YDULDQFHLQ6FDODYHUVXV-DYD¡
FRQVWUXFWRUV¡ YDULDQFHRIPXWDEOHW\SHV
FDVHFODVV GHFLPDOLQWHJHUOLWHUDOV
FRQVWUDLQWVRQDGYDQWDJHVDQG GHFODUDWLRQVLWH
GLVDGYDQWDJHRI GHFODUDWLRQV
SDUHQWFODVVFRQVWUXFWRUVFDOOLQJ DQQRWDWLRQVLQ¡
FRQWH[WIUHHJUDPPDUV RUGHURIGHFODUDWLRQWUDLWVDQG
FRQWUDFW YLVLELOLW\PRGLILHUVLQ
GHILQHG GHFODUDWLYHFRPSRVLWLRQRIWUDLWV
FRQWUDFWXDOFRQVWUDLQWVLQ'HVLJQE\&RQWUDFW GHFODUDWLYHSURJUDPPLQJ
 GHFRPSLOHUV VFDODSMDYDSDQGMDG 
FRQWUDYDULDQFHRUFRQWUDYDULDQW GHHSPDWFKLQJ
GHINH\ZRUG

Index | 411

Download at WoweBook.Com
GHIDXOWDUJXPHQWYDOXH
GHILQLWLRQVPHWKRG
E
GHSHQGHQF\LQMHFWLRQ ', HDJHUPDWFKLQJ
GHILQHG (%1) ([WHQGHG%DFNXV1DXU)RUP JUDPPDU
6SULQJ)UDPHZRUN QRWDWLRQ
XVLQJ&DNH3DWWHUQ¡ H[WHUQDOSD\UROO'6/JUDPPDU
GHULYHGW\SHV (FOLSVH,'(
DFFHVVWRPHPEHUVRISDUHQWW\SHV GHYHORSLQJ6FDODDSSOLFDWLRQV
'HVLJQE\&RQWUDFW LQVWDOOLQJ6FDODSOXJLQ
%DQN$FFRXQW6SHFREMHFW H[DPSOH  (LIIHOODQJXDJH
GHILQHG (LWKHUREMHFW
GHVLJQSDWWHUQV¡ HOVHFODXVH LIVWDWHPHQWV 
DOWHUQDWLYHWR9LVLWRU3DWWHUQ¡ (PDFVHGLWRU
GHSHQGHQF\LQMHFWLRQ ', LPSOHPHQWDWLRQ HQFDSVXODWLRQ
&DNH3DWWHUQ¡ GHILQHG
GLDPRQGRIGHDWK SUREOHPZLWKPXOWLSOH YLVLELOLW\UXOHVDQG
LQKHULWDQFH  (QVXULQJFODVV
GRZKLOHORRSV HQXPHUDWHGW\SHV
GRFXPHQWDWLRQ (QXPHUDWLRQFODVV
6FDODWRROVDQG$3,V (QXPHUDWLRQ9DOXHFODVV
6FDODW\SHV\VWHP HQXPHUDWLRQV¡
'6/V 'RPDLQ6SHFLILF/DQJXDJHV ¡ DGYDQWDJHVDQGGLVDGYDQWDJHVRI
 FDVHFODVVHVDQGSDWWHUQPDWFKLQJYHUVXV
EHQHILWVDQGGUDZEDFNVRI 
GHILQHG +WWS0HWKRGREMHFW H[DPSOH ¡
H[WHUQDO'6/VZLWKSDUVHUFRPELQDWRUV VFDOD(QXPHUDWLRQFODVV
¡ HTPHWKRG $Q\5HI 
JHQHUDWLQJSD\FKHFNVZLWKH[WHUQDO'6/ HTXDOLW\RIREMHFWV
¡ HTXDOVPHWKRG
SDUVHUFRPELQDWRUV FDVHFODVVFRPSDULVRQV
SD\UROOH[WHUQDO'6/¡ HTXDOVRSHUDWRU 
6FDODLPSOHPHQWDWLRQRIH[WHUQDO'6/ HYHQWV
JUDPPDU¡ XVLQJIRUFRQFXUUHQF\¡
LQWHUQDO'6/IRUSD\UROODSSOLFDWLRQ H[FHSWLRQKDQGOLQJSDWWHUQPDWFKLQJXVLQJWU\
H[DPSOH ¡ FDWFKDQGILQDOO\FODXVHV
DSSO\PHWKRGV H[FHSWLRQV
LPSOLFLWFRQYHUVLRQVDQGXVHUGHILQHG #WKURZVDQQRWDWLRQDQG
W\SHV #XQFKHFNHGDQQRWDWLRQDQG
LQIL[RSHUDWRUQRWDWLRQ DQGDOWHUQDWLYHVWR
SD\UROO$3,¡ WKURZLQJ
SD\UROOLQWHUQDO'6/ H[HFXWLQJDVFULSW
SD\UROOUXOHV'6/LPSOHPHQWDWLRQ¡ H[LVWHQWLDOW\SHV
 GHILQHG
LQWHUQDOYHUVXVH[WHUQDO H[DPSOHVRI
GXFNW\SLQJ H[SHFWDWLRQV
GHILQHG H[SRQHQWLDOVZLWKIORDWLQJSRLQWOLWHUDOV
G\QDPLFW\SLQJ H[SUHVVLRQV
YHUVXVVWDWLFW\SLQJ IRUH[SUHVVLRQ
G\QDPLFDOO\W\SHGODQJXDJHV LIVWDWHPHQWVDV
H[WHQGVNH\ZRUG

412 | Index

Download at WoweBook.Com
H[WHUQDO'6/V IRUPDOSDUDPHWHUV
VHHDOVR'6/V )3 VHHIXQFWLRQDOSURJUDPPLQJ
LQWHUQDO'6/VYHUVXV IUHHYDULDEOHV
H[WUDFWRUV IVF IDVWVFDODFRPSLOHU WRRO
WUDQVODWLQJUHJXODUH[SUHVVLRQFDSWXUH IXQFWLRQOLWHUDOV
JURXSVWR FORVXUHVDQG
XQDSSO\PHWKRGV GHILQHG
XVHLQSDWWHUQPDWFKLQJFDVHVWDWHPHQWV SDVVLQJWRIRUHDFK
 SDVVLQJWRPHWKRGIRUSDWWHUQPDWFKLQJ
IXQFWLRQW\SHV
GHILQHG
F )XQFWLRQFXUULHGPHWKRG
IDFWRU\PHWKRGVDSSO\PHWKRGDV )XQFWLRQDO-DYDSURMHFW
IDPLO\SRO\PRUSKLVP IXQFWLRQDOSURJUDPPLQJ¡
)LERQDFFLVHTXHQFHFDOFXODWLQJ FDOOE\QDPHDQGFDOOE\YDOXH
ILHOGV FRPSRQHQWPRGHODQG
FRPSDULVRQWR-DYDFODVVOHYHO FXUU\LQJ
GHILQHG GDWDVWUXFWXUHV
LQGLVWLQJXLVKDEOHIURPDFFHVVRUPHWKRGV OLVWV
RYHUULGLQJ¡ PDSV
PXWDEOH GHILQLWLRQRI
RUGHURILQLWLDOL]DWLRQXVLQJOD]\YDOV ILOWHULQJRSHUDWLRQV
RYHUULGLQJDEVWUDFWDQGFRQFUHWHILHOGV IROGLQJDQGUHGXFLQJRSHUDWLRQV¡
RYHUULGLQJDEVWUDFWDQGFRQFUHWHILHOGVLQ IXQFWLRQVLQPDWKHPDWLFV
FODVVHV LPSOLFLWFRQYHUVLRQV
RYHUULGLQJDEVWUDFWDQGFRQFUHWHILHOGVLQ LPSOLFLWIXQFWLRQSDUDPHWHUV
WUDLWV¡ LPSOLFLWVFDXWLRQZLWK
UHIHUHQFLQJREMHFWILHOG OD]\YDOV
YLVLELOLW\DQGDFFHVVWR PDSSLQJRSHUDWLRQV
ILOWHULQJ PL[HGSDUDGLJPLQ6FDOD
LQIRUH[SUHVVLRQV 2SWLRQVREMHFW
LQIXQFWLRQDOSURJUDPPLQJ SDUWLDOIXQFWLRQV
ILQDOGHFODUDWLRQVDWWHPSWLQJWRRYHUULGH SDWWHUQPDWFKLQJ
ILQDONH\ZRUG UHFXUVLRQ
ILQLVKLQJSUREOHP LQ'6/GHVLJQ  LQ6FDOD¡
ILUVWFODVV IXQFWLRQOLWHUDOVDQGFORVXUHV
IORDWLQJSRLQWOLWHUDOV WDLOFDOOVDQGWDLOFDOORSWLPL]DWLRQ
IOXHQWLQWHUIDFH WUDYHUVDORIGDWDVWUXFWXUHV
IROGLQJGDWDVWUXFWXUHV¡ YDULDEOHVLPPXWDEOHYDOXHVRI
IRUFRPSUHKHQVLRQV¡ )XQFWLRQ1REMHFW
H[SDQGHGYDULDEOHVFRSH GHILQLQJWUDLWVIRU
ILOWHUVLQ YDULDQFHXQGHULQKHULWDQFH
VLPSOHH[DPSOH IXQFWLRQV
XVLQJ2SWLRQVZLWK VHHDOVRIXQFWLRQDOSURJUDPPLQJ
\LHOGLQJFROOHFWLRQV GHILQHG
\LHOGLQJVXFFHVVLYHEORFNVRIG\QDPLFDOO\ KLJKHURUGHU
IRUPDWWHG;0/ RYHUORDGHG
IRUHDFKPHWKRG 6FDODXVLQJLQ-DYD
WUDYHUVDORSHUDWLRQVLQIXQFWLRQDO IXWXUHV
SURJUDPPLQJ

Index | 413

Download at WoweBook.Com
GHFODULQJ
G LPSHUDWLYHODQJXDJHV
*DQJRI)RXU *2) SDWWHUQV LPSHUDWLYHSURJUDPPLQJ
JHQHUDWRUH[SUHVVLRQV LPSOLFLWDUJXPHQWV
JHQHUDWRUV LPSOLFLWFRQYHUVLRQV
 OHIWDUURZ RSHUDWRU FDXWLRQZLWK
GHILQHG GHILQHG
LQIRUFRPSUHKHQVLRQV GHILQLQJFXVWRPREMHFWDQGFRQYHUVLRQ
JHQHULFV¡ PHWKRG
GHILQHG LQIXQFWLRQDOSURJUDPPLQJ
-DYD LQLQWHUQDO'6/SD\UROOLPSOHPHQWDWLRQ
XVLQJIURP6FDOD 
6FDODXVLQJIURP-DYD ,QWLQWR5LFK,QW
YDULDQFHXQGHULQKHULWDQFHGLIIHUHQFHV 3UHGHIDQ\$UURZ$VVRFPHWKRG
EHWZHHQ-DYDDQG6FDOD UXOHVIRUFRPSLOHUWRILQGDQGXVHFRQYHUVLRQ
JUDPPDUV PHWKRGV
FRQWH[WIUHH LPSOLFLWIXQFWLRQSDUDPHWHUV
(%1)QRWDWLRQIRUH[WHUQDOSD\UROO'6/ FDXWLRQZLWK
JUDPPDU LPSOLFLWNH\ZRUG
SDUVLQJH[SUHVVLRQJUDPPDUV 3(*V  GHILQHG
JXDUGVSDWWHUQPDWFKLQJRQ LPSOLFLWW\SLQJ
LPSRUWVWDWHPHQWV
H LPSRUWLQJ-DYDW\SHVDQGWKHLUPHPEHUV
+DGRRSOLEUDU\ 
+DVNHOO4XLFN&KHFNWRRO UHODWLYHSDWKXVHGLQ
KH[DGHFLPDOLQWHJHUOLWHUDOV LQILQLWHGDWDVWUXFWXUHV
KLJKHURUGHUIXQFWLRQV OD]LQHVVDQG
XVLQJOD]\YDOVWRPDQDJH
LQIL[QRWDWLRQ
I GHILQHG
,2 LQSXWRXWSXW LQIL[RSHUDWRUQRWDWLRQ
DXWRPDWLFLPSRUWDWLRQRIPHWKRGVE\6FDOD LQIL[W\SHV
 LQKHULWDQFH
1,2 QRQEORFNLQJ,2  FDVHFODVV
LGHQWLILHUVFKDUDFWHUVDOORZHGLQ GHILQHG
,'(V LQWHJUDWHGGHYHORSPHQWHQYLURQPHQWV  GHILQLWLRQ
¡ OLQHDUL]DWLRQRIREMHFWKLHUDUFK\¡
(FOLSVH PXOWLSOHSUREOHPVZLWK
GHYHORSLQJ6FDODDSSOLFDWLRQV VLQJOHLQKHULWDQFHSOXVWUDLWVLQ6FDOD
LQVWDOOLQJ6FDODSOXJLQ YDULDQFHXQGHU¡
,QWHOOL- LQVWDQFH
GHYHORSLQJ6FDODDSSOLFDWLRQV LQVWDQWLDWH
LQVWDOOLQJ6FDODSOXJLQV LQWHJHUOLWHUDOV
1HW%HDQV ,QWHOOL-,'($
GHYHORSLQJ6FDODDSSOLFDWLRQV GHYHORSLQJ6FDODDSSOLFDWLRQV
LQVWDOOLQJ6FDODSOXJLQV LQVWDOOLQJ6FDODSOXJLQV
WH[WHGLWRUV LQWHUDFWLYHPRGHVFDODFRPPDQG
LIVWDWHPHQWV #LQWHUIDFHNH\ZRUG -DYD 
LPPXWDEOHYDOXHV LQWHUQDO'6/V
LPPXWDEOHYDULDEOHV

414 | Index

Download at WoweBook.Com
VHHDOVR'6/V MDYDLR,2([FHSWLRQFODVV
H[WHUQDO'6/VYHUVXV MDYDODQJ6WULQJFODVV
LQWHUQHGVWULQJV MDYDQLRSDFNDJH
LQWHUSUHWHUVWDUWLQJ MDYDXWLOFRQFXUUHQWSDFNDJH
LQWHUSUHWLQJYHUVXVFRPSLOLQJ -DYD%HDQV
LQYDULDQFHDQGLQYDULDQW FRQYHQWLRQVIRU
LQYDULDQWVXEFODVVLQJ YHWRDEOHHYHQWV
LQYDULDQWV MDYDFFRPSLOHU
LQYHUVLRQRIFRQWURO ,R&  -DYDGRFVW\OH#UHWXUQDQQRWDWLRQ
,2+DQGOHU$FWRU$GDSWHUREMHFW MDYDSWRRO
,WHUDEOHREMHFW -DYD5HEHOWRRO
ILOWHULQJPHWKRGV -DYD7RNHQ3DUVHUV
IROGDQGUHGXFHPHWKRGV -'. -DYD'HYHORSPHQW.LW 
PDSPHWKRG MRLQSRLQWV
,WHUDWRU3DWWHUQ -8QLW
UXQQLQJVSHFLILFDWLRQV
-90 -DYD9LUWXDO0DFKLQH 
J -90YHUVLRQRI6FDOD
MDGWRRO LQVWDOOLQJ
-DYD
DQQRWDWLRQV
DVSHFWRULHQWHGSURJUDPPLQJ$VSHFW- L
', GHSHQGHQF\LQMHFWLRQ  OD]\HYDOXDWLRQLQILQLWHGDWDVWUXFWXUHVDQG
LPSRUWDWLRQRIGDWDW\SHVLQWR6FDOD 
LQWHUIDFLQJZLWKW\SHV\VWHPXVLQJ OD]\YDOXHV
H[LVWHQWLDOW\SHV 3RVWFODVV H[DPSOH 
LQYRNLQJPHWKRGQDPHLGHQWLFDOWR6FDOD OD]\GHILQHG
UHVHUYHGZRUG OHIWDVVRFLDWLYHPHWKRGLQYRFDWLRQV
-'. -DYD'HYHORSPHQW.LW  OLEUDULHV
-90 -DYD9LUWXDO0DFKLQH  -DYDOLEUDU\LQWHURSHUDELOLW\¡
UHIOHFWLRQPHWKRGV $VSHFW-¡
OLEUDULHVLQWHURSHUDELOLW\ZLWK6FDOD¡ +DGRRS
 6SULQJ)UDPHZRUN
$VSHFW-¡ 7HUUDFRWWD
+DGRRS PLVFHOODQHRXVVPDOOHU6FDODOLEUDULHV
6SULQJ)UDPHZRUN QRWDEOH6FDODOLEUDULHV
7HUUDFRWWD /LIWZHEIUDPHZRUN
SDFNDJHFRQFHSWIRUQDPHVSDFHV OLQHDUL]DWLRQRIREMHFWKLHUDUFK\¡
UHJXODUH[SUHVVLRQV 
6FDODLQWHURSHUDELOLW\ZLWK¡ DOJRULWKPIRUUHIHUHQFHW\SHV
$Q\9DOW\SHVDQG-DYDSULPLWLYHV KDQGFDOFXODWLRQIRU& H[DPSOH 
-DYDDQG6FDODJHQHULFV /LQNHG/LVWFODVVWKDWXVHV1RGHV H[DPSOH 
-DYD%HDQSURSHUWLHV 
6FDODQDPHVLQ-DYDFRGH /LVNRY6XEVWLWXWLRQ3ULQFLSOH
XVLQJ6FDODIXQFWLRQVLQ-DYD /LVWFODVV
VWDWLFPHWKRGVFRPSDQLRQREMHFWVDQG DSSO\DQGXQDSSO\6HTPHWKRGV
¡ GHFODUDWLRQ
VWDWLFW\SLQJ 1LOFDVHREMHFW
YDULDQFH¡ 6FDODLPSOHPHQWDWLRQ¡
MDYDFRPPDQG /LVWREMHFW

Index | 415

Download at WoweBook.Com
DSSO\PHWKRGSDUDPHWHUL]HG DEVWUDFWW\SHVDVDUJXPHQWV
IROGLQJ DGGLQJQHZPHWKRGVWRFODVVHV
OLVWVLQIXQFWLRQDOSURJUDPPLQJ FODVVOHYHO
OLWHUDOV¡ GHFODUDWLRQV¡
ERROHDQ GHIDXOWDQGQDPHGDUJXPHQWV
FKDUDFWHU QHVWLQJPHWKRGGHILQLWLRQV
GHILQHG GHILQHG
IORDWLQJSRLQW GHILQLQJ
LQWHJHU -DYDVWDWLFPHWKRGVDQGFRPSDQLRQREMHFWV
VWULQJ ¡
V\PERO RSHUDWRUVDV
ORDGWLPHZHDYLQJ LQIL[QRWDWLRQ
ORRSV RYHUULGLQJ
GRZKLOH RYHUULGLQJDFFHVVRUPHWKRGV
IRUORRSVRUFRPSUHKHQVLRQV¡ LQGLVWLQJXLVKDEOHIURPILHOGV
JHQHUDWRUH[SUHVVLRQVLQ ¡
ORRSLQJWKURXJKDQGPDWFKLQJ;0/ SDUDPHWHUL]HG
WUDPSROLQH ZLWKRXWSDUHQWKHVHVDQGGRWV
ZKLOH RSHUDWRUSUHFHGHQFH
ORZHUW\SHERXQGV UHIHUHQFLQJREMHFWPHWKRG
0H\HU%HUWUDQG
0,1$ $SDFKH 
M HYHQWVSURYLGHGE\
0DF26; PL[LQFRPSRVLWLRQ
LQVWDOOLQJ6FDOD XVLQJWUDLWV
7H[W0DWHHGLWRU PL[LQV
PDLOER[IRU$FWRUV GHILQHG
PDLQPHWKRG LQYDVLYH
0DQLIHVWV WUDLWVDV¡
0DSFRPSDQLRQREMHFW PRGXOHV
0DSYDOXHV FRPSRQHQWVDQG
0DSDSSO\PHWKRG FRQWUDFWRI
0DS5HGXFH PXOWLSOHLQKHULWDQFH
PDSVLQIXQFWLRQDOSURJUDPPLQJ PXWDEOHILHOGV
0DWFK(UURUREMHFW PXWDEOHYDOXHV
PDWKHPDWLFVIXQFWLRQVLQ
0DYHQEXLOGWRRO
PHPEHUV N
LPSRUWLQJ 1DJJDWLOLEUDU\
PHPRL]DWLRQ QDPHGDUJXPHQWV
VXSSRUWE\SDFNUDWSDUVHUV QDPHVSDFHV
PHVVDJHV UHODWLRQVKLSWR6FDOD¦VQHVWHGSDFNDJH
PHWDGDWD V\QWD[
VHHDOVRDQQRWDWLRQV QHPHWKRG $Q\5HI 
DGGLQJWRGHFODUDWLRQV QHVWHGFODVVHV
GHIDXOWYDOXHVDQG 1(7
PHWDSURJUDPPLQJ LQYRNLQJPHWKRGQDPHLGHQWLFDOWR6FDOD
0HWD6FDODOLEUDU\ UHVHUYHGZRUG
PHWKRGFKDLQLQJ UHJXODUH[SUHVVLRQV
PHWKRGV 1(7YHUVLRQRI6FDOD

416 | Index

Download at WoweBook.Com
1HW%HDQV ZRUNLQJZLWK9HWRDEOH&OLFNVWUDLW
GHYHORSLQJ6FDODDSSOLFDWLRQV H[DPSOH 
LQVWDOOLQJ6FDODSOXJLQV 2EVHUYHU3DWWHUQ
QHZRSHUDWRU WUDLWLPSOHPHQWLQJ
1LOFDVHREMHFW RFWDOLQWHJHUOLWHUDOV
1,2 QRQEORFNLQJ,2  2GHUVN\0DUWLQ
1LR6RFNHW$FFHSWRUREMHFW 2SHQ&ORVHG3ULQFLSOH 2&3 
1RGH6HTFODVV?DQG??PHWKRGV YLRODWLRQE\9LVLWRU3DWWHUQ
1RGH6HTREMHFW RSHUDWRUFKDUDFWHUV
1RQHFODVV GHILQHG
QRQWHUPLQDOV HQFRGLQJLQ-DYDLGHQWLILHUV
1RWKLQJW\SH LQLGHQWLILHUV
1XOOREMHFW RSHUDWRUQRWDWLRQ
QXOOV LQIL[RSHUDWRUQRWDWLRQ
DYRLGLQJXVLQJ2SWLRQ6RPHDQG1RQH RSHUDWRURYHUORDGLQJ
FODVVHV¡ RSHUDWRUSUHFHGHQFH
2SWLRQVYHUVXV RSHUDWRUV
FRQGLWLRQDO
2SWLRQFODVV¡
O DOWHUQDWLYHVWRH[FHSWLRQV
REMHFWV\VWHP 6FDOD ¡
IXQFWLRQDORSHUDWLRQVRQ
FODVVHVDQGREMHFWV
QXOOVYHUVXV
SDFNDJHREMHFWV
XVLQJZLWKIRUFRPSUHKHQVLRQV
OLQHDUL]DWLRQRIREMHFWKLHUDUFK\¡
RURSHUDWRU __ 
3UHGHIREMHFW
RYHUORDGHGIXQFWLRQV
VHDOHGFODVVKLHUDUFKLHV¡
RYHUORDGHGPHWKRGV
W\SHKLHUDUFK\
H[SOLFLWUHWXUQW\SHUHTXLUHPHQW
REMHFWRULHQWHGSURJUDPPLQJ 223 
RYHUULGHNH\ZRUG
FDVHFODVVHV¡
RYHUULGLQJFODVVDQGWUDLWPHPEHUV¡
FODVVHVDQGREMHFWVEDVLFVRI
DEVWUDFWDQGFRQFUHWHILHOGV
FRPSDQLRQREMHFWV¡
LQFODVVHV
FRQVWUXFWRUV¡
LQWUDLWV¡
GHILQHG
DEVWUDFWDQGFRQFUHWHPHWKRGV
HTXDOLW\RIREMHFWV
DEVWUDFWW\SHV¡
PL[HGSDUDGLJPLQ6FDOD
DFFHVVRUPHWKRGVLQGLVWLQJXLVKDEOHIURP
QHVWHGFODVVHV
ILHOGV¡
RYHUULGLQJPHPEHUVRIFODVVHVDQGWUDLWV
ILQDOGHFODUDWLRQV
¡
SDUHQWFODVVHV
UHXVDEOHVRIWZDUHFRPSRQHQWVDQG P
YLVLELOLW\UXOHV¡ SDFNDJHREMHFWV
REMHFWV SDFNDJHV
EDVLFVRI GHILQLQJXVLQJQHVWHGSDFNDJHV\QWD[LQ
GHHSPDWFKLQJRQFRQWHQWV 6FDOD
GHILQHG URRWSDFNDJHIRU6FDODOLEUDU\FODVVHV
LQVWDQWLDWLRQLQ6FDOD SDFNUDWSDUVHUV
LQ6FDOD 3DLUFODVV
YHUVXVFODVVOHYHOPHPEHUV DSSO\PHWKRG
2EVHUYDEOH&OLFNVWUDLW H[DPSOH  3DLUREMHFW
SDUDPHWHUL]HGPHWKRGV

Index | 417

Download at WoweBook.Com
SDUDPHWHUL]HGW\SHV XVLQJZLWKFDVHFODVVHVHQXPHUDWLRQV
DEVWUDFWW\SHVYHUVXV YHUVXV
GHILQHG YDULDEOHVLQPDWFKHV
0DQLIHVWV SDWWHUQPDWFKLQJLGHQWLILHUV
SDUDPHWHUL]HGPHWKRGV SD\UROOH[WHUQDO'6/ H[DPSOH ¡
YDOXHW\SHVFUHDWHGIURP SD\UROOLQWHUQDO'6/ H[DPSOH 
SDUDPHWHUV 3(*V SDUVLQJH[SUHVVLRQJUDPPDUV 
FRQVWUXFWRULQLWLDOL]DWLRQRIYDOVDQGYDUV 
 SHUIRUPDQFH
LPSOLFLWIXQFWLRQSDUDPHWHUV 3LPS0\/LEUDU\GHVLJQSDWWHUQ
RUGHURIQDPHGDUJXPHQWVDQG SODLQLGHQWLILHUV
UHTXLUHGUHWXUQW\SHDQQRWDWLRQV SRLQWFXWV
SDUHQWFODVVHV SRO\PRUSKLVP
SDUVHUFRPELQDWRUVH[WHUQDO'6/VZLWK¡ IDPLO\SRO\PRUSKLVP
 SDWWHUQPDWFKLQJYHUVXV
JHQHUDWLQJSD\FKHFNVZLWK SRVWFRQGLWLRQV
3D\UROO3DUVHU&RPELQDWRUV¡ SRVWIL[QRWDWLRQ
 #3UHDQQRWDWLRQ
SD\UROOH[WHUQDO'6/¡ SUHLQLWLDOL]HGILHOGV
6FDODLPSOHPHQWDWLRQRIH[WHUQDO'6/ SUHFHGHQFHRSHUDWRU
JUDPPDU¡ SUHFRQGLWLRQV
3DUVHUVREMHFW 3UHGHIREMHFW
GRFXPHQWDWLRQRIFRPSRVLWLRQRSHUDWRUV DQ\$UURZ$VVRFPHWKRG
 GHFODULQJW\SHVDQGH[FHSWLRQV
aFDVHFODVV GRFXPHQWDWLRQ
SDUVLQJH[SUHVVLRQJUDPPDUV 3(*V  LPSOLFLWFRQYHUVLRQPHWKRGVIRUYDOXHW\SHV
 
SDUWLDODSSOLFDWLRQ LWHPVLPSRUWHGRUGHILQHGE\
SDUWLDOIXQFWLRQV UHTXLUHDQGDVVXPHPHWKRGVXVLQJIRU
SDWKGHSHQGHQWW\SHV FRQWUDFWHQIRUFHPHQW
&VXSHU VWULQJ:UDSSHUPHWKRG
&WKLV SULPDU\FRQVWUXFWRU
S6XFFHVVFDVHFODVV H[DPSOH  SULPLWLYHGDWDW\SHV
SHULRGGHOLPLWHGSDWKH[SUHVVLRQV LQVWDQFHVRIYDOXHW\SHVFRUUHVSRQGLQJWR
SDWWHUQPDWFKLQJ¡ 
ELQGLQJQHVWHGYDULDEOHVLQFDVHFODXVHV -DYDFRQYHUVLRQRI$Q\9DOW\SHVWR
RQFDVHFODVVHV SULQWOQIXQFWLRQ
GHILQHG SDUWLDOO\DSSOLHG H[DPSOH 
RQHQXPHUDWLRQV SULYDWHNH\ZRUG
H[WUDFWRUVLQFDVHVWDWHPHQWV SULYDWHYLVLELOLW\
LQIXQFWLRQDOSURJUDPPLQJ VFRSHG¡
PDWFKLQJRQWXSOHVDQGJXDUGV SURGXFWLRQ
SRO\PRUSKLVPYHUVXV SURGXFWLRQUXOHV
RQUHJXODUH[SUHVVLRQV SURMHFWLRQIXQFWLRQV
RQVHTXHQFHV SURWHFWHGNH\ZRUG
VLPSOHPDWFKRIERROHDQYDOXHV SURWHFWHGYLVLELOLW\
RQW\SH VFRSHG¡
XVLQJRQ;0/VWUXFWXUHV SXEOLFYLVLELOLW\
XVLQJWU\FDWFKDQGILQDOO\FODXVHV SXUH VLGHHIIHFWIUHHIXQFWLRQV 

418 | Index

Download at WoweBook.Com
H[FHSWLRQV
Q PHWKRGUHVROXWLRQLQ
4XLFN&KHFN +DVNHOO 

R S
VED]WRRO
5DQJHREMHFW
LQVWDOOLQJ6FDOD&KHFN
5DQJH,QFOXVLYHFODVV
6%7 VLPSOHEXLOGWRRO 
UDZVWULQJVLQUHJXODUH[SUHVVLRQSDWWHUQ
6FDOD
PDWFKLQJ
EHQHILWVRI
UHFXUVLRQ
FRGHH[DPSOHV¡
H[SOLFLWUHWXUQW\SHDQQRWDWLRQ
FRPELQLQJZLWKRWKHUODQJXDJHV
LQIXQFWLRQDOSURJUDPPLQJ
LQVWDOOLQJ
WDLOFDOO
LQWURGXFWLRQWR
IROG/HIWDQGUHGXFH/HIW
RIILFLDOZHEVLWH
UHGXFLQJGDWDVWUXFWXUHV¡
UHVRXUFHVIRUPRUHLQIRUPDWLRQ
5HGXFWLRWRRO
VFDODFRPPDQG¡
UHIHUHQFHW\SHV
FSRSWLRQ
OLQHDUL]DWLRQDOJRULWKPIRU
FRPPDQGVDYDLODEOHLQVFDODLQWHUDFWLYH
OLVWHG
PRGH
SDUHQWRI$Q\5HI
GRFXPHQWDWLRQ
WHVWLQJHTXDOLW\
LQWHUDFWLYHPRGH
UHIHUHQWLDOWUDQVSDUHQF\
LQYRNLQJVFULSWV
UHILQHPHQWLQFRPSRXQGW\SHGHFODUDWLRQV
OLPLWDWLRQVRIYHUVXVVFDODF

RSWLRQV
GHILQHG
UXQQLQJLQLQWHUSUHWHGPRGH
UHIOHFWLRQ
VFULSWRUREMHFWVSHFLILHGIRU
5HJH[FODVV
VFDODWRROVXSSRUWSDFNDJH
UHJXODUH[SUHVVLRQV
VFDODDFWRUV$FWRUFODVV
PDWFKLQJRQ
#VFDODUHIOHFW%HDQ3URSHUW\DQQRWDWLRQ
XVHLQSDUVLQJ

UHLILHGW\SHV
VFDODELOLW\6FDODVXSSRUWIRU
UHODWLYHLPSRUWV
VFDODEOHDEVWUDFWLRQV VHHFRPSRQHQWV
5(3/ 5HDG(YDOXDWH3ULQW/RRS 
VFDODEOHODQJXDJH 6FDOD 
5HTXHVWFDVHFODVV
VFDODFFRPSLOHU
UHTXLUHPHQWVVSHFLILFDWLRQ
;RSWLRQV
UHVHUYHGZRUGV
;VFULSWRSWLRQ
OLVWLQJRIUHVHUYHGZRUGVLQ6FDOD
FRPPDQGRSWLRQV
QRWDOORZHGLQLGHQWLILHUV
FRPSLOLQJFRGHLQWR-90FODVVILOH
#5HWHQWLRQDQQRWDWLRQ
SOXJLQDUFKLWHFWXUH
#UHWXUQDQQRWDWLRQ
VFDODFRPPDQGYHUVXV
UHWXUQNH\ZRUG
6FDOD&KHFN
UHWXUQW\SHIRUPHWKRGV¡
VFDODGRFWRRO
UHTXLUHGH[SOLFLWGHFODUDWLRQVRI
6FDODGRFV
XVLQJ2SWLRQ6RPHDQG1RQHW\SHV
6FDOD2EMHFWFODVV
5LFK,QWFODVV
WDJPHWKRG
5LFK6WULQJFODVV
VFDODSWRRO
ULJKWDVVRFLDWLYHPHWKRGLQYRFDWLRQV
6FDOD7HVW
5XE\
6FDOD[OLEUDU\
G\QDPLFW\SLQJ
6FDOD]OLEUDU\

Index | 419

Download at WoweBook.Com
VFRSH 6SULQJ)UDPHZRUN
GHILQHG VWDEOHW\SHV
H[SDQGHGYDULDEOHVFRSHLQIRU VWDWH
FRPSUHKHQVLRQV VWDWLFPHPEHUV6FDODDQG
SDFNDJHREMHFWV VWDWLFW\SLQJ
RISULYDWHDQGSURWHFWHGYLVLELOLW\¡ YHUVXVG\QDPLFW\SLQJ
VFULSWLQJODQJXDJHVSRSXODULW\RI 6WDWLF$QQRWDWLRQFODVV
VHDOHGFODVVKLHUDUFKLHV¡ DQQRWDWLRQVGHULYHGIURP
VHDOHGNH\ZRUG 6WUHDPFODVV
VHOIW\SHV VWULFW
VHOIW\SHDQQRWDWLRQV¡ 6WULQJFODVV
DQGDEVWUDFWW\SHPHPEHUV LPSOLFLWFRQYHUVLRQWR5LFK6WULQJ
GHILQHG VWULQJOLWHUDOV
7ZLWWHU&OLHQW&RPSRQHQW H[DPSOH  VWURQJYHUVXVZHDNW\SLQJ
6HTFODVVILUVWDQGILUVW2SWLRQPHWKRGV VWUXFWXUDOW\SHV
VHTXHQFHV GHILQHG
PDWFKLQJRQ VXEW\SHV
5DQJH,QFOXVLYHFODVV VXSHUNH\ZRUG
VHTXHQWLDOFRPSRVLWLRQ VXSHUW\SH
FRPELQDWRURSHUDWRUV #VZLWFKDQQRWDWLRQ
#VHULDO9HUVLRQ8,'DQQRWDWLRQ V\PEROOLWHUDOV
6HWFRPSDQLRQREMHFW V\PEROV
6HWYDOXHV GHILQHG
VHWVLQIXQFWLRQDOSURJUDPPLQJ LQPHWKRGQDPHVDQGRWKHULGHQWLILHUV
VKRUWFLUFXLWLQJRSHUDWRUV DQG__ 
VLGHHIIHFWIUHH
VLJQDWXUH
T
VLQJOHLQKHULWDQFH WDJPHWKRG 6FDOD2EMHFW 
6LQJOH5HVSRQVLELOLW\3ULQFLSOH WDLOFDOOV
VLQJOHWRQREMHFWV #WDLO5HFDQQRWDWLRQDQG
HOLPLQDWLQJQHHGIRU6LQJOHWRQ3DWWHUQ IROG/HIWDQGUHGXFH/HIWRSHUDWLRQV
PHWKRGVGHILQHGLQFRPSDQLRQREMHFWV WUDPSROLQHIRU
 WDLOFDOOUHFXUVLRQ
VLQJOHWRQW\SHV #WDLO5HFDQQRWDWLRQ
VLQJOHWRQV 7'' 7HVW'ULYHQ'HYHORSPHQW ¡
6FDODFODVVHVGHFODUHGDV 
VOHHSLQJEDUEHUSUREOHP GHPRQVWUDWLQJ GHILQHG
$FWRUV ¡ 'HVLJQE\&RQWUDFWDQG
6073PDLOVHUYHU H[DPSOH ¡ 6FDOD&KHFNWRRO
FRGHFIRU6073 6FDOD7HVWWRRO
FRQYHUVDWLRQZLWKVHUYHU 6SHFVOLEUDU\¡
VHWXS WHUPLQDOV
6PWS+DQGOHUFODVV 7HUUDFRWWDOLEUDU\
6RPHFODVV WHVWGRXEOH
#VSHFLDOL]HGDQQRWDWLRQ WH[WHGLWRUV
6SHFVOLEUDU\¡ 7H[W0DWHHGLWRU
XVLQJIRU%''VSHFLILFDWLRQH[HUFLVLQJ WKLVNH\ZRUG
FRPELQHG%XWWRQDQG6XEMHFW VHOIYHUVXVLQVHOIW\SHDQQRWDWLRQV
W\SHV VHOIW\SHDQQRWDWLRQV
VXSHUYHUVXV

420 | Index

Download at WoweBook.Com
WKUHDGLQJLQ6FDOD W\SHSURMHFWLRQV
RQHRIIWKUHDGV W\SHV\VWHP
XVLQJMDYDXWLOFRQFXUUHQW VHHDOVRGDWDW\SHV
#WKURZVDQQRWDWLRQ 6FDOD
WUDLWNH\ZRUG W\SHYDULDQFH
WUDLWV¡ VHHDOVRYDULDQFHXQGHULQKHULWDQFH
DVSHFWVYHUVXV W\SHYDULDQFHDQQRWDWLRQV
FRQVWUXFWLQJ W\SHV
FODVVRUWUDLW VHHDOVRGDWDW\SHV
LQLWLDOL]LQJYDOXHVLQWUDLWV GHILQHG
GHILQHG W\SLQJ
HIIHFWLYHGHVLJQRI¡
IXQFWLRQVDVLQVWDQFHVRI
LPSOHPHQWLQJFRPSRQHQWVZLWK U
DVPL[LQV¡ XQDSSO\PHWKRG¡
YHWRLQJFOLFNHYHQWV XQDSSO\6HTPHWKRGIRUFROOHFWLRQV
RYHUULGLQJDFFHVVRUPHWKRGV #XQFKHFNHGDQQRWDWLRQ
LQGLVWLQJXLVKDEOHIURPILHOGV 8QLFRGHFKDUDFWHUV
RYHUULGLQJPHPEHUVRI 8QLIRUP$FFHVV3ULQFLSOH
DEVWUDFWDQGFRQFUHWHILHOGV¡ XQLYHUVH VED]UHPRWHUHSRVLWRU\ 
SURPRWLRQRIPL[LQFRPSRVLWLRQ XSSHUW\SHERXQGV
VWDFNLQJ
WUDPSROLQHV V
WU\FDWFKDQGILQDOO\FODXVHV
YDONH\ZRUG
WXSOHV
LQGHFODUDWLRQRIUHDGRQO\YDULDEOH
GHILQHG
XVLQJLQGHFODUDWLRQRILPPXWDEOHYDULDEOH
SDWWHUQPDWFKLQJRQ

YDOXHW\SHV\QWD[IRU
YDOVOD]\ VHHOD]\YDOXHV
ZD\VWRFUHDWHWZRLWHPWXSOH
9DOXHFODVV
7ZLWWHUFOLHQWFRPSRQHQWPRGHOIRU H[DPSOH 
9DOXHREMHFW
¡
YDOXHW\SHV
W\SHDOLDV
GHILQHG
W\SHDQQRWDWLRQV
IXQFWLRQW\SHV
GHILQHG
LPSOLFLWFRQYHUVLRQVE\3UHGHIREMHFW
UHTXLUHGH[SOLFLWW\SHDQQRWDWLRQV
PHWKRGV
VHOIW\SHDQQRWDWLRQV¡
LQIL[W\SHV
W\SHERXQGV¡
OLVWHG
GHILQHG
SDUDPHWHUL]HGW\SHV
/LVWFODVV6FDODLPSOHPHQWDWLRQ¡
VLQJOHWRQW\SHV
ORZHU
WXSOHV
XSSHU
W\SHGHVLJQDWRUV
XVLQJLQDEVWUDFWW\SHGHFODUDWLRQV
W\SHSURMHFWLRQV
YLHZVDQGYLHZERXQGV
XVHLQW\SHERXQGVH[SUHVVLRQV
W\SHFRQVWUXFWRUV
9DOXHWR6WULQJPHWKRG
W\SHGHVLJQDWRUV
YDOXHV
W\SHHUDVXUH
YDUNH\ZRUG
GHILQHG
YDULDEOHLGHQWLILHUV
JHW&ODVVPHWKRGRQ-90
YDULDEOHOHQJWKDUJXPHQWOLVWV
W\SHLQIHUHQFH¡
YDULDEOHV

Index | 421

Download at WoweBook.Com
ELQGLQJQHVWHGYDULDEOHVLQFDVHFODXVHV H[SORULQJXVLQJ1RGH6HTWRROV
GHFODUDWLRQV ORRSLQJDQGPDWFKLQJ
GHILQHG UHDGLQJ
H[SDQGHGVFRSHLQIRUH[SUHVVLRQV ZULWLQJ
LPPXWDEOHYDOXHVLQIXQFWLRQDO EORJJLQJV\VWHP H[DPSOH ¡
SURJUDPPLQJ
LQPDWFKHV
PXWDEOHDQGLPPXWDEOH
Y
\LHOGNH\ZRUG
LQVWDWLFDQGG\QDPLFW\SLQJ
YDULDQFHDQQRWDWLRQV
VXPPDU\RI
YDULDQFHXQGHULQKHULWDQFH
DEVWUDFWYHUVXVSDUDPHWHUL]HGW\SHV
YDULDQFHLQ6FDODYHUVXV-DYD¡
YDULDQFHRIPXWDEOHW\SHV
YHUVLRQV6FDOD
9HWRDEOH&OLFNVWUDLW H[DPSOH 
YLHZERXQGV¡
LPSOHPHQWLQJ/LQNHG/LVWFODVVWKDWXVHV
1RGHV
YLHZV¡
9LPHGLWRU
YLVLELOLW\¡
ILQHJUDLQHGYLVLELOLW\UXOHVLQ6FDOD
SULYDWH
SURWHFWHG
SXEOLF
VFRSHGSULYDWHDQGSURWHFWHGYLVLELOLW\¡

VXPPDU\RIYLVLELOLW\VFRSHV
9LVLWRU3DWWHUQDOWHUQDWLYHWR¡

W
ZHDNYHUVXVVWURQJW\SLQJ
ZHDYLQJORDGWLPH
ZHEDSSOLFDWLRQIUDPHZRUNV
ZHESDJHIRUWKLVERRN[[L
FRGHH[DPSOHV[L[
ZKLOHORRSV
LPSOHPHQWLQJXVLQJE\QDPHSDUDPHWHUV
DQGFXUU\LQJ
ZLWKNH\ZRUG
ZUDSSHUFODVVHVLQ6FDOD
5LFKZUDSSHUFODVVHVGHILQHGLQ
VFDODUXQWLPHSDFNDJH

X
;0/¡

422 | Index

Download at WoweBook.Com
About the Authors
'HDQ:DPSOHULVDFRQVXOWDQWWUDLQHUDQGPHQWRUZLWK2EMHFW0HQWRU,QF+HVSH
FLDOL]HVLQ6FDOD-DYDDQG5XE\DQGZRUNVZLWKFOLHQWVRQDSSOLFDWLRQGHVLJQVWUDWHJLHV
WKDW FRPELQH REMHFWRULHQWHG SURJUDPPLQJ IXQFWLRQDO SURJUDPPLQJ DQG DVSHFW
RULHQWHGSURJUDPPLQJ+HDOVRFRQVXOWVRQ$JLOHPHWKRGVVXFKDV/HDQDQG;3'HDQ
LVDIUHTXHQWVSHDNHUDWLQGXVWU\DQGDFDGHPLFFRQIHUHQFHVRQWKHVHWRSLFV+HKDVD
3K'LQSK\VLFVIURPWKH8QLYHUVLW\RI:DVKLQJWRQ
$OH[3D\QHLV3ODWIRUP/HDGDW7ZLWWHU,QFZKHUHKHGHYHORSVVHUYLFHVWKDWHQDEOH
SURJUDPPHUVWREXLOGDWRSWKHSRSXODUVRFLDOPHVVDJLQJVHUYLFH$OH[KDVSUHYLRXVO\
EXLOWZHEDSSOLFDWLRQVIRUSROLWLFDOFDPSDLJQVQRQSURILWVDQGHDUO\VWDJHVWDUWXSV
DQGVXSSRUWHGLQIRUPDWLRQVHFXULW\HIIRUWVIRUPLOLWDU\DQGLQWHOOLJHQFHFXVWRPHUV,Q
KLVIUHHWLPH$OH[VWXGLHVVSHDNVDQGZULWHVDERXWWKHKLVWRU\SUHVHQWXVHDQGHYR
OXWLRQRISURJUDPPLQJODQJXDJHVDVZHOODVPLQLPDOLVWDUWDQGGHVLJQ

Colophon
7KHDQLPDORQWKHFRYHURI3URJUDPPLQJ6FDODLVD0DOD\DQWDSLU 7DSLUXVLQGLFXV 
DOVRFDOOHGDQ$VLDQWDSLU,WLVDEODFNDQGZKLWHKRRIHGPDPPDOZLWKDURXQGVWRFN\
ERG\VLPLODUWRWKDWRIDSLJ$W¡IHHWORQJDQG¡SRXQGVWKH0DOD\DQLVWKH
ODUJHVWRIWKHIRXUWDSLUVSHFLHV,WOLYHVLQWURSLFDOUDLQIRUHVWVLQ6RXWKHDVW$VLD
7KH0DOD\DQWDSLU¦VDSSHDUDQFHLVVWULNLQJLWVIURQWKDOIDQGKLQGOHJVDUHVROLGEODFN
DQGLWVPLGVHFWLRQLVPDUNHGZLWKDZKLWHVDGGOH7KLVSDWWHUQSURYLGHVSHUIHFWFDP
RXIODJHIRUWKHWDSLULQDPRRQOLWMXQJOH2WKHUSK\VLFDOFKDUDFWHULVWLFVLQFOXGHDWKLFN
KLGHDVWXPS\WDLODQGDVKRUWIOH[LEOHVQRXW'HVSLWHLWVERG\VKDSHWKH0DOD\DQ
WDSLULVDQDJLOHFOLPEHUDQGDIDVWUXQQHU
7KHWDSLULVDVROLWDU\DQGPDLQO\QRFWXUQDODQLPDO,WWHQGVWRKDYHYHU\SRRUYLVLRQ
VRLWUHOLHVRQVPHOODQGKHDULQJDVLWURDPVODUJHWHUULWRULHVLQVHDUFKRIIRRGWUDFNLQJ
RWKHUWDSLUV¦VFHQWVDQGFRPPXQLFDWLQJYLDKLJKSLWFKHGZKLVWOHV7KH0DOD\DQWDSLU¦V
SUHGDWRUVDUHWLJHUVOHRSDUGVDQGKXPDQVDQGLWLVFRQVLGHUHGHQGDQJHUHGGXHWR
KDELWDWGHVWUXFWLRQDQGRYHUKXQWLQJ
7KH FRYHU LPDJH LV IURP WKH 'RYHU 3LFWRULDO $UFKLYH 7KH FRYHU IRQW LV $GREH ,7&
*DUDPRQG7KHWH[WIRQWLV/LQRW\SH%LUNDWKHKHDGLQJIRQWLV$GREH0\ULDG&RQ
GHQVHGDQGWKHFRGHIRQWLV/XFDV)RQW¦V7KH6DQV0RQR&RQGHQVHG

Download at WoweBook.Com
Download at WoweBook.Com

You might also like