0% found this document useful (0 votes)
711 views

Scala For The Impatient

This book introduces Scala as an attractive choice for programmers who want to use modern language features. Scala runs on the Java virtual machine, providing access to huge libraries and tools, and embraces functional programming without abandoning object-oriented programming. The book is intended for impatient readers who want to start programming in Scala right away without exhaustive explanations of concepts.

Uploaded by

Jianfeng Tian
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
711 views

Scala For The Impatient

This book introduces Scala as an attractive choice for programmers who want to use modern language features. Scala runs on the Java virtual machine, providing access to huge libraries and tools, and embraces functional programming without abandoning object-oriented programming. The book is intended for impatient readers who want to start programming in Scala right away without exhaustive explanations of concepts.

Uploaded by

Jianfeng Tian
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 98

Scala for the Impatient

!"#$%&'()*+*!,$*-.*/"%0)1,22*3455.*677*8&'()0*8909%:9;.

<(9*9:"7=)&"2*">*?,:,*,2;*!@@*(,0*07"A9;*;"A2*B"20&;9%,C7$D*,2;*#%"'%,119%0*A("*,%9
9,'9%*)"*=09*1"%9*1";9%2*7,2'=,'9*>9,)=%90*,%9*7""E&2'*9709A(9%9.*-B,7,*&0*,2*,))%,B)&:9
B("&B9F*&2*>,B)D*G*)(&2E*&)*&0*C$*>,%*)(9*1"0)*,))%,B)&:9*B("&B9*>"%*#%"'%,119%0*A("*A,2)*)"
1":9*C9$"2;*?,:,*"%*!@@.*-B,7,*(,0*,*B"2B&09*0$2),H*)(,)*&0*%9>%90(&2'*,>)9%*)(9*?,:,
C"&79%#7,)9.*G)*%=20*"2*)(9*?,:,*:&%)=,7*1,B(&29D*#%":&;&2'*,BB900*)"*,*(='9*09)*">*7&C%,%&90
,2;*)""70.*G)*91C%,B90*)(9*>=2B)&"2,7*#%"'%,11&2'*0)$79*A&)("=)*,C,2;"2&2'*"CI9B)J
"%&92),)&"2D*'&:&2'*$"=*,2*&2B%9192),7*79,%2&2'*#,)(*)"*,*29A*#,%,;&'1.*<(9*-B,7,
&2)9%#%9)9% 79)0*$"=*%=2*K=&BE*9H#9%&192)0D*A(&B(*1,E90*79,%2&2'*-B,7, :9%$*92I"$,C79.
62;D*7,0)*C=)*2")*79,0)D*-B,7,*&0*0),)&B,77$*)$#9;D*92,C7&2'*)(9*B"1#&79%*)"*>&2;*9%%"%0D*0"
)(,)*$"=*;"2L)*A,0)9*)&19*>&2;&2'*)(91*7,)9%*&2*%=22&2'*#%"'%,10*M"%*A"%09D*;"2L)*>&2;
)(91N.

G*A%")9*)(&0*C""E*>"% impatient %9,;9%0*A("*A,2)*)"*0),%)*#%"'%,11&2'*A&)(*-B,7,*%&'()


,A,$. G*,00=19*$"=*E2"A*?,:,D*!OD*"%*!@@D*,2;*G*A"2L)*C"%9*$"=*A&)(*9H#7,&2&2'
:,%&,C790D*7""#0D*"%*B7,0090.*G*A"2L)*9H(,=0)&:97$*7&0)*,77*>9,)=%90*">*)(9*7,2'=,'9D*G*A"2L)
79B)=%9*$"=*,C"=)*)(9*0=#9%&"%&)$*">*"29*#,%,;&'1*":9%*,2")(9%D*,2;*G*A"2L)*1,E9*$"=
0=>>9%*)(%"='(*7"2'*,2;*B"2)%&:9;*9H,1#790.*G20)9,;D*$"=*A&77*'9)*)(9*&2>"%1,)&"2*)(,)
$"=*299;*&2*B"1#,B)*B(=2E0*)(,)*$"=*B,2*%9,;*,2;*%9:&9A*,0*299;9;.

-B,7,*&0*,*C&'*7,2'=,'9D*C=)*$"=*B,2*=09*&)*9>>9B)&:97$*A&)("=)*E2"A&2'*,77*">*&)0*;9),&70
&2)&1,)97$.*P,%)&2*Q;9%0E$D*)(9*B%9,)"%*">*-B,7,D*(,0*&;92)&>&9;*)(9*>"77"A&2'*79:970*">
9H#9%)&09*>"%*,##7&B,)&"2*#%"'%,119%0*,2;*7&C%,%$*;90&'29%0R

6##7&B,)&"2*S%"'%,119% T&C%,%$*U90&'29% Q:9%,77*-B,7,*T9:97


V9'&22&2'*M65N V9'&22&2'
G2)9%19;&,)9*M63N ?=2&"%*MT5N G2)9%19;&,)9
WH#9%)*M6XN -92&"%*MT3N 6;:,2B9;
WH#9%)*MTXN WH#9%)

Y"%*9,B(*B(,#)9%*M,2;*"BB,0&"2,77$*>"%*&2;&:&;=,7*09B)&"20ND*G*&2;&B,)9*)(9*9H#9%&92B9
79:97. <(9*B(,#)9%0*#%"'%900*)(%"='(*79:970*65D*T5D*63D*T3D*6XD*TX.*W:92*&>*$"=*;"2L)
A,2)*)"*;90&'2*$"=%*"A2*7&C%,%&90D*E2"A&2'*,C"=)*)(9*)""70*)(,)*-B,7,*#%":&;90*>"%*7&C%,%$
;90&'29%0*B,2*1,E9*$"=*,*1"%9*9>>9B)&:9*7&C%,%$*=09%.

G*("#9*$"=*92I"$*79,%2&2'*-B,7,*A&)(*)(&0*C""E.*G>*$"=*>&2;*9%%"%0*"%*(,:9*0=''90)&"20*>"%
&1#%":9192)D*#79,09*:&0&) http://horstmann.com/scala ,2;*79,:9*,*B"1192).

5
Table of Contents

5. <(9*V,0&B0*M65N
3. !"2)%"7*-)%=B)=%90*,2;*Y=2B)&"20*M65N
X. 6%%,$0*M65N
Z. P,#0*,2;*<=#790*M65N
[. !7,0090*M65N
\. QCI9B)0*M65N
]. S,BE,'90*,2;*G1#"%)0*M65N
^. G2(9%&),2B9*M65N
_. Y&790*,2;*89'=7,%*WH#%900&"20*M65N
54. <%,&)0*MT5N
55. Q#9%,)"%0*MT5N
53. /&'(9%JQ%;9%*Y=2B)&"20*MT5N
5X. !"779B)&"20*M63N
5Z. S,))9%2*P,)B(&2'*,2;*!,09*!7,0090*M63N
5[. 622"),)&"20*M63N
5\. `PT*S%"B900&2'*M63N
5]. <$#9*S,%,19)9%0*MT3N
5^. 6;:,2B9;*<$#90 MT3N
5_. S,%0&2'*,2;*U"1,&2J-#9B&>&B*T,2'=,'90*M6XN
34. 6B)"%0*M6XN
35. G1#7&B&)0*MTXN
33. 6C0)%,B)*<$#90*MTXN
3X. /&'(9%Ja&2;9;*<$#90*MTXN
3Z. U97&1&)9;*B"2)&2=,)&"20*MTXN

3
1. The Basics (A1)
G2*)(&0*B(,#)9%D*$"=*A&77*79,%2*("A*)"*=09*-B,7,*,0*,2*&2;=0)%&,7J0)%92')(*#"BE9)*B,7B=7,)"%D
A"%E&2'*&2)9%,B)&:97$*A&)(*2=1C9%0*,2;*,%&)(19)&B*"#9%,)&"20.*b9*&2)%";=B9*,*2=1C9%*">
&1#"%),2)*-B,7,*B"2B9#)0*,2;*&;&"10*,7"2'*)(9*A,$.*c"=*A&77*,70"*79,%2*("A*)"*C%"A09
)(9*-B,7,;"B*;"B=192),)&"2*,)*,*C9'&229%L0*79:97.

/&'(7&'()0*">*)(&0*&2)%";=B)&"2*,%9R

d e0&2'*)(9*-B,7,*&2)9#%9)9%
d U9>&2&2'*:,%&,C790*A&)( var ,2; val
d f=19%&B*)$#90
d e0&2'*"#9%,)"%0*,2;*>=2B)&"20
d f,:&',)&2'*-B,7,;"B

1.1. The Scala Interpreter


<"*0),%)*)(9*-B,7,*&2)9%#%9)9%D

d G20),77*-B,7,
d P,E9*0=%9*)(,)*)(9 scala/bin ;&%9B)"%$*&0*"2*)(9*S6</
d Q#92*,*B"11,2;*0(977*&2*$"=%*"#9%,)&2'*0$0)91
d <$#9 scala >"77"A9;*C$*)(9 Wf<W8 E9$.

Tip: U"2L)*7&E9*)(9*B"11,2;*0(977g*<(9%9*,%9*")(9%*A,$0*">*%=22&2'*)(9
&2)9%#%9)9%h099 ())#Rii("%0)1,22.B"1i0B,7,i&20),77.

f"A*)$#9*B"11,2;0*>"77"A9;*C$ Wf<W8.*W,B(*)&19D*)(9*&2)9%#%9)9%*;&0#7,$0*)(9*,20A9%.
Y"%*9H,1#79D*&>*$"=*)$#9 8 * 5 + 2 M,0*0("A2*&2*C"7;>,B9*C97"AND*$"=*'9)*,2*,20A9%*Z3.

scala> 8 * 5 + 2
res0: Int = 42

<(9*,20A9%*&0*0)"%9;*&2*,*:,%&,C79 res0 )(,)*$"=*B,2*=09*&2*$"=%*&2#=)R

scala> 0.5 * res0


res1: Double = 21.0
scala> "Hello, " + res0
res2: java.lang.String = Hello, 42

60*$"=*B,2*099D*)(9*&2)9%#%9)9%*,70"*;&0#7,$0*)(9*)$#9*">*)(9*%90=7)h&2*"=%*9H,1#790D IntD
DoubleD*,2; java.lang.String.

X
c"=*B,2*B,77*19)(";0.*U9#92;&2'*"2*("A*$"=*7,=2B(9;*)(9*&2)9%#%9)9%D*$"=*1,$*C9*,C79
)"*=09 tab completion.*<%$*)$#&2' res2.to ,2;*)(92*(&)*)(9 <6V E9$.*U&;*)(9*&2)9%#%9)9%
">>9%*B("&B90*0=B(*,0

toCharArray toLowerCase toString toUpperCase

G>*0"D*),C*B"1#79)&"2*A"%E0.*<$#9*, U ,2;*(&)*)(9 <6V E9$*,',&2.*c"=*2"A*'9)*,*0&2'79


B"1#79)&"2

res2.toUpperCase

/&)*)(9 Wf<W8 E9$D*,2;*)(9*,20A9%*&0*;&0#7,$9;.*MG>*$"=*B,2L)*=09*),C*B"1#79)&"2*&2*$"=%


92:&%"2192)D*$"=L77*(,:9*)"*)$#9*)(9*B"1#79)9*19)(";*2,19*$"=%097>.N

670"*)%$*(&))&2'*)(9*j*,2;*k*,%%"A*E9$0.*G2*1"0)*&1#79192),)&"20D*$"=*A&77*099*)(9
#%9:&"=07$*&00=9;*B"11,2;0D*,2;*$"=*B,2*9;&)*)(91.*<%$*)(9*lD*mD*,2; UWT E9$0*)"
B(,2'9*)(9*7,0)*B"11,2;*)"

res2.toLow
LowerCase

60*$"=*B,2*099D*)(9*-B,7,*&2)9%#%9)9%*%9,;0*,2*9H#%900&"2D*9:,7=,)90*&)D*#%&2)0*&)D*,2;*%9,;0
)(9*29H)*9H#%900&"2.*<(&0*&0*B,779;*)(9 read-eval-print loop "%*8WST.

<9B(2&B,77$*0#9,E&2'D*)(9 scala #%"'%,1*&0 not ,2*&2)9%#%9)9%.*V9(&2;*)(9*0B9290D*$"=%


&2#=)*&0*K=&BE7$*B"1#&79;*&2)"*C$)9*B";90D*,2;*)(9*C$)9*B";90*,%9*9H9B=)9;*C$*)(9*?,:,
:&%)=,7*1,B(&29.*Y"%*)(,)*%9,0"2D*1"0)*-B,7,*#%"'%,119%0*#%9>9%*)"*%9>9%*)"*&)*,0*n)(9
8WSTo.

Tip: <(9*8WST*&0*$"=%*>%&92;.*V9B,=09*$"=*'9)*&20),2)*>99;C,BED*$"=*A&77*>997
92B"=%,'9;*)"*9H#9%&192)D*,2;*$"=*A&77*>997*'"";*A(929:9%*0"19)(&2'*A"%E0.

G)*&0*,*'"";*&;9,*)"*E99#*,2*9;&)"%*A&2;"A*"#92*,)*)(9*0,19*)&19*0"*$"=*B,2
B"#$*,2;*#,0)9*0=BB900>=7*B";9*02&##9)0*>"%*7,)9%*=09.*670"D*,0*$"=*)%$*1"%9
B"1#79H*9H,1#790D*$"=*1,$*A,2)*)"*B"1#"09*)(91*&2*)(9*9;&)"%*,2;*)(92
#,0)9*)(91*&2)"*)(9*8WST.

1.2. Declaring Variables


G20)9,;*">*=0&2'*)(9*:,%&,C790 res0D res1D*,2;*0"*"2D*$"=*B,2*;9>&29*$"=%*"A2R

scala> val answer = 8 * 5 + 2


answer: Int = 42

Z
c"=*B,2*=09*$"=%*:,%&,C790*&2*0=C09K=92)*9H#%900&"20R

scala> 0.5 * answer


res3: Double = 21.0

f")9*)(,)*$"=*299;*2")*0#9B&>$*)(9*)$#9*">*,*:,%&,C79.*G)*&0*&2>9%%9;*>%"1*)(9*)$#9*">*)(9
:,7=9*A&)(*A(&B(*$"=*&2&)&,7&p9*&).*MG)*&0*,2*9%%"%*)"*;9B7,%9*,*:,%&,C79*A&)("=)*,2*&2&)&,7
:,7=9.N

/"A9:9%D*$"=*B,2*0#9B&>$*)(9*)$#9*&>*29B900,%$.*Y"%*9H,1#79D

val greeting: String = null


val greeting: Any = "Hello"

Note: G2*-B,7,D*)(9*)$#9*">*,*:,%&,C79*"%*>=2B)&"2*&0*,7A,$0*A%&))92 after )(9


:,%&,C79*"%*>=2B)&"2.*<(&0*1,E90*&)*9,0&9%*)"*%9,;*;9B7,%,)&"20*A&)(*B"1#79H
)$#90.

b(929:9%*G*1":9*C,BE*,2;*>"%)(*C9)A992*?,:,*,2;*-B,7,D*G*>&2;*)(,)*1$
>&2'9%0*A%&)9*;9B7,%,)&"20*0=B(*,0 String greeting "2*,=)"#&7")D*,2;*G*(,:9*)"
%9A%&)9*)(91*,0 greeting: String.*<(&0*&0*,*C&)*,22"$&2'D*C=)*A(92*G*A"%E
A&)(*B"1#79H*-B,7,*#%"'%,10D*G*%9,77$*,##%9B&,)9*)(,)*G*;"2L)*(,:9*)"*;9B%$#)
)$#9*!J0)$79*;9B7,%,)&"20.

6*:,%&,C79*;9B7,%9;*A&)( val &0*,B)=,77$*,*B"20),2)h$"=*B,2L)*B(,2'9*&)0*B"2)92)0R

scala> answer = 0
<console>:6: error: reassignment to val

<"*;9B7,%9*,*:,%&,C79*A("09*B"2)92)0*B,2*:,%$D*=09*, varR

var counter = 0
counter = 1 // QED*B,2*B(,2'9*, var

G2*-B,7,D*$"=*,%9*92B"=%,'9;*)"*=09*, val =27900*$"=*%9,77$*299;*)"*B(,2'9*)(9*B"2)92)0.


S9%(,#0*0=%#%&0&2'7$*>"%*?,:,*"%*!@@*#%"'%,119%0D*1"0)*#%"'%,10*;"2L)*299;*1,2$ var.

Note: c"=*1,$*(,:9*2")&B9;*)(,)*)(9%9*A9%9*2"*091&B"7"20*,>)9%*:,%&,C79
;9B7,%,)&"20*"%*,00&'2192)0.*G2*-B,7,D*091&B"7"20*,%9*"27$*%9K=&%9;*&>*$"=
(,:9*1=7)&#79*0),)9192)0*"2*)(9*0,19*7&29.

[
c"=*B,2*;9B7,%9*1=7)&#79*:,%&,C790*)"'9)(9%R

var i, j = 0
var greeting, message: String = null

1.3. Commonly Used Types


c"=*(,:9*,7%9,;$*0992*,*>9A*">*)(9*;,),*)$#90*">*)(9*-B,7,*7,2'=,'9D*0=B(*,0 Int ,2;
Double.*T&E9*?,:,D*-B,7,*(,0*09:92*2=19%&B*)$#90

Byte Char Short Int Long Float Double

,2;*, Boolean )$#9.*/"A9:9%D*=27&E9*?,:,D*)(909*)$#90*,%9 classes.*<(9%9*&0*2"*;&0)&2B)&"2


C9)A992*#%&1&)&:9*)$#90*,2;*B7,00*)$#90*&2*-B,7,.*c"=*B,2*&2:"E9*19)(";0*"2*2=1C9%0D
>"%*9H,1#79

1.toString() // $&97;0*)(9*0)%&2' "1"

"%D*1"%9*9HB&)&2'7$D

1.to(10) // $&97;0 Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

Mb9*A&77*;&0B=00*)(9 Range B7,00*&2 )(9*n!"779B)&"20o*B(,#)9%.*Y"%*2"AD*I=0)*:&9A*&)*,0*,


B"779B)&"2*">*2=1C9%0.N

G2*-B,7,D*)(9%9*&0*2"*299;*>"%*A%,##9%*)$#90.*G)*&0*)(9*I"C*">*)(9*-B,7,*B"1#&79%*)"*B"2:9%)
C9)A992*#%&1&)&:9*)$#90*,2;*A%,##9%0.*Y"%*9H,1#79D*&>*$"=*1,E9*,2*,%%,$*"> IntD*$"=*'9)
,2 int[] ,%%,$*&2*)(9*:&%)=,7*1,B(&29.

60*$"=*0,A*&2 -9B)&"2*5D*-B,7,*%97&90*"2*)(9*=2;9%7$&2' java.lang.String B7,00*>"%


0)%&2'0.*/"A9:9%D*&)*,='192)0*)(,)*B7,00*A&)(*A977*":9%*,*(=2;%9;*"#9%,)&"20*&2*)(9
StringOps B7,00.*Y"%*9H,1#79D*)(9 intersect 19)(";*$&97;0*)(9*B(,%,B)9%0*)(,)*,%9
B"11"2*)"*)A"*0)%&2'0.

"Hello".intersect("World") // $&97;0 "lo"

G2*)(&0*9H#%900&"2D*)(9 java.lang.String "CI9B) "Hello" &0*&1#7&B&)7$*B"2:9%)9;*)"*,


StringOps "CI9B)D*,2;*)(92*)(9 intersect 19)(";*">*)(9 StringOps B7,00*&0*,##7&9;.

<(9%9>"%9D*$"=*A,2)*)"*%9191C9%*)(9 StringOps B7,00*A(92*$"=*=09*)(9*-B,7,


;"B=192),)&"2*M099 -9B)&"2*]N.

-&1&7,%7$D*)(9%9*,%9*B7,0090 RichIntD RichDoubleD RichCharD*,2;*0"*"2.*W,B(*">*)(91*(,0*,


01,77*09)*">*B"2:92&92B9*19)(";0*>"%*,B)&2'*"2*)(9&%*#""%*B"=0&20 IntD DoubleD CharD*,2;

\
0"*"2.*<(9 to 19)(";*)(,)*$"=*(,:9*0992*,C":9*&0*,B)=,77$*,*19)(";*">*)(9 RichInt B7,00.
G2*)(9*9H#%900&"2

1.to(10)

)(9 Int :,7=9 1 &0*>&%0)*B"2:9%)9;*)"*, RichIntD*,2;*)(9 to 19)(";*&0*,##7&9;*)"*)(,)*:,7=9.

Y&2,77$D*)(9%9*,%9*B7,0090 BigInt ,2; BigDecimal >"%*B"1#=),)&"20*)(,)*%9K=&%9


B"1#=),)&"20*A&)(*,%C&)%,%$*MC=)*>&2&)9N*2=1C9%0*">*;&'&)0.*<(909*,%9*C,BE9;*C$*)(9
java.math.BigInteger ,2; java.math.BigDecimal B7,0090D*C=)D*,0*$"=*A&77*099*&2 -9B)&"2
ZD*)(9$*,%9*1=B(*1"%9*B"2:92&92)*C9B,=09*$"=*B,2*=09*)(91*A&)(*)(9*=0=,7*1,)(91,)&B,7
"#9%,)"%0.

Note: G2*-B,7,D*$"=*=09*19)(";0D*2")*B,0)0D*)"*B"2:9%)*C9)A992*2=19%&B*)$#90.
Y"%*9H,1#79D 99.44.toInt &0 99D*,2; 99.toChar &0 'c'.*Q>*B"=%09D*,0*&2*?,:,D
)(9 toString 19)(";*B"2:9%)0*,2$*"CI9B)*)"*,*0)%&2'.

<"*B"2:9%)*,*0)%&2'*B"2),&2&2'*,*2=1C9%*&2)"*)(9*2=1C9%D*$"=*,70"*=09 toInt "%


toDouble.*Y"%*9H,1#79D "99.44".toDouble &0 99.44.

1.4. Arithmetic and Operator Overloading


6%&)(19)&B*"#9%,)&"20*&2*-B,7,*A"%E*I=0)*,0*$"=*A"=7;*9H#9B)*&2*?,:,*"%*!@@R

val answer = 8 * 5 + 2

<(9 + - * / % "#9%,)"%0*;"*)(9&%*=0=,7*I"CD*,0*;"*)(9*C&)*"#9%,)&"20 & | ^ >> <<.*<(9%9*&0


I=0)*"29*0=%#%&0&2'*,0#9B)R*<(909*"#9%,)"%0*,%9*,B)=,77$*19)(";0.*Y"%*9H,1#79D

a + b

&0*,*0("%)(,2;*>"%

a.+(b)

/9%9D + &0*)(9*2,19*">*)(9*19)(";.*-B,7,*(,0*2"*0&77$*#%9I=;&B9*)(,)*,*19)(";*2,19*B,2
"27$*B"2),&2*,7#(,2=19%&B*B(,%,B)9%0.*c"=*B,2*;9>&29*19)(";0*A&)(*I=0)*,C"=)*,2$
0$1C"70.*Y"%*9H,1#79D*)(9 BigInt B7,00*;9>&290*,*19)(";*B,779; /%.*G)*%9)=%20*,*#,&%
B"2),&2&2'*)(9*K=")&92)*,2;*%91,&2;9%*">*,*;&:&0&"2.

G2*'929%,7D*$"=*B,2*A%&)9

]
a method b

,0*,*0("%)(,2;*>"%

a.method(b)

A(9%9 method &0*,*19)(";*A&)(*)A"*#,%,19)9%0*M"29*&1#7&B&)D*"29*9H#7&B&)N.*Y"%*9H,1#79D


&20)9,;*">

1.to(10)

$"=*B,2*A%&)9

1 to 10

e09*A(,)9:9%*$"=*)(&2E*&0*9,0&9%*)"*%9,;.*V9'&22&2'*-B,7,*#%"'%,119%0*)92;*)"*0)&BE*)"
)(9*?,:,*0$2),HD*,2;*)(,)*&0*I=0)*>&29.*Q>*B"=%09D*9:92*)(9*1"0)*(,%;929;*?,:,
#%"'%,119%0*0991*)"*#%9>9% a + b ":9% a.+(b).

<(9%9*&0*"29*2"),C79*;&>>9%92B9*C9)A992*-B,7,*,2;*?,:,*"%*!@@.*-B,7,*;"90*2")*(,:9 ++ "%
-- "#9%,)"%0.*G20)9,;D*0&1#7$*=09 +=1 "% -=1.

counter+=1 // G2B%9192)0 counterh-B,7,*(,0*2" ++

-"19*#9"#79*A"2;9%*A(9)(9%*)(9%9*&0*,2$*;99#*%9,0"2*>"%*-B,7,L0*%9>=0,7*)"*#%":&;9*,
++ "#9%,)"%.*Mf")9*)(,)*$"=*B,2L)*0&1#7$*&1#79192)*,*19)(";*B,779; ++.*-&2B9*)(9 Int
B7,00*&0*&11=),C79D*0=B(*,*19)(";*B"=7;2L)*B(,2'9*,2*&2)9'9%*:,7=9.N*<(9*-B,7,*;90&'29%0
;9B&;9;*&)*A,02L)*A"%)(*(,:&2'*$9)*,2")(9%*0#9B&,7*%=79*I=0)*)"*0,:9*"29*E9$0)%"E9.

c"=*B,2*=09*)(9*=0=,7*1,)(91,)&B,7*"#9%,)"%0*A&)( BigInt ,2; BigDecimal "CI9B)0R

val x: BigInt = 1234567890


x * x * x // $&97;0 1881676371789154860897069000

<(,)L0*1=B(*C9))9%*)(,2*?,:,D*A(9%9*$"=*A"=7;*(,:9*(,;*)"*B,77
x.multiply(x).multiply(x).

Note: G2*?,:,D*$"=*B,22")*":9%7",;*"#9%,)"%0D*,2;*)(9*?,:,*;90&'29%0*B7,&19;
)(&0*&0*,*'"";*)(&2'*C9B,=09*&)*#%9:92)0*$"=*>%"1*&2:92)&2'*B%,p$*"#9%,)"%0*7&E9
!@$&* )(,)*1,E9*$"=%*#%"'%,1*&1#"00&C79*)"*%9,;.*Q>*B"=%09D*)(,)L0*0&77$.*G2
?,:,D*$"=*B,2*1,E9*$"=%*#%"'%,10*I=0)*,0*(,%;*)"*%9,;*C$*=0&2'*B%,p$*19)(";
2,190*7&E9 qxywz.*-B,7,*,77"A0*$"=*)"*;9>&29*"#9%,)"%0D*79,:&2'*&)*)"*$"=*)"*=09
)(&0*>9,)=%9*A&)(*%90)%,&2)*,2;*'"";*),0)9.

^
1.5. Calling Functions and Methods
-B,7,*(,0*>=2B)&"20*&2*,;;&)&"2*)"*19)(";0.*G)*0&1#79%*)"*=09*1,)(91,)&B,7*>=2B)&"20*0=B(
,0 min "% pow &2*-B,7,*)(,2*&2*?,:,h$"=*299;*2")*=09*0),)&B*19)(";0*&2*,*B7,00.

sqrt(2) // $&97;0*5.Z5Z35X[\3X]X4_[5
pow(2, 4) // $&97;0*5\.4
min(3, Pi) // $&97;0*X.4

<(9*1,)(91,)&B,7*>=2B)&"20*,%9*;9>&29;*&2*)(9 scala.math #,BE,'9.

c"=*B,2*&1#"%)*)(91*A&)(*)(9*0),)9192)

import math._ // G2*-B,7,D*)(9 _ B(,%,B)9%*&0*,*nA&7;B,%;oD*7&E9 * &2*?,:,

Note: b(92*$"=*=09*,*#,BE,'9*)(,)*0),%)0*A&)( scala.D*$"=*B,2*"1&)*)(9 scala


#%9>&H.*Y"%*9H,1#79D import math._ &0*9K=&:,792)*)" import scala.math._D*,2;
math.sqrt(2) &0*)(9*0,19*,0 scala.math.sqrt(2).

b9*;&0B=00*)(9 import 0),)9192)*&2*1"%9*;9),&7*&2 )(9*nS,BE,'90*,2;*G1#"%)0o*B(,#)9%.


Y"%*2"AD*I=0)*=09 import packageName._ A(929:9%*$"=*299;*)"*&1#"%)*,*#,%)&B=7,%
#,BE,'9.

-B,7,*;"902L)*(,:9*0),)&B*19)(";0D*C=)*&)*(,0*,*0&1&7,%*>9,)=%9D*B,779; singleton objectsD


A(&B(*A9*A&77*;&0B=00*&2*;9),&7*&2 )(9*nQCI9B)0o*B(,#)9%.*P,2$*B7,0090*(,:9*, companion
object A("09*19)(";0*,B)*I=0)*7&E9*0),)&B*19)(";0*;"*&2*?,:,.*Y"%*9H,1#79D*)(9 BigInt
B"1#,2&"2*"CI9B)*)"*)(9 BigInt B7,00*(,0*,*19)("; probablePrime )(,)*B,2*'929%,)9*,
%,2;"1*#%&19*2=1C9%*A&)(*,*'&:92*2=1C9%*">*C&)0.*<%$

BigInt.probablePrime(100, util.Random)

&2*)(9*8WST.*c"=L77*'9)*,*2=1C9%*0=B(*,0*54X_ZZ]_^4Z_53443][Z^\[Z43Z4]5X.*f")9
)(,)*)(9*B,77 BigInt.probablePrime &0*I=0)*7&E9*,*0),)&B*19)(";*B,77*&2*?,:,.

Note: /9%9D Random &0*,*0&2'79)"2*%,2;"1*2=1C9%*'929%,)"%*"CI9B)D*;9>&29;*&2


)(9 scala.util #,BE,'9.*<(&0*&0*"29*">*)(9*>9A*0&)=,)&"20*A(9%9*,*0&2'79)"2
"CI9B)*&0*C9))9%*)(,2*,*B7,00.*G2*?,:,D*&)*&0*,*B"11"2*9%%"%*)"*B"20)%=B)*,*29A
java.util.Random "CI9B)*>"%*9,B(*%,2;"1*2=1C9%.

_
-B,7,*19)(";0*A&)("=)*#,%,19)9%0*">)92 ;"2L)*=09*#,%92)(9090.*Y"%*9H,1#79D*)(9*6SG*">
)(9 StringOps B7,00*0("A0*,*19)("; distinctD*A&)("=) ()D*)"*'9)*)(9*;&0)&2B)*79))9%0*&2*,
0)%&2'.*c"=*B,77*&)*,0

"Hello".distinct

<(9*%=79*">*)(=1C*&0*)(,)*,*#,%,19)9%7900*19)(";*)(,)*;"902L)*1";&>$*)(9*"CI9B)*(,0*2"
#,%92)(9090.*b9*;&0B=00*)(&0*>=%)(9%*&2 )(9*n!7,0090o*B(,#)9%.

1.6. The apply Method


G2*-B,7,D*&)*&0*B"11"2*)"*=09*,*0$2),H*)(,)*7""E0*7&E9*,*>=2B)&"2*B,77.*Y"%*9H,1#79D*&> s &0*,
0)%&2'D*)(92 s(i) &0*)(9 i)(*B(,%,B)9%*">*)(9*0)%&2'.*MG2*!@@D*$"=*A"=7;*A%&)9 s[i]D*"%*&2
?,:,D s.charAt(i).N*<%$*&)*"=)*&2*)(9*8WSTR

"Hello"(4) // $&97;0 'o'

c"=*B,2*)(&2E*">*)(&0*,0*,2*":9%7",;9;*>"%1*">*)(9 () "#9%,)"%.*G)*&0*&1#79192)9;*,0*,
19)(";*A&)(*)(9*2,19 apply.*Y"%*9H,1#79D*&2*)(9*;"B=192),)&"2*">*)(9 StringOps B7,00D
$"=*A&77*>&2;*,*19)(";

def apply(n: Int): Char

<(,)*&0D "Hello"(4) &0*,*0("%)B=)*>"%

"Hello".apply(4)

b(92*$"=*7""E*,)*)(9*;"B=192),)&"2*">*)(9 BigInt B"1#,2&"2*"CI9B)D*$"=*A&77*099 apply


19)(";0*)(,)*79)*$"=*B"2:9%)*0)%&2'0*"%*2=1C9%0*)" BigInt "CI9B)0.*Y"%*9H,1#79D*)(9*B,77

BigInt("1234567890")

&0*,*0("%)B=)*>"%

BigInt.apply("1234567890")

G)*$&97;0*29A BigInt "CI9B)D without having to use new.*Y"%*9H,1#79D

BigInt("1234567890") * BigInt("112358111321")

e0&2'*)(9 apply 19)(";*">*,*B"1#,2&"2*"CI9B)*&0*,*B"11"2*-B,7,*&;&"1*>"%*B"20)%=B)&2'


"CI9B)0.Y"%*9H,1#79D Array(1, 4, 9, 16) %9)=%20*,2*,%%,$D*)(,2E0*)"*)(9 apply 19)(";*">
)(9 Array B"1#,2&"2*"CI9B).

54
1.7. Scaladoc
?,:,*#%"'%,119%0*=09*?,:,;"B*)"*2,:&',)9*)(9*?,:,*6SG.*-B,7,*(,0*&)0*"A2*:,%&,2)D*B,779;
-B,7,;"B*M099 Y&'=%9*5N.

Y&'=%9*5J5R <(9*W2)%$*S,'9*>"%*-B,7,;"B

f,:&',)&2'*-B,7,;"B*&0*,*C&)*1"%9*B(,7792'&2'*)(,2*?,:,;"B.*-B,7,*B7,0090*)92;*)"*(,:9
1,2$*1"%9*B"2:92&92B9*19)(";0*)(,2*?,:,*B7,0090.*-"19*19)(";0*=09*>9,)=%90*)(,)
$"= (,:92L)*79,%29;*$9).*Y&2,77$D*0"19 >9,)=%90*,%9*9H#"09;*,0*)(9$*,%9*&1#79192)9;D*2")
,0*)(9$*,%9*=09;.*M<(9*-B,7,*)9,1*&0*A"%E&2'*"2*&1#%":&2'*)(9*-B,7,;"B*#%9092),)&"2D*0"
)(,)*&)*A&77*C9*1"%9*,##%",B(,C79*)"*C9'&229%0*&2*)(9*>=)=%9.N

/9%9*,%9*0"19*)&#0*>"%*2,:&',)&2'*-B,7,;"B*,0*,*29AB"19%*)"*)(9*7,2'=,'9.

c"=*B,2*C%"A09*-B,7,;"B*"27&29*,) ())#RiiAAA.0B,7,J7,2'."%'i,#&D*C=)*&)*&0*,*'"";*&;9,*)"
;"A27",;*,*B"#$*>%"1 ())#RiiAAA.0B,7,J7,2'."%'i;"A27",;0O,#& ,2;*&20),77*&)*7"B,77$.

e27&E9*?,:,;"BD*A(&B(*#%9092)0*,2*,7#(,C9)&B,7*7&0)&2'*">*B7,0090D*-B,7,;"BL0*B7,00*7&0)*&0
0"%)9;*C$*#,BE,'90.*G>*$"=*E2"A*)(9*B7,00*2,19*C=)*2")*)(9*#,BE,'9*2,19D*=09*)(9*>&7)9%
"2*)(9*)"#*79>)*B"%29%*M099 Y&'=%9*3N.

55
Y&'=%9*5J3R <(9*Y&7)9%*V"H*&2*-B,7,;"B

!7&BE*"2*)(9*`*0$1C"7*)"*B79,%*)(9*>&7)9%.

f")9*)(9*Q*,2;*!*0$1C"70*29H)*)"*9,B(*B7,00*2,19.*<(9$*79)*$"=*2,:&',)9*)"*)(9*B7,00*M!N
"%*)(9*B"1#,2&"2*"CI9B)*MQN.

-B,7,;"B*B,2*C9*,*C&)*":9%A(971&2'.*a99#*)(909*)&#0*&2*1&2;R

d <(9 scala. #%9>&H*">*,*#,BE,'9*2,19*B,2*C9*"1&))9;*&2*-B,7,*B";9.*P92),77$*#=)


&)*C,BE*A(92*$"=*B"20=7)*-B,7,;"B.
d 89191C9%*)"*7""E*&2)" RichIntD RichDoubleD*,2;*0"*"2D*&>*$"=*A,2)*)"*E2"A*("A
)"*A"%E*A&)(*2=19%&B*)$#90.*-&1&7,%7$D*)"*A"%E*A&)(*0)%&2'0D*7""E*&2)" StringOps.
d <(9*1,)(91,)&B,7*>=2B)&"20*,%9*&2*)(9 package scala.mathD*2")*&2*,2$*B7,00.
d -"19)&190D*$"=L77*099*>=2B)&"20*A&)(*>=22$*2,190.*Y"%*9H,1#79D BigInt (,0*,
19)("; unary_-.*60*$"=*A&77*099 )(9*nQ#9%,)"%0o*B(,#)9%D*)(&0*&0*("A*$"=*;9>&29
)(9*#%9>&H*29',)&"2*"#9%,)"% -x.
d 6*19)(";*),''9;*,0 implicit &0*,2*,=)"1,)&B*B"2:9%0&"2.*Y"%*9H,1#79D*)(9
BigInt "CI9B)*(,0*B"2:9%0&"20*>%"1 int ,2; long )" BigInt )(,)*,%9*,=)"1,)&B,77$
B,779;*A(92*299;9;.*-99 )(9*nG1#7&B&)0o*B(,#)9% >"%*1"%9*&2>"%1,)&"2*,C"=)
&1#7&B&)*B"2:9%0&"20.
d P9)(";0*B,2*(,:9*>=2B)&"20*,0*#,%,19)9%0.*Y"%*9H,1#79D*)(9 count 19)(";*&2
StringOps %9K=&%90*,*>=2B)&"2*)(,)*%9)=%20 true "% false >"%*, CharD*0#9B&>$&2'
A(&B(*B(,%,B)9%0*0("=7;*C9*B"=2)9;.

def count(p: (Char) => Boolean


Boolean) : Int

c"=*0=##7$*,*>=2B)&"2D*">)92*&2*,*:9%$*B"1#,B)*2"),)&"2D*A(92*$"=*B,77*)(9
19)(";.*60*,2*9H,1#79D*)(9*B,77 s.count(_.isUpper) B"=2)0*)(9*2=1C9%*">
=##9%B,09*B(,%,B)9%0.*b9*A&77*;&0B=00*)(&0*0)$79*">*#%"'%,11&2'*&2*1=B(*1"%9
;9),&7*&2 )(9*n/&'(9%*Q%;9%*Y=2B)&"20o*B(,#)9%.

53
d c"=L77*"BB,0&"2,77$*%=2*&2)"*B7,0090*0=B(*,0 Range "% Seq[Char].*<(9$*19,2*A(,)
$"=%*&2)=&)&"2*)9770*$"=h,*%,2'9*">*2=1C9%0D*,*09K=92B9*">*B(,%,B)9%0.*c"=*A&77
79,%2*,77*,C"=)*)(909*B7,0090*,0*$"=*;97:9*1"%9*;99#7$*&2)"*-B,7,.
d U"2L)*'9)*;&0B"=%,'9;*)(,)*)(9%9*,%9*0"*1,2$*19)(";0.*G)L0*)(9*-B,7,*A,$*)"
#%":&;9*7")0*">*19)(";0*>"%*9:9%$*B"2B9&:,C79*=09*B,09.*b(92*$"=*299;*)"*0"7:9
,*#,%)&B=7,%*#%"C791D*I=0)*7""E*>"%*,*19)(";*)(,)*&0*=09>=7.*P"%9*">)92*)(,2*2")D
)(9%9*&0*"29*)(,)*0"7:90*$"=%*),0ED*A(&B(*19,20*$"=*;"2L)*(,:9*)"*A%&)9*0"*1=B(
B";9*$"=%097>.
d Y&2,77$D*;"2L)*A"%%$*&>*$"=*%=2*&2)"*)(9*"BB,0&"2,7*&2;9B&#(9%,C79*&2B,2),)&"2D
0=B(*,0*)(&0*"29*&2*)(9 StringOps B7,00R

def patch [B >: Char, That](from: Int, patch: GenSeq[B], replaced: Int)(implicit bf: Ca

?=0)*&'2"%9*&).*<(9%9*&0*,2")(9%*:9%0&"2*"> patch )(,)*7""E0*1"%9*%9,0"2,C79.

def patch(from: Int, that: GenSeq[Char], replaced: Int): StringOps[A]

G>*$"=*)(&2E*"> GenSeq[Char] ,2; StringOps[A] ,0 StringD*)(9*19)(";*&0*#%9))$


9,0$*)"*=2;9%0),2;*>%"1*)(9*;"B=192),)&"2.*62;*&)L0*9,0$*)"*)%$*&)*"=)*&2*)(9
8WSTR

"Harry".patch(1, "ung", 2) // c&97;0 "Hungry"

1.8. Exercises
5. G2*)(9*-B,7,*8WSTD*)$#9 3. >"77"A9;*C$*)(9 <6V E9$.*b(,)*19)(";0*B,2*C9
,##7&9;g
3. G2*)(9*-B,7,*8WSTD*B"1#=)9*)(9*0K=,%9*%"")*">*XD*,2;*)(92*0K=,%9*)(,)*:,7=9.*V$
("A*1=B(*;"90*)(9*%90=7)*;&>>9%*>%"1*Xg*M/&2)R*<(9 res :,%&,C790*,%9*$"=%
>%&92;.N
X. 6%9*)(9 res :,%&,C790 val "% varg
Z. -B,7,*79)0*$"=*1=7)&#7$*,*0)%&2'*A&)(*,*2=1C9%h)%$*"=) "crazy" * 3 &2*)(9
8WST.*b(,)*;"90*)(&0*"#9%,)&"2*;"g*b(9%9*B,2*$"=*>&2;*&)*&2*-B,7,;"Bg
[. b(,)*;"90 10 pow 2 19,2g*G2*A(&B(*B7,00*&0*)(9 pow 19)(";*;9>&29;g
\. e0&2' BigIntD*B"1#=)9*3543Z.
]. b(,)*;"*$"=*299;*)"*&1#"%)*0"*)(,)*$"=*B,2*'9)*,*%,2;"1*#%&19*,0
probablePrime(100, Random)D*A&)("=)*,2$*K=,7&>&9%0*C9>"%9 probablePrime ,2;
Randomg
^. Q29*A,$*)"*B%9,)9*%,2;"1*>&79*"%*;&%9B)"%$*2,190*&0*)"*#%";=B9*,*%,2;"1 BigInt
,2;*B"2:9%)*&)*)"*C,09*X\D*$&97;&2'*,*0)%&2'*0=B(*,0 "qsnvbevtomcj38o06kul".*S"E9
,%"=2;*-B,7,;"B*)"*>&2;*,*A,$*">*;"&2'*)(&0*&2*-B,7,.
_. /"A*;"*$"=*'9)*)(9*>&%0)*B(,%,B)9%*">*,*0)%&2'*&2*-B,7,g*<(9*7,0)*B(,%,B)9%g
54. b(,)*;"*)(9 takeD dropD takeRightD*,2; dropRight 0)%&2'*>=2B)&"20*;"g*b(,)
,;:,2),'9i;&0,;:,2),'9*;"*)(9$*(,:9*":9%*=0&2' substringg

5X
2. Control Structures and Functions (A1)
G2*)(&0*B(,#)9%D*$"=*A&77*79,%2*("A*)"*&1#79192)*B"2;&)&"20D*7""#0D*,2;*>=2B)&"20*&2*-B,7,.
c"=*A&77*92B"=2)9%*,*>=2;,192),7*;&>>9%92B9*C9)A992*-B,7,*,2;*")(9%*#%"'%,11&2'
7,2'=,'90.*G2*?,:,*"%*!@@D*A9*;&>>9%92)&,)9*C9)A992 expressions M0=B(*,0 3 + 4N*,2;
statements M>"%*9H,1#79D*,2 if 0),)9192)N.*62*9H#%900&"2*(,0*,*:,7=9F*,*0),)9192)*B,%%&90
"=)*,2*,B)&"2.*G2*-B,7,D*,71"0)*,77*B"20)%=B)0*(,:9*:,7=90.*<(&0*>9,)=%9*B,2*1,E9*#%"'%,10
1"%9*B"2B&09*,2;*9,0&9%*)"*%9,;.

/9%9*,%9*)(9*(&'(7&'()0*">*)(&0*B(,#)9%R

d 62 if 9H#%900&"2*(,0*,*:,7=9
d 6*C7"BE*(,0*,*:,7=9h)(9*:,7=9*">*&)0*7,0)*9H#%900&"2
d <(9*-B,7, for 7""#*&0*7&E9*,2*n92(,2B9;o*?,:, for 7""#
d -91&B"7"20*,%9*M1"0)7$N*"#)&"2,7
d <(9 void )$#9*&0 Unit
d 6:"&;*=0&2' return &2*,*>=2B)&"2
d V9A,%9*">*1&00&2' = &2*,*>=2B)&"2*;9>&2&)&"2
d WHB9#)&"20*A"%E*I=0)*7&E9*&2*?,:,*"%*!@@D*C=)*$"=*=09*,*n#,))9%2*1,)B(&2'o
0$2),H*>"% catch.
d -B,7,*(,0*2"*B(9BE9;*9HB9#)&"20

2.1. Conditional Expressions


-B,7,*(,0*,2 ifielse B"20)%=B)*A&)(*)(9*0,19*0$2),H*,0*)(,)*&2*?,:,*"%*!@@.*/"A9:9%D*&2
-B,7,D*,2 ifielse (,0*,*:,7=9D*2,197$*)(9*:,7=9*">*)(9*9H#%900&"2*)(,)*>"77"A0*)(9 if "%
else.*Y"%*9H,1#79D

if (x > 0) 1 else -1

(,0*,*:,7=9*">*5*"%*J5D*;9#92;&2'*"2*)(9*:,7=9*"> x.*c"=*B,2*#=)*)(,)*:,7=9*&2*,*:,%&,C79R

val s = if (x > 0) 1 else -1

<(&0*(,0*)(9*0,19*9>>9B)*,0

if (x > 0) s = 1 else s = -1

/"A9:9%D*)(9*>&%0)*>"%1*&0*C9))9%R*G)*B,2*C9*=09;*)"*&2&)&,7&p9*, val.*G2*)(9*09B"2;*>"%1D s
299;0*)"*C9*, var.

M60*,7%9,;$*192)&"29;D*091&B"7"20*,%9*1"0)7$*"#)&"2,7*&2*-B,7,h099 -9B)&"2*3N.

5Z
?,:,*,2;*!@@*(,:9*, ?: "#9%,)"%*>"%*)(&0*#=%#"09.*<(9*9H#%900&"2

x > 0 ? 1 : -1 // ?,:,*"%*!@@

&0*9K=&:,792)*)"*)(9*-B,7,*9H#%900&"2 if (x > 0) 1 else -1.*V=)*$"=*B,2L)*#=)*0),)9192)0


&20&;9*, ?: 9H#%900&"2.*<(9*-B,7, ifielse B"1C&290*)(9 ifielse ,2; ?: B"20)%=B)0*)(,)*,%9
09#,%,)9*&2*?,:,*,2;*!@@.

G2*-B,7,D*9:9%$*9H#%900&"2*(,0*,*)$#9.*Y"%*9H,1#79D*)(9*9H#%900&"2 if (x > 0) 1 else -1


(,0*)(9*)$#9 Int C9B,=09*C")(*C%,2B(90*(,:9*)(9*)$#9 Int.*<(9*)$#9*">*,*1&H9;*)$#9
9H#%900&"2*0=B(*,0

if (x > 0) "positive" else -1

&0*)(9*B"11"2*0=#9%)$#9*">*C")(*C%,2B(90.*G2*)(&0*9H,1#79D*"29*C%,2B(*&0*,
java.lang.StringD*,2;*)(9*")(9%*,2 Int.*<(9*B"11"2*0=#9%)$#9*&0*B,779; Any.*M-99 )(9
n<(9*-B,7,*<$#9*/&9%,%B($o*B(,#)9% >"%*;9),&70.N

G>*)(9 else #,%)*&0*"1&))9;D*>"%*9H,1#79*&2

if (x > 0) 1

)(92*&)*&0*#"00&C79*)(,)*)(9 if 0),)9192)*$&97;0*2"*:,7=9.*/"A9:9%D*&2*-B,7,D*9:9%$
9H#%900&"2*&0*0=##"09;*)"*(,:9 some :,7=9.*<(&0*&0*>&29009;*C$*&2)%";=B&2'*,*B7,00 Unit
)(,)*(,0*"29*:,7=9D*A%&))92*,0 ().*<(9 if 0),)9192)*A&)("=)*,2 else &0*9K=&:,792)*)"

if (x > 0) 1 else ()

<(&2E*"> () ,0*,*#7,B9("7;9%*>"%*n2"*=09>=7*:,7=9oD*,2;*)(&2E*"> Unit ,0*)(9*,2,7"'*"> void


&2*?,:,*"%*!@@.

M<9B(2&B,77$*0#9,E&2'D void (,0*2"*:,7=9*A(9%9,0 Unit (,0*"29*:,7=9*)(,)*0&'2&>&90*n2"


:,7=9oD*C=)*A9*A"2L)*;A977*"2*)(,).N

Note: -B,7,*(,0*2" switch 0),)9192)D*C=)*&)*(,0*,*1=B(*1"%9*#"A9%>=7*#,))9%2


1,)B(&2'*19B(,2&01*)(,)*A9*A&77*;&0B=00*&2 )(9*nS,))9%2*P,)B(&2'*,2;*!,09
!7,0090o*B(,#)9%.*Y"%*2"AD*I=0)*=09*,*09K=92B9*"> if 0),)9192)0.

Caution: <(9*8WST*&0*1"%9*29,%0&'()9;*)(,2*)(9*B"1#&79%h&)*"27$*0990*"29
7&29*">*B";9*,)*,*)&19.*Y"%*9H,1#79D*A(92*$"=*)$#9

5[
if (x > 0) 1
else if (x == 0) 0 else -1

)(9*8WST*9H9B=)90 if (x > 0) 1 ,2;*0("A0*)(9*,20A9%.*<(92*&)*'9)0*B"2>=09;


,C"=) else -1.

G>*$"=*A,2)*)"*C%9,E*)(9*7&29*C9>"%9*)(9*9709D*=09*C%,B90R

if (x > 0) { 1
} else if (x == 0) 0 else -1

<(&0*&0*"27$*,*B"2B9%2*&2*)(9*8WST.*G2*,*B"1#&79;*#%"'%,1D*)(9*#,%09%*A&77
>&2;*)(9 else "2*)(9*29H)*7&29.

Tip: G>*$"=*A,2)*)"*#,0)9*,*C7"BE*">*B";9*&2)"*)(9*8WST*A&)("=)*A"%%$&2'
,C"=)*&)0*29,%0&'()9;2900D*=09 paste mode.*<$#9

:paste

<(92*#,0)9*&2*)(9*B";9*C7"BE*,2;*)$#9 !Qf<8QT@a.*<(92*)(9*8WST*,2,7$p90
)(9*C7"BE*&2*&)0*92)&%9)$.

2.2. Statement Termination


G2*?,:,*,2;*!@@D*9:9%$*0),)9192)*92;*&2*,*091&B"7"2.*G2*-B,7,h7&E9*&2*?,:,-B%&#)*,2;
")(9%*0B%&#)&2'*7,2'=,'90h,*091&B"7"2*&0*29:9%*%9K=&%9;*&>*&)*>,770*I=0)*C9>"%9*)(9*92;*">
)(9*7&29.*6*091&B"7"2*&0*,70"*"#)&"2,7*C9>"%9*,2 }D*,2 elseD*,2;*0&1&7,%*7"B,)&"20*A(9%9*&)
&0*B79,%*>%"1*B"2)9H)*)(,)*)(9*92;*">*,*0),)9192)*(,0*C992*%9,B(9;.

/"A9:9%D*&>*$"=*A,2)*)"*(,:9*1"%9*)(,2*"29*0),)9192)*"2*,*0&2'79*7&29D*$"=*299;*)"
09#,%,)9*)(91*A&)(*091&B"7"20.*Y"%*9H,1#79D

if (n > 0) { r = r * n; n -= 1 }

6*091&B"7"2*&0*299;9;*)"*09#,%,)9 r = r * x ,2; n -= 1.*V9B,=09*">*)(9 }D*2"*091&B"7"2


&0*299;9;*,>)9%*)(9*09B"2;*0),)9192).

G>*$"=*A,2)*)"*B"2)&2=9*,*7"2'*0),)9192)*":9%*)A"*7&290D*$"=*299;*)"*1,E9*0=%9*)(,)*)(9
>&%0)*7&29*92;0*&2*,*0$1C"7*)(,) cannot be )(9*92;*">*,*0),)9192).*62*"#9%,)"%*&0*">)92*,
'"";*B("&B9R

5\
s = s0 + (v - v0) * t + // <(9 + )9770*)(9*#,%09%*)(,)*)(&0*&0 not )(9*92;
0.5 * (a - a0) * t * t

G2*#%,B)&B9D*7"2'*9H#%900&"20*=0=,77$*&2:"7:9*>=2B)&"2*"%*19)(";*B,770D*,2;*)(92*"29
;"902L)*299;*)"*A"%%$*1=B(h,>)9%*,2*"#92&2' (D*)(9*B"1#&79%*A"2L)*&2>9%*)(9*92;*">*,
0),)9192)*=2)&7*&)*(,0*0992*)(9*1,)B(&2' ).

G2*)(9*0,19*0#&%&)D*-B,7,*#%"'%,119%0*>,:"%*)(9*a9%2&'(,2*q*8&)B(&9*C%,B9*0)$79R

if (n > 0) {
r = r * n
n -= 1
}

<(9*7&29*92;&2'*A&)(*, { 092;0*,*B79,%*0&'2,7*)(,)*)(9%9*&0*1"%9*)"*B"19.

P,2$*#%"'%,119%0*B"1&2'*>%"1*?,:,*"%*!@@*,%9*&2&)&,77$*=2B"1>"%),C79*,C"=)*"1&))&2'
091&B"7"20.*G>*$"=*#%9>9%*)(91D*I=0)*#=)*)(91*&2h)(9$*;"*2"*(,%1.

2.3. Block Expressions and Assignments


G2*?,:,*"%*!@@D*,*C7"BE*0),)9192)*&0*,*09K=92B9*">*0),)9192)0*92B7"09;*&2 { }.*c"=*=09*,
C7"BE*0),)9192)*A(929:9%*$"=*299;*)"*#=)*1=7)&#79*,B)&"20*&2*)(9*C";$*">*,*C%,2B( "%
7""#*0),)9192).

G2*-B,7,D*, { } C7"BE*B"2),&20*,*09K=92B9*"> expressionsD*,2;*)(9*%90=7)*&0*,70"*,2


9H#%900&"2.*<(9*:,7=9*">*)(9*C7"BE*&0*)(9*:,7=9*">*)(9*7,0)*9H#%900&"2.

<(&0*>9,)=%9*B,2*C9*=09>=7*&>*)(9*&2&)&,7&p,)&"2*">*, val ),E90*1"%9*)(,2*"29*0)9#.*Y"%


9H,1#79D

val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx * dx + dy * dy) }

<(9*:,7=9*">*)(9 { } C7"BE*&0*)(9*7,0)*9H#%900&"2D*0("A2*(9%9*&2*C"7;.*<(9*:,%&,C790 dx
,2; dyD*A(&B(*A9%9*"27$*299;9;*,0*&2)9%19;&,)9*:,790*&2*)(9*B"1#=),)&"2D*,%9*29,)7$
(&;;92*>%"1*)(9*%90)*">*)(9*#%"'%,1.

G2*-B,7,D*,00&'2192)0*(,:9*2"*:,7=9D*"%D*0)%&B)7$*0#9,E&2'D*)(9$*(,:9*,*:,7=9*">*)$#9 Unit.
<(9 Unit )$#9*&0*)(9*9K=&:,792)*">*)(9 void )$#9*&2*?,:,*,2;*!@@.*b(9%9,0 void (,0*2"
:,7=90D*)(9 Unit )$#9*(,0*,*0&2'79*:,7=9*A%&))92*,0 ().*MG>*$"=*,%9*0"*&2B7&29;D*$"=*B,2
#"2;9%*)(9*;&>>9%92B9*C9)A992*,2*91#)$*A,779)*,2;*,*A,779)*A&)(*"29*;"77,%*)(,)*$"=
,%92L)*,77"A9;*)"*0#92;.N

6*C7"BE*)(,)*92;0*&2*,2*,00&'2192)*0),)9192)D*0=B(*,0

5]
{ r = r * n; n -= 1 }

(,0*, Unit :,7=9.*<(&0*&0*2")*,*#%"C791D*I=0)*0"19)(&2'*)"*C9*,A,%9*">*A(92*;9>&2&2'


>=2B)&"20h099 -9B)&"2*\.

V9B,=09*,00&'2192)0*(,:9 Unit :,7=9D*;"2L)*B(,&2*)(91*)"'9)(9%.

x = y = 1 // f"

<(9*:,7=9*"> y = 1 &0 ()D*,2;*&)L0*(&'(7$*=27&E97$*)(,)*$"=*A,2)9;*)"*,00&'2*, Unit )" x.*MG2


B"2)%,0)D*&2*?,:,*,2;*!@@D*)(9*:,7=9*">*,2*,00&'2192)*&0*)(9*:,7=9*)(,)*&0*C9&2'*,00&'29;.
G2*)("09*7,2'=,'90D*B(,&29;*,00&'2192)0*,%9*=09>=7.N

2.4. Loops
-B,7,*(,0*)(9*0,19 while ,2; do 7""#0*,0*?,:,*,2;*!@@.*Y"%*9H,1#79D

while (n > 0) {
r = r * n
n -= 1
}

-B,7,*(,0*2"*;&%9B)*,2,7"'*">*)(9 for (initialize; test; update) 7""#.*G>*$"=*299;*0=B(*,


7""#D*$"=*(,:9*)A"*B("&B90.*c"=*B,2*=09*, while 7""#.*Q%*$"=*B,2*=09*, for 0),)9192)
7&E9*)(&0R

for (i <- 1 to n)
r = r * i

c"=*0,A*)(9 to 19)(";*">*)(9 RichInt B7,00*&2 )(9*n<(9*8WST*,2;*V,0&B*-$2),Ho*B(,#)9%.


<(9*B,77 1 to n %9)=%20*, Range ">*)(9*2=1C9%0*>%"1*5*)" n M&2B7=0&:9N.

<(9*B"20)%=B)

for (i <- expr)

1,E90*)(9*:,%&,C79 i )%,:9%09*,77*:,7=90*">*)(9*9H#%900&"2*)"*)(9*%&'()*">*)(9 <-.*WH,B)7$


("A*)(,)*)%,:9%0,7*A"%E0*;9#92;0*"2*)(9*)$#9*">*)(9*9H#%900&"2.*Y"%*,*-B,7,*B"779B)&"2D
0=B( ,0*, RangeD*)(9*7""#*1,E90 i ,00=19*9,B(*:,7=9*&2*)=%2.

5^
Note: <(9%9*&0*2" val "% var C9>"%9*)(9*:,%&,C79*&2*)(9 for 7""#.*<(9*)$#9*">
)(9*:,%&,C79*&0*)(9*979192)*)$#9*">*)(9*B"779B)&"2.*<(9*0B"#9*">*)(9*7""#
:,%&,C79*9H)92;0*=2)&7*)(9*92;*">*)(9*7""#.

b(92*)%,:9%0&2'*,*0)%&2'*"%*,%%,$D*$"=*">)92*299;*,*%,2'9*>%"1*4*)" n J*5.*G2*)(,)*B,09D*=09
)(9 until 19)(";*&20)9,;*">*)(9 to 19)(";.*G)*%9)=%20*,*%,2'9*)(,)*;"902L)*&2B7=;9*)(9
=##9%*C"=2;.

val s = "Hello"
var sum = 0
for (i <- 0 until s.size
s.size) // T,0)*:,7=9*>"% i &0 s.size - 1
sum += s(i)

G2*)(&0*9H,1#79D*)(9%9*&0*,B)=,77$*2"*299;*)"*=09*&2;9H90.*c"=*B,2*;&%9B)7$*7""#*":9%*)(9
B(,%,B)9%0R

var sum = 0
for (ch <- "Hello") sum += ch

G2*-B,7,D*7""#0*,%9*2")*=09;*,0*">)92*,0*&2*")(9%*7,2'=,'90.*60*$"=*A&77*099*&2 )(9*n/&'(9%
Q%;9%*Y=2B)&"20o*B(,#)9%D*$"=*B,2*">)92*#%"B900*)(9*:,7=90*&2*,*09K=92B9*C$*,##7$&2'*,
>=2B)&"2*)"*,77*">*)(91D*A(&B(*B,2*C9*;"29*A&)(*,*0&2'79*19)(";*B,77.

Note: -B,7,*(,0*2" break "% continue 0),)9192)0*)"*C%9,E*"=)*">*,*7""#.*b(,)


)"*;"*&>*$"=*299;*, breakg*/9%9*,%9*,*>9A*"#)&"20R

5. e09*,*V""79,2*B"2)%"7*:,%&,C79*&20)9,;
3. e09*290)9;*>=2B)&"20h$"=*B,2 return >%"1*)(9*1&;;79*">*,*>=2B)&"2
X. e09*)(9 break 19)(";*&2*)(9 Breaks "CI9B)R

import util.control.Breaks._
breakable {
for (...) {
if (...) break; // WH&)0*)(9 breakable C7"BE
...
}
}

<(9*B"2)%"7*)%,20>9%*&0*;"29*C$*)(%"A&2'*,2;*B,)B(&2'*,2*9HB9#)&"2D*0"
$"=*A,2)*)"*,:"&;*)(&0*19B(,2&01*A(92*)&19*&0*">*)(9*90092B9.

5_
2.5. Advanced For Loops and For Comprehensions
G2*)(9*#%9B9;&2'*09B)&"2D*$"=*0,A*)(9*C,0&B*>"%1*">*)(9 for 7""#.*/"A9:9%D*)(&0*B"20)%=B)
&0*1=B(*%&B(9%*&2*-B,7,*)(,2*&2*?,:,*"%*!@@.*<(&0*09B)&"2*B":9%0*)(9*,;:,2B9;*>9,)=%90.

c"=*B,2*(,:9*1=7)&#79 generators ">*)(9*>"%1 variable <- expression.*-9#,%,)9*)(91*C$


091&B"7"20.*Y"%*9H,1#79D

for (i <- 1 to 3; j <- 1 to 3) print((10 * i + j) + " ")


// S%&2)0 11 12 13 21 22 23 31 32 33

W,B(*'929%,)"%*B,2*(,:9*, guardD*,*V""79,2*B"2;&)&"2*#%9B9;9;*C$ ifR

for (i <- 1 to 3; j <- 1 to 3 if i != jj) print((10 * i + j) + " ")


// S%&2)0 12 13 21 23 31 32

f")9*)(,)*)(9%9*&0*2"*091&B"7"2*C9>"%9*)(9 if.

c"=*B,2*(,:9*,2$*2=1C9%*"> definitionsD*&2)%";=B&2'*:,%&,C790*)(,)*B,2*C9*=09;*&20&;9*)(9
7""#R

for (i <- 1 to 3; from = 4 - i; j <- from to 3) print((10 * i + j) + " ")


// S%&2)0 13 22 23 31 32 33

b(92*)(9*C";$*">*)(9 for 7""#*0),%)0*A&)( yieldD*)(92*)(9*7""#*B"20)%=B)0*,*B"779B)&"2*">


:,7=90D*"29*>"%*9,B(*&)9%,)&"2R

for (i <- 1 to 10) yield i % 3


// c&97;0 Vector(1, 2, 0, 1, 2, 0, 1, 2, 0, 1)

<(&0*)$#9*">*7""#*&0*B,779;*, for comprehension.

<(9*'929%,)9;*B"779B)&"2*&0*B"1#,)&C79*A&)(*)(9*>&%0)*'929%,)"%.

for (c <- "Hello"; i <- 0 to 1) yield (c + i).toChar


// c&97;0 "HIeflmlmop"
for (i <- 0 to 1; c <- "Hello") yield (c + i).toChar
// c&97;0 Vector('H', 'e', 'l', 'l', 'o', 'I', 'f', 'm', 'm', 'p')

Note: G>*$"=*#%9>9%D*$"=*B,2*92B7"09*)(9*'929%,)"%0D*'=,%;0D*,2;*;9>&2&)&"20*">
, for 7""#*&20&;9*C%,B90D*,2;*$"=*B,2*=09*29A7&290*&20)9,;*">*091&B"7"20*)"
09#,%,)9*)(91R

34
for { i <- 1 to 3
from = 4 - i
j <- from to 3 }

2.6. Functions
-B,7,*(,0*>=2B)&"20*&2*,;;&)&"2*)"*19)(";0.*6*19)(";*"#9%,)90*"2*,2*"CI9B)D*C=)*,
>=2B)&"2*;"902L). !@@*(,0*>=2B)&"20*,0*A977D*C=)*&2*?,:,D*$"=*&1&),)9*)(91*A&)(*0),)&B
19)(";0.

<"*;9>&29*,*>=2B)&"2D*$"=*0#9B&>$*)(9*>=2B)&"2L0*2,19D*#,%,19)9%0D*,2;*C";$D*7&E9*)(&0R

def abs(x: Double) = if (x >= 0) x else -x

c"=*1=0)*0#9B&>$*)(9*)$#90*">*,77*#,%,19)9%0D*C=)D*,0*7"2'*,0*)(9*>=2B)&"2*&0*2")*%9B=%0&:9D
$"=*299;*2")*0#9B&>$*)(9*%9)=%2*)$#9.*<(9*-B,7,*B"1#&79%*;9)9%1&290*)(9*%9)=%2*)$#9*>%"1
)(9*)$#9*">*)(9*9H#%900&"2*)"*)(9*%&'()*">*)(9 = 0$1C"7.

G>*)(9*C";$*">*)(9*>=2B)&"2*%9K=&%90*1"%9*)(,2*"29*9H#%900&"2D*=09*,*C7"BE.*<(9*7,0)
9H#%900&"2*">*)(9*C7"BE*C9B"190*)(9*:,7=9*)(,)*)(9*>=2B)&"2*%9)=%20.*Y"%*9H,1#79D*)(9
>"77"A&2'*>=2B)&"2*%9)=%20*)(9*:,7=9*"> r ,>)9%*)(9 for 7""#.

def fac(n : Int) = {


var r = 1
for (i <- 1 to n) r = r * i
r
}

<(9%9*&0*2"*299;*>"%*)(9 return E9$A"%;*&2*)(&0*9H,1#79.*G)*&0*#"00&C79*)"*=09 return ,0*&2


?,:,*"%*!@@D*)"*9H&)*,*>=2B)&"2*&119;&,)97$D*C=)*)(,)*&0*2")*B"11"27$*;"29*&2*-B,7,.

Tip: b(&79*)(9%9*&0*2")(&2'*A%"2'*A&)(*=0&2' return &2*,*2,19;*>=2B)&"2


M9HB9#)*)(9*A,0)9*">*09:92*E9$0)%"E90ND*&)*&0*,*'"";*&;9,*)"*'9)*=09;*)"*7&>9
A&)("=) return.*S%9))$*0""2D*$"=*A&77*C9*=0&2'*7")0*"> anonymous functionsD
,2;*)(9%9D return ;"902L)*%9)=%2*,*:,7=9*)"*)(9*B,779%.*G)*C%9,E0*"=)*)"*)(9
92B7"0&2'*2,19;*>=2B)&"2.*<(&2E*"> return ,0*,*E&2;*"> break 0),)9192)*>"%
>=2B)&"20D*,2;*"27$*=09*&)*A(92*$"=*A,2)*)(,)*C%9,E"=)*>=2B)&"2,7&)$.

b&)(*,*%9B=%0&:9*>=2B)&"2D*$"=*1=0)*0#9B&>$*)(9*%9)=%2*)$#9.*Y"%*9H,1#79D

35
def fac(n: Int):: Int = if (n <= 0) 1 else n * fac(n - 1)

b&)("=)*)(9*%9)=%2*)$#9D*)(9*-B,7,*B"1#&79%*B"=7;2L)*:9%&>$*)(,)*)(9*)$#9*"> n * fac(n -
1) &0*,2 Int.

Note: -"19*#%"'%,11&2'*7,2'=,'90*M0=B(*,0*PT*,2;*/,0E977N can &2>9%*)(9


)$#90*">*%9B=%0&:9*>=2B)&"2D*=0&2'*)(9*/&2;79$JP&729%*,7'"%&)(1.*/"A9:9%D*)(&0
;"902L)*A"%E*A977*&2*,2*"CI9B)J"%&92)9;*7,2'=,'9.*G)*&0*0)&77*,*%909,%B(*#%"C791
("A*)"*9H)92;*)(9*/&2;79$JP&729%*,7'"%&)(1*0"*)(,)*&)*B,2*(,2;79*0=C)$#90.

2.7. Default and Named Arguments (L1)


c"=*B,2*0#9B&>$*;9>,=7)*,%'=192)0*>"%*>=2B)&"20*)(,)*,%9*=09;*A(92*$"=*;"2L)*0#9B&>$
9H#7&B)*:,7=90.*Y"%*9H,1#79D

def decorate(str: String, left: String = "[", right: String = "]") =


left + str + right

<(&0*>=2B)&"2*(,0*)A"*#,%,19)9%0D left ,2; rightD*A&)(*;9>,=7)*,%'=192)0 "[" ,2; "]".

b(92*$"=*B,77 decorate("Hello")D*$"=*'9) "[Hello]".*G>*$"=*;"2L)*7&E9*)(9*;9>,=7)0D


0=##7$*$"=%*"A2R decorate("Hello", "<<<", ">>>").

G>*$"=*0=##7$*>9A9%*,%'=192)0*)(,2*)(9%9*,%9*#,%,19)9%0D*)(9*;9>,=7)0*,%9*,##7&9;*>%"1
)(9*92;.*Y"%*9H,1#79D decorate("Hello", ">>>[") =090*)(9*;9>,=7)*:,7=9*">*)(9
right #,%,19)9%D*$&97;&2' ">>>[Hello]".

c"=*B,2*,70"*=09*)(9*#,%,19)9%*2,190*A(92*$"=*0=##7$*)(9*,%'=192)0.*Y"%*9H,1#79D

decorate(left = "<<<", str = "Hello", right = ">>>")

<(9*%90=7)*&0 "<<<Hello>>>".*f")9*)(,)*)(9*2,19;*,%'=192)0*299;*2")*C9*&2*)(9*0,19
"%;9%*,0*)(9*#,%,19)9%0.

f,19;*,%'=192)0*B,2*1,E9*,*>=2B)&"2*B,77*1"%9*%9,;,C79.*<(9$*,%9*,70"*=09>=7*&>*,
>=2B)&"2*(,0*1,2$*;9>,=7)*#,%,19)9%0.

c"=*B,2*1&H*=22,19;*,2;*2,19;*,%'=192)0D*#%":&;9;*)(9*=22,19;*"290*B"19*>&%0)R

decorate("Hello", right = "]<<<") // B,770 decorate("Hello", "[", "]<<<")

33
2.8. Variable Arguments (L1)
-"19)&190D*&)*&0*B"2:92&92)*)"*&1#79192)*,*>=2B)&"2*)(,)*B,2*),E9*,*:,%&,C79*2=1C9%*">
,%'=192)0.*<(9*>"77"A&2'*9H,1#79*0("A0*)(9*0$2),HR

def sum(args: Int*) = {


var result = 0
for (arg <- args.elements) result += arg
result
}

c"=*B,77*)(9*>=2B)&"2*A&)(*,0*1,2$*,%'=192)0*,0*$"=*7&E9.

val s = sum(1, 4, 9, 16, 25)

<(9*>=2B)&"2*%9B9&:90*,*0&2'79*#,%,19)9%*">*)$#9 SeqD*A(&B(*A9*A&77*;&0B=00*&2 )(9


n!"779B)&"20o*B(,#)9%.*Y"%*2"AD*,77*$"=*299;*)"*E2"A*&0*)(,)*$"=*B,2*$"=*B,2*=09*, for
7""#*)"*:&0&)*9,B(*979192).

G>*$"=*,7%9,;$*(,:9*,*09K=92B9*">*:,7=90D*$"=*B,22")*#,00*&)*;&%9B)7$*)"*0=B(*,*>=2B)&"2.
Y"%*9H,1#79D*)(9*>"77"A&2'*&0*2")*B"%%9B)R

val s = sum(1 to 5) // W%%"%

G>*)(9 sum >=2B)&"2*&0*B,779;*A&)(*"29*,%'=192)D*)(,)*1=0)*C9*,*0&2'79*&2)9'9%D*2")*,*%,2'9


">*&2)9'9%0.*<(9*%919;$*&0*)"*)977*)(9*B"1#&79%*)(,)*$"=*A,2)*)(9*#,%,19)9%*)"*C9
B"20&;9%9;*,0*,2*,%'=192)*09K=92B9.*6##92; : _*D*7&E9*)(&0R

val s = sum(1 to 5: _*) // !"20&;9% 1 to 5 ,0*,2*,%'=192)*09K=92B9

<(&0*0$2),H*&0*299;9;*&2*,*%9B=%0&:9*;9>&2&)&"2R

def sum(args: Int*) : Int =


if (args.length == 0)
0 else
args.head + sum(args.tail : _*)

/9%9D*)(9 head ">*,*09K=92B9*&0*&)0*&2&)&,7*979192)D*,2; tail &0*,*09K=92B9*">*,77*")(9%


979192)0.*<(,)L0*,',&2*, SeqD*,2;*A9*(,:9*)"*=09 : _* )"*B"2:9%)*&)*)"*,2*,%'=192)
09K=92B9.

3X
Caution: b(92*$"=*B,77*,*?,:,*19)(";*A&)(*:,%&,C79*,%'=192)0*">*)$#9
ObjectD*0=B(*,0 PrintStream.printf "% MessageFormat.formatD*)(92*$"=*299;
)"*B"2:9%)*#%&1&)&:9*)$#90*C$*(,2;.*Y"%*9H,1#79D

val str = MessageFormat("The answer to {0} is {1}", "everything",


42.asInstanceOf[AnyRef]
.asInstanceOf[AnyRef])

<(&0*&0*)(9*B,09*>"%*,2$ Object #,%,19)9%D*C=)*G*192)&"2*&)*(9%9*C9B,=09*)(9$


,%9*1"0)*B"11"2*A&)(*:,%,%'0*19)(";0.

2.9. Procedures
-B,7,*(,0*,*0#9B&,7*2"),)&"2*>"%*,*>=2B)&"2*)(,)*%9)=%20*2"*:,7=9.*G>*)(9*>=2B)&"2*C";$*&0
92B7"09;*&2*C%,B90 without a preceding =symbolD*)(92*)(9*%9)=%2*)$#9*&0 Unit.*-=B(*,
>=2B)&"2*&0*B,779;*, procedure.*6*#%"B9;=%9*%9)=%20*2"*:,7=9D*,2;*$"=*"27$*B,77*&)*>"%*&)0
0&;9*9>>9B).*Y"%*9H,1#79D*)(9*>"77"A&2'*#%"B9;=%9*#%&2)0*,*0)%&2'*&20&;9*,*C"HD*7&E9

-------
|Hello|
-------

V9B,=09*)(9*#%"B9;=%9*;"902L)*%9)=%2*,2$*:,7=9D*A9*"1&)*)(9 = 0$1C"7.

def box(s : String) { // T""E*B,%9>=77$R*2" =


val border = "-" * s.size + "--\n"
println(border + "|" + s + "|\n" + border)
}

-"19*#9"#79*M2")*19N*;&07&E9*)(&0*B"2B&09*0$2),H*>"%*#%"B9;=%90*,2;*0=''90)*)(,)*$"=
,7A,$0*=09*,2*9H#7&B&)*%9)=%2*)$#9*"> UnitR

def box(s : String):: Unit = {


...
}

Caution: <(9 B"2B&09*#%"B9;=%9*0$2),H*B,2*C9*,*0=%#%&09*>"%*?,:,*,2;*!@@


#%"'%,119%0.*G)*&0*,*B"11"2*9%%"%*)"*,BB&;92),77$*"1&)*)(9 = &2*,*>=2B)&"2
;9>&2&)&"2.*c"=*'9)*,2*9%%"%*1900,'9*,)*)(9*#"&2)*A(9%9*)(9*>=2B)&"2*&0*B,779;D
,2;*$"=*,%9*)"7;*)(,) Unit &0*2")*,BB9#),C79*,)*)(,)*7"B,)&"2.

3Z
2.10. Lazy Values (L1)
b(92*, val &0*;9B7,%9;*,0 lazyD*&)0*&2&)&,7&p,)&"2*&0*;9>9%%9;*=2)&7*&)*&0*,BB9009;*>"%*)(9*>&%0)
)&19.*Y"%*9H,1#79D

lazy val words = io.Source.fromFile("/usr/share/dict/words").mkString

Mb9*A&77*;&0B=00*>&79*"#9%,)&"20*&2 )(9*nY&790*,2;*89'=7,%*WH#%900&"20o*B(,#)9%.*Y"%*2"AD
I=0)*),E9*&)*>"%*'%,2)9;*)(,)*)(&0*B,77*%9,;0*,77*B(,%,B)9%0*>%"1,*>&79*&2)"*,*0)%&2'.N

G>*)(9*#%"'%,1*29:9%*,BB90090 wordsD*)(9*>&79*&0*29:9%*"#929;.*<"*:9%&>$*)(&0D*)%$*&)*"=)*&2
)(9*8WSTD*C=)*1&00#977*)(9*>&79*2,19.*<(9%9*A&77*C9*2"*9%%"%*A(92*)(9*&2&)&,7&p,)&"2
0),)9192)*&0*9H9B=)9;.*/"A9:9%D*A(92*$"=*,BB900 wordsD*$"=*A&77*'9)*,2*9%%"%*1900,'9
)(,)*)(9*>&79*&0*2")*>"=2;.

T,p$*:,7=90*,%9*=09>=7*)"*;97,$*B"0)7$*&2&)&,7&p,)&"2*0),)9192)0.*<(9$*B,2*,70"*;9,7*A&)(
")(9%*&2&)&,7&p,)&"2*&00=90D*0=B(*,0*B&%B=7,%*;9#92;92B&90.*P"%9":9%D*)(9$*,%9*90092)&,7*>"%
;9:97"#&2'*7,p$*;,),*0)%=B)=%90h099*)(9*-)%9,10*09B)&"2*&2 )(9*n!"779B)&"20o*B(,#)9%.

c"=*B,2*)(&2E*">*7,p$*:,7=90*,0*(,7>A,$*C9)A992 val ,2; def.*!"1#,%9

val words = io.Source.fromFile("/usr/share/dict/words").mkString


// W:,7=,)9;*,0*0""2*,0 words &0*;9>&29;
lazy val words = io.Source.fromFile("/usr/share/dict/words").mkString
// W:,7=,)9;*)(9*>&%0)*)&19 words &0*=09;
def words = io.Source.fromFile("/usr/share/dict/words").mkString
// W:,7=,)9;*9:9%$*)&19 words &0*=09;

Note: T,p&2900*&0*2")*B"0)J>%99.*W:9%$*)&19D*,*7,p$*:,7=9*&0*,BB9009;D*, 19)(";


&0*B,779;*)(,)*B(9BE0D*&2*,*)(%9,;0,>9*1,229%D*A(9)(9%*)(9*:,7=9*(,0*C992
&2&)&,7&p9;.

2.11. Exceptions
-B,7,*9HB9#)&"20*A"%E*)(9*0,19*A,$*,0*&2*?,:,*"%*!@@.*b(92*$"=*)(%"A*,2*9HB9#)&"2D
>"%*9H,1#79

throw new IllegalArgumentException("x should not be negative")

)(92*)(9*B=%%92)*B"1#=),)&"2*&0*,C"%)9;D*,2;*)(9*%=2)&19*0$0)91*7""E0*>"%*,2*9HB9#)&"2
(,2;79%*)(,)*B,2*,BB9#)*,2 IllegalArgumentException.*!"2)%"7*%90=190*A&)(*)(9
&229%1"0)*0=B(*(,2;79%.*G>*2"*0=B(*(,2;79%*9H&0)0D*)(9*#%"'%,1*)9%1&2,)90.

3[
60*&2*?,:,D*)(9*"CI9B)0*)(,)*$"=*)(%"A*299;*)"*C97"2'*)"*,*0=CB7,00*">
java.lang.Throwable.*/"A9:9%D*=27&E9*?,:,D*-B,7,*(,0*2"*nB(9BE9;o*9HB9#)&"20h$"=
29:9%*299;*)"*;9B7,%9*)(,)*,*>=2B)&"2*"%*19)(";*1&'()*)(%"A*,2*9HB9#)&"2.

Note: G2*?,:,D*nB(9BE9;o*9HB9#)&"20*,%9*B(9BE9;*,)*B"1#&79J)&19.*G>*$"=%
19)(";*1&'()*)(%"A*,2 IOExceptionD*$"=*1=0)*;9B7,%9*&).*<(&0*>"%B90
#%"'%,119%0*)"*)(&2E*A(9%9*)("09*9HB9#)&"20*0("=7;*C9*(,2;79;D*A(&B(*&0*,
7,=;,C79*'",7.*e2>"%)=2,)97$D*&)*B,2*,70"*'&:9*%&09*)"*1"20)%"=0*19)(";
0&'2,)=%90*0=B(*,0 void doSomething() throws IOException,
InterruptedException, ClassNotFoundException.*P,2$*?,:,*#%"'%,119%0
;9)90)*)(&0*>9,)=%9*,2;*92;*=#*;9>9,)&2'*&)*C$*9&)(9%*B,)B(&2'*9HB9#)&"20*)""
9,%7$*"%*=0&2'*9HB900&:97$*'929%,7*9HB9#)&"2*B7,0090. <(9*-B,7,*;90&'29%0
;9B&;9;*,',&20)*B(9BE9;*9HB9#)&"20D*%9B"'2&p&2'*)(,)*)("%"='(*B"1#&79J)&19
B(9BE&2'*&02L) always ,*'"";*)(&2'.

6 throw 9H#%900&"2*(,0*)(9*0#9B&,7*)$#9 Nothing.*<(,)*&0*=09>=7*&2 if/else 9H#%900&"20.*G>


"29*C%,2B(*(,0*)$#9 NothingD*)(9*)$#9*">*)(9 if/else 9H#%900&"2*&0*)(9*)$#9*">*)(9*")(9%
C%,2B(.*Y"%*9H,1#79D*B"20&;9%

if (x >= 0) sqrt(x)
else throw new IllegalArgumentException("x should not be negative")

<(9*>&%0)*C%,2B(*(,0*)$#9 DoubleD*)(9*09B"2;*(,0*)$#9 Nothing.*<(9%9>"%9D*)(9 if/else


9H#%900&"2*,70"*(,0*)$#9 Double.

<(9*0$2),H*>"%*B,)B(&2'*9HB9#)&"20*&0*1";979;*,>)9%*)(9*#,))9%2*1,)B(&2'*0$2),H*M099 )(9
nS,))9%2*P,)B(&2'*,2;*!,09*!7,0090o*B(,#)9%N.

try {
process(new FileReader(filename))
} catch {
case _: FileNotFoundException => println(filename + " not found")
case ex: IOException => ex.printStackTrace()
}

60*&2*?,:,*"%*!@@D*)(9*1"%9*'929%,7*9HB9#)&"2*)$#90*0("=7;*B"19*7,)9%*)(,2*)(9*1"%9
0#9B&>&B*"290.

f")9*)(,)*$"=*B,2*=09 _ >"%*)(9*:,%&,C79*2,19*&>*$"=*;"2L)*299;*&).

<(9 try/finally 0),)9192)*79)0*$"=*;&0#"09*">*,*%90"=%B9*A(9)(9%*"%*2")*,2*9HB9#)&"2*(,0


"BB=%%9;.*Y"%*9H,1#79D

3\
val reader = new FileReader(filename)
try {
process(reader)
} finally {
reader.close()
}

<(9 finally B7,=09*&0*9H9B=)9;*A(9)(9%*"%*2")*)(9 process >=2B)&"2*)(%"A0*,2*9HB9#)&"2.


<(9 reader &0*,7A,$0*B7"09;.

<(&0*B";9*&0*,*C&)*0=C)79D*,2;*&)*%,&090*09:9%,7*&00=90.

d b(,)*&>*)(9*B"20)%=B)"%*)(%"A0*,2*9HB9#)&"2g*<(92*)(9 try C7"BE*&0*29:9%


92)9%9;D*,2;*29&)(9%*&0*)(9 finally B7,=09.*<(,)L0*I=0)*,0*A977hreader A,0*29:9%
&2&)&,7&p9;D*0"*&)*1,E90*2"*09209*)"*&2:"E9 close "2*&).
d b($*&02L) val reader = new FileReader(filename) &20&;9*)(9 try C7"BEg*<(92
)(9*0B"#9*"> reader A"=7;*2")*9H)92;*)"*)(9 finally B7,=09.
d b(,)*&> reader.close() )(%"A0*,2*9HB9#)&"2g*<(92*)(,)*9HB9#)&"2*&0*)(%"A2*"=)
">*)(9*0),)9192)D*0=#9%09;&2'*,2$*9,%7&9%*"29.*M<(&0*&0*I=0)*7&E9*&2*?,:,D*,2;*&)*&02L)
:9%$*2&B9.*G;9,77$D*)(9*"7;*9HB9#)&"2*A"=7;*0),$*,)),B(9;*)"*)(9*29A*"29.N

f")9*)(,) try/catch ,2; try/finally (,:9*B"1#79192),%$*'",70.*<(9 try/catch


0),)9192)*(,2;790*9HB9#)&"20D*,2;*)(9 try/finally 0),)9192)*),E90*0"19*,B)&"2*M=0=,77$
B79,2=#N*A(92*,2*9HB9#)&"2*&0*2")*(,2;79;.*G)*&0*#"00&C79*)"*B"1C&29*)(91*&2)"*,*0&2'79
try/catch/finally 0),)9192)

try { ... } catch { ... } finally { ... }

<(&0*&0*)(9*0,19*,0

try { try { ... } catch { ... } } finally { ... }

/"A9:9%D*)(,)*B"1C&2,)&"2*&0*%,%97$*=09>=7.

2.12. Exercises
5. <(9 signum ">*,*2=1C9%*&0*5*&>*)(9*2=1C9%*&0*#"0&)&:9D*J5*&>*&)*&0*29',)&:9*,2;*4*&>
&)*&0*p9%".*b%&)9*,*>=2B)&"2*)(,)*B"1#=)90*)(&0*:,7=9.
3. b(,)*&0*)(9*:,7=9*">*,2*91#)$*C7"BE*9H#%900&"2 {}g*b(,)*&0*&)0*)$#9g
X. !"19*=#*A&)(*"29*0&)=,)&"2*A(9%9*)(9*,00&'2192) x = y = 1 &0*:,7&;*&2*-B,7,.
M/&2)R*S&BE*,*0=&),C79*)$#9*>"% x.N
Z. b%&)9*,*-B,7,*9K=&:,792)*>"%*)(9*?,:,*7""#

for (int i = 10; i >= 0; i--) System.out.println(i);

3]
[. b%&)9*,*#%"B9;=%9 countdown(n: Int) )(,)*#%&2)0*)(9*2=1C9%0*>%"1 n )"*4.
\. b%&)9*, for 7""#*>"%*B"1#=)&2'*)(9*#%";=B)*">*)(9*e2&B";9*B";90*">*,77*79))9%0*&2
,*0)%&2'.*Y"%*9H,1#79D*)(9*#%";=B)*">*)(9*B(,%,B)9%0*&2 "Hello" &0*^3[5[3^_\.
]. -"7:9*)(9*#%9B9;&2'*9H9%B&09*A&)("=)*A%&)&2'*,*7""#.*M/&2)R*T""E*,)*)(9 StringOps
-B,7,;"B.N
^. b%&)9*,*>=2B)&"2 product(s : String) )(,)*B"1#=)90*)(9*#%";=B)D*,0*;90B%&C9;*&2
)(9*#%9B9;&2'*9H9%B&090.
_. P,E9*)(9*>=2B)&"2*">*)(9*#%9B9;&2'*9H9%B&09*,*%9B=%0&:9*>=2B)&"2.
54. b%&)9*,*>=2B)&"2*)(,)*B"1#=)90 xnD*A(9%9 n &0*,2*&2)9'9%.*e09*)(9*>"77"A&2'
%9B=%0&:9*;9>&2&)&"2R

xn r y3 &> n &0*9:92*,2;*#"0&)&:9D*A(9%9 y r xn i*3

xn r xá Hn J*5 &> n &0*";;*,2;*#"0&)&:9

x4 r*5

xn r*5*i xJn &> n &0*29',)&:9

U"2L)*=09*, return 0),)9192).

3^
3. Working With Arrays (A1)
G2*)(&0*B(,#)9%D*$"=*A&77*79,%2*("A*)"*A"%E*A&)(*,%%,$0*&2*-B,7,.*?,:,*,2;*!@@
#%"'%,119%0*=0=,77$*B(""09*,2*,%%,$*"%*,*B7"09*%97,)&"2*M&.9.D*,%%,$*7&0)0*"%*:9B)"%0N*A(92
)(9$*299;*)"*B"779B)*,*C=2B(*">*979192)0.*G2*-B,7,D*)(9%9*,%9*")(9%*B("&B90*M099 )(9
n!"779B)&"20o*B(,#)9%ND*C=)*>"%*2"AD*GL77*,00=19*)(,)*$"=*,%9*&1#,)&92)*,2;*I=0)*A,2)*)"*'9)
'"&2'*A&)(*,%%,$0.

a9$*#"&2)0*">*)(&0*B(,#)9%R

d e09*,2 Array &>*)(9*0&p9*&0*>&H9;D*,2 ArrayBuffer &>*)(9*0&p9*B,2*:,%$


d c"=*;"2L)*=09 new A(92*$"=*0=##7$*&2&)&,7*:,7=90
d e09 () )"*,BB900*979192)0
d e09 for (elem <- arr) )"*)%,:9%09*)(9*979192)0
d e09 for (elem <- arr if ...) ...yield ...*)"*)%,20>"%1*&2)"*,*29A*,%%,$
d -B,7,*,2;*?,:,*6%%,$0*,%9*&2)9%"#9%,C79F*A&)( ArrayBufferD*=09
collection.JavaConversions

3.1. Fixed Size Arrays


G>*$"=*299;*,2*,%%,$*A("09*0&p9*;"902L)*B(,2'9D*=09*)(9 Array )$#9*&2*-B,7,.*Y"%*9H,1#79D

val a = new Array[String](10)


// 6*0)%&2'*,%%,$*A&)(*)92*979192)0D*,77*&2&)&,7&p9;*A&)( null
val s = Array("Hello", "World")
// 62 Array[String] ">*0&p9*3h)(9*)$#9*&0*&2>9%%9;
// f")9R*f" new A(92*$"=*0=##7$*&2&)&,7*:,7=90
s(0) = "Goodbye"
// Array("Goodbye"
"Goodbye", World")
// e09 () &20)9,;*"> [] >"%*979192)*,BB900

G20&;9*)(9*?sPD*,*-B,7, Array &0*&1#79192)9;*,0*,*?,:,*,%%,$*.*<(9*,%%,$0*&2*)(9


#%9B9;&2'*9H,1#79*(,:9*)(9*)$#9 java.lang.String[] &20&;9*)(9*?sP.*62*,%%,$*"> IntD
DoubleD*"%*,2")(9%*9K=&:,792)*">*)(9*?,:,*#%&1&)&:9*)$#90D*&0*,*#%&1&)&:9*)$#9*,%%,$.*Y"%
9H,1#79D Array(2,3,5,7,11) &0*,2 int[] &2*)(9*?sP.

3.2. Variable Size Arrays: Array Buffers


?,:,*(,0 ArrayList ,2;*!@@*(,0 vector >"%*,%%,$0*)(,)*'%"A*,2;*0(%&2E*"2*;91,2;.*<(9
9K=&:,792)*&2*-B,7,*&0*)(9 ArrayBuffer.

3_
import collection.mutable.ArrayBuffer
val b = ArrayBuffer[Int]()
// Q% new ArrayBuffer[Int]
// 62*91#)$*,%%,$*C=>>9%D*%9,;$*)"*("7;*&2)9'9%0
b += 1
// ArrayBuffer(1)
// 6;;*,2*979192)*,)*)(9*92;*A&)( +=
b += (1, 2, 3, 5)
// ArrayBuffer(1, 1, 2, 3, 55)
// 6;;*1,2$*979192)0*,)*)(9*92;*C$*92B7"0&2'*)(91*&2*#,%92)(9090
b ++= Array(8, 11, 17)
// ArrayBuffer(1, 1, 2, 3, 5, 8, 11, 17 17)
// c"=*B,2*,##92;*,2$*B"779B)&"2*A&)(*)(9 ++= "#9%,)"%
b.trimEnd(2)
// ArrayBuffer(1, 1, 2, 3, 5, 8)
// 891":90*)(9*7,0)*)A"*979192)0

6;;&2'*"%*%91":&2'*979192)0*,)*)(9*92;*">*,2*,%%,$*C=>>9%*&0*,2*9>>&B&92)*Mn,1"%)&p9;
B"20),2)*)&19oN*"#9%,)&"2.

c"=*B,2*,70"*&209%)*,2;*%91":9*979192)0*,)*,2*,%C&)%,%$*7"B,)&"2D*C=)*)("09*"#9%,)&"20*,%9
2")*,0*9>>&B&92)h,77*979192)0*,>)9%*)(,)*7"B,)&"2*1=0)*C9*0(&>)9;.*Y"%*9H,1#79R

b.insert(2, 6)
// ArrayBuffer(1, 1, 6, 2)
// G209%)*C9>"%9*&2;9H*3
b.insert(2, 7, 8, 99)
// ArrayBuffer(1, 1, 7, 8, 99, 6, 2)
// c"=*B,2*&209%)*,0*1,2$*979192)0*,0*$"=*7&E9
b.remove(2)
// ArrayBuffer(1, 1, 8, 9, 6, 2)
b.remove(2, 3)
// ArrayBuffer(1, 1, 2)
// <(9*09B"2;*#,%,19)9%*)9770*("A*1,2$*979192)0*)"*%91":9

-"19)&190D*$"=*A,2)*)"*C=&7;*=#*,2 ArrayD*C=)*$"=*;"2L)*$9)*E2"A*("A*1,2$*979192)0
$"=*A&77*299;.*G2*)(,)*B,09D*>&%0)*1,E9*,2*,%%,$*C=>>9%D*)(92*B,77

b.toArray
// Array(1, 1, 2)

!"2:9%097$D*B,77 a.toBuffer )"*B"2:9%)*)(9*,%%,$ a )"*,2*,%%,$*C=>>9%.

X4
3.3. Traversing Arrays (and Array Buffers)
G2*?,:,*,2;*!@@D*)(9%9*,%9*09:9%,7*0$2),B)&B,7*;&>>9%92B90*C9)A992*,%%,$0*,2;*,%%,$*7&0)i
:9B)"%.*-B,7,*&0*1=B(*1"%9*=2&>"%1.*P"0)*">*)(9*)&19D*$"=*B,2*=09*)(9*0,19*B";9*>"%
C")(.

/9%9*&0*("A*$"=*)%,:9%09*,2*,%%,$*"%*,%%,$*C=>>9%*A&)(*, for 7""#.

for (i <- 0 until a.size)


println(i + ": " + a(i))

<(9*:,%&,C79 i '"90*>%"1*4*)" a.size - 1.

<(9 until 19)(";*C97"2'0*)"*)(9 RichInt B7,00D*,2;*&)*%9)=%20*,77*2=1C9%0*=#*)"*MC=)*2")


&2B7=;&2'N*)(9*=##9%*C"=2;.*Y"%*9H,1#79D

0 until 10
// Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

f")9*)(,) 0 until 10 &0*,B)=,77$*,*19)(";*B,77 0.until(10).

<(9*B"20)%=B)

for (i <- range)

1,E90*)(9*:,%&,C79 i )%,:9%09*,77*:,7=90*">*)(9*%,2'9 <-.*G2*"=%*B,09D*)(9*7""#*:,%&,C79 i


,00=190*)(9*:,7=90*4D*5D*,2;*0"*"2D*=2)&7*MC=)*2")*&2B7=;&2'N a.size.

<"*:&0&)*9:9%$*09B"2;*979192)D*79) i )%,:9%09

0 until (a.size, 2)
// Range(0, 2, 4, ...)

<"*:&0&)*)(9*979192)0*0),%)&2'*>%"1*)(9*92;*">*)(9*,%%,$D*)%,:9%09

(0 until a.size).reverse
// Range(..., 2, 1, 0)

G>*$"=*;"2L)*299;*)(9*,%%,$*&2;9H*&2*)(9*7""#*C";$D*:&0&)*)(9*,%%,$*979192)0*;&%9B)7$D*7&E9
)(&0R

for (elem <- a)


println(elem)

X5
<(&0*&0*:9%$*0&1&7,%*)"*)(9*n92(,2B9;ofor 7""#*&2*?,:,*"%*)(9*n%,2'9JC,09;o for 7""#*&2
!@@.*<(9*:,%&,C79 elem &0*09)*)" a(0)D*)(92 a(1)D*,2;*0"*"2.

3.4. Transforming Arrays


G2*)(9*#%9B9;&2'*09B)&"20D*$"=*0,A*("A*)"*A"%E*A&)(*,%%,$0*I=0)*7&E9*$"=*A"=7;*&2*?,:,*"%
!@@.*V=)*&2*-B,7,D*$"=*B,2*'"*>=%)(9%.*G)*&0*:9%$*9,0$*)"*),E9*,2*,%%,$*M"%*,%%,$*C=>>9%N*,2;
)%,20>"%1*&)*&2*0"19*A,$.*<(909*)%,20>"%1,)&"20*;"2L)*1";&>$*)(9*"%&'&2,7*,%%,$D*C=)*)(9$
$&97;*,*29A*"29.

e09*, for B"1#%9(920&"2D*7&E9*)(&0R

val a = Array(2, 3, 5, 7, 11)


val result = for (elem <- a) yield 2 * elem
// result &0 Array(4, 6, 10, 14, 22)

<(9 for (...) yield 7""#*B%9,)90*,*29A*B"779B)&"2*">*)(9*0,19*)$#9*,0*)(9*"%&'&2,7


B"779B)&"2.*G>*$"=*0),%)9;*A&)(*,2*,%%,$D*$"=*'9)*,2")(9%*,%%,$.*G>*$"=*0),%)9;*A&)(*,2*,%%,$
C=>>9%D*)(,)L0*A(,)*$"=*'9)*>%"1 for (...) yield.

<(9*%90=7)*B"2),&20*)(9*9H#%900&"20*,>)9%*)(9 yieldD*"29*>"%*9,B(*&)9%,)&"2*">*)(9*7""#.

Q>)92*)&190D*A(92*$"=*)%,:9%09*,*B"779B)&"2D*$"=*"27$*A,2)*)"*#%"B900*)(9*"290*)(,)*1,)B(
,*#,%)&B=7,%*B"2;&)&"2.*<(&0*&0*,B(&9:9;*A&)(*, guardR*,2 if &20&;9*)(9 for.*/9%9*A9*%9)=%2
"27$*)(9*9:92*979192)0R

for (elem <- b if (b % 2 == 0)


0)) yield elem

62;*(9%9*A9*;"=C79*9:9%$*9:92*979192)D*0)&77*;%"##&2'*)(9*";;*"290R

for (elem <- b if (b % 2 == 0)) yield 2 * elem

a99#*&2*1&2;*)(,)*)(9*%90=7)*&0*,*29A*B"779B)&"2h)(9*"%&'&2,7*B"779B)&"2*&0*2")*,>>9B)9;.

Note: 67)9%2,)&:97$D*$"=*B"=7;*A%&)9

b.filter(_ % 2 == 0).map(2 * _)

"%*9:92

b filter { _ % 2 == 0 } map { 2 * _ }

X3
-"19*#%"'%,119%0*A&)(*9H#9%&92B9*&2*>=2B)&"2,7*#%"'%,11&2'*#%9>9% filter
,2; map &20)9,;*">*'=,%;0*,2; yield.*<(,)L0*I=0)*,*1,))9%*">*0)$79h)(9 for 7""#
;"90*9H,B)7$*)(9*0,19*A"%E.*e09*A(,)9:9%*$"=*>&2;*9,0&9%.

!"20&;9%*)(9*>"77"A&2'*9H,1#79.*t&:92*,*09K=92B9*">*&2)9'9%0D*A9*A,2)*)"*%91":9*,77*C=)
)(9*>&%0)*29',)&:9*2=1C9%.*6*)%,;&)&"2,7*09K=92)&,7*0"7=)&"2*A"=7;*09)*,*>7,'*A(92*)(9*>&%0)
29',)&:9*2=1C9%*&0*B,779;D*)(92*%91":9*,77*979192)0*C9$"2;.

var first = true


var n = a.size
var i = 0
while (i < n) {
if (a[i] >= 0) i += 1
else {
if (first) { first = false; i += 1 }
else { a.remove(i); n -= 1 }
}
}

V=)*A,&)h)(,)L0*,B)=,77$*2")*0"*'"";.*G)L0*&29>>&B&92)*)"*%91":9*:,%&,C790*>%"1*)(9*>%"2).
b9*0("=7;*0),%)*>%"1*)(9*C,BE*,>)9%*>&2;&2'*)(9*>&%0)*1,)B(.

G2*-B,7,D*$"=%*7&>9*B,2*C9*9,0&9%.*Y&%0)D*79)L0*=09*, foriyield 7""#*)"*>&2;*,77*1,)B(&2'*&2;9H


:,7=90.

val indexes = for (i <- 0 until a.size if a(i) < 0) yield i

<(92*A9*:&0&)*)(9*&2;9H90*&2*%9:9%09D*9HB9#)*>"% indexes(0).

for (j <- (1 until indexes.size).reverse) a.remove(indexes(j))

<(9*E9$*"C09%:,)&"2*&0*)(,)*&)*&0*C9))9%*)"*(,:9 all index values together &20)9,;*">*099&2'


)(91*"29*C$*"29.

3.5. Common Algorithms


G)*&0*">)92*0,&;*)(,)*,*7,%'9*#9%B92),'9*">*C=0&2900*B"1#=),)&"20*,%9*2")(&2'*C=)
B"1#=)&2'*0=10*,2;*0"%)&2'.*Y"%)=2,)97$D*-B,7,*(,0*C=&7)J&2*>=2B)&"20*>"%*)(909*),0E0.

Array(1, 7, 2, 9).sum
// 19
// b"%E0*>"% ArrayBuffer )""

XX
G2*"%;9%*)"*=09*)(9 sum 19)(";D*)(9*979192)*)$#9*1=0)*C9*,*2=19%&B*)$#9R*,2*&2)9'%,7*"%
>7",)&2'J#"&2)*)$#9D*"% BigIntegeriBigDecimal.

-&1&7,%7$D*)(9 min ,2; max 19)(";0*$&97;*)(9*01,7790)*,2;*7,%'90)*979192)*&2*,2*,%%,$*"%


,%%,$*C=>>9%.

ArrayBuffer("Mary", "had", "a", "little", "lamb").max


max
// "little"

<(9 sortWith 19)(";*0"%)0*,2*,%%,$*"%*,%%,$*C=>>9%*,2; returns )(9*0"%)9;*,%%,$*"%*,%%,$


C=>>9%D*A&)("=)*1";&>$&2'*)(9*"%&'&2,7R

val b = ArrayBuffer(1, 7, 2, 9)
val bSorted = b.sortWith(_ < _)
// b &0*=2B(,2'9;F bSorted &0 ArrayBuffer(1, 2, 7, 9)

c"=*#,00*)(9*B"1#,%&0"2*>=2B)&"2*,0*,*#,%,19)9%h099 )(9*n/&'(9%*Q%;9%*Y=2B)&"20o
B(,#)9% >"%*)(9*>=2B)&"2*0$2),H.

c"=*B,2*0"%)*,2*,%%,$D*C=)*2")*,2*,%%,$*C=>>9%D*&2*#7,B9R

val a = Array(1, 7, 2, 9)
util.Sorting.quickSort(a)
// a &0*2"A Array(1, 2, 7, 9)

Y"%*)(9 minimax ,2; quickSort 19)(";0D*)(9*979192)*)$#9*1=0)*(,:9*,*B"1#,%&0"2


"#9%,)&"2.*<(&0*&0*)(9*B,09*>"%*2=1C9%0D*0)%&2'0D*,2;*")(9%*)$#90*A&)(*)(9 Ordered )%,&).

Y&2,77$D*&>*$"=*A,2)*)"*;&0#7,$*)(9*B"2)92)0*">*,2*,%%,$*"%*,%%,$*C=>>9%D*)(9
mkString 19)(";*79)0*$"=*0#9B&>$*)(9*09#,%,)"%*C9)A992*979192)0.*6*09B"2;*:,%&,2)*(,0
#,%,19)9%0*>"%*)(9*#%9>&H*,2;*0=>>&H.*Y"%*9H,1#79D

a.mkString(" and ")


// "1 and 7 and 2 and 9"
a.mkString(",", "<", ">")
// "<1,7,2,9>"

!"2)%,0)*A&)( toStringR

a.toString
// "[I@b73e5"
// <(&0*&0*)(9*=097900 toString 19)(";*>%"1*?,:,
b.toString
// "ArrayBuffer(1, 7, 2, 9)"
// <(9 toString 19)(";*B"2),&20*)(9*)$#9D*A(&B(*&0*=09>=7*>"%*;9C=''&2'

XZ
3.6. Deciphering ScalaDoc
<(9%9*,%9*7")0*">*=09>=7*19)(";0*"2*,%%,$0*,2;*,%%,$*7&0)0D*,2;*&)*&0*,*'"";*&;9,*)"*C%"A09
)(9*-B,7,*;"B=192),)&"2*)"*'9)*,2*&;9,*A(,)L0*)(9%9.

Note: <(9*19)(";0*>"%*)(9 Array B7,00*,%9*7&0)9;*=2;9% ArrayOps.*<9B(2&B,77$D


,2*,%%,$*&0*B"2:9%)9;*)"*,2 ArrayOps "CI9B)*C9>"%9*,2$*">*)(9*"#9%,)&"20*&0
,##7&9;.

V9B,=09*-B,7,*(,0*%&B(9%*)$#9*0$0)91*)(,2*?,:,D*$"=*1,$*92B"=2)9%*0"19*0)%,2'9J7""E&2'
0$2),H*,0*$"=*C%"A09*)(9*-B,7,*;"B=192),)&"2.*Y"%)=2,)97$D*$"=*;"2L)*(,:9*)"*=2;9%0),2;
,77*2=,2B90*">*)(9*)$#9*0$0)91*)"*;"*=09>=7*A"%E.*e09 <,C79*5 ,0*,*n;9B";9%*%&2'o.

<,C79*XJ5R -B,7,U"B*U9B";9%*8&2'
ScalaDoc Explanation
<(&0*19)(";*),E90*, predicateD*,*>=2B)&"2*>%"1*6*)"
def count (p:
p: (A) => V""79,2.*G)*B"=2)0*>"%*("A*1,2$*979192)0*)(9*>=2B)&"2
Boolean
Boolean) : Int &0*)%=9.*Y"%*9H,1#79D a.count(_ > 0) B"=2)0*("A*1,2$
979192)0*"> a ,%9*#"0&)&:9.
<(&0*19)(";*),E90 zero or more ,%'=192)0*">*)$#9 A.*Y"%
def append (elems: A*
A*) :
9H,1#79D a.append(1, 7, 2, 9) ,##92;0*>"=%*979192)0
Unit
)" a.
<(9 xs #,%,19)9%*B,2*C9*,2$*B"779B)&"2*A&)(*)(9
TraversableOnce )%,&)D*)(9*1"0)*'929%,7*)%,&)*&2*)(9*-B,7,
B"779B)&"20*(&9%,%B($.*Q)(9%*B"11"2*)%,&)0*)(,)*$"=*1,$
92B"=2)9%*&2*-B,7,U"B*,%9*,%9 Traversable ,2;
Iterable.*677*-B,7,*B"779B)&"20*&1#79192)*)(909*)%,&)0D
def appendAll (xs: ,2;*)(9*;&>>9%92B9*C9)A992*)(91*&0*,B,;91&B*>"%*7&C%,%$
TraversableOnce[A]
TraversableOnce[A]) : Unit =09%0.*-&1#7$*)(&2E*n,2$*B"779B)&"2o*A(92*$"=*099*"29
">*)(909.

/"A9:9%D*)(9 Seq )%,&)*%9K=&%90*979192)*,BB900*C$*,2


&2)9'9%*&2;9H.*<(&2E*n,%%,$D*7&0)D*"%*0)%&2'o.

def += (elem: A) : <(&0*19)(";*%9)=%20 thisD*A(&B(*,77"A0*$"=*)"*B(,&2


ArrayBuffer.this.type B,770.*Y"%*9H,1#79D a += 4 -= 5.

X[
b(92*$"=*A"%E*A&)(*,2 ArrayBuffer[A]D*$"=*B,2*I=0)
)(&2E*">*)(9*19)(";*,0 def += (elem: A) :
ArrayBuffer[A].

G>*0"19"29*>"%10*,*0=CB7,00*"> ArrayBufferD*)(92*)(9
%9)=%2*)$#9*"> += &0*)(,)*0=CB7,00.

f")9*)(,)*)(9*>=2B)&"2*B"#&90*,2 ArrayBuffer[A]
[A] &2)"*,2
Array[B]
[B].*/9%9D*V*&0*,77"A9;*)"*C9*, supertype ">*6.*Y"%
9H,1#79D*$"=*B,2*B"#$*>%"1*,2 ArrayBuffer[Int] )"*,2
def copyToArray [B >: A] Array[Any].
(xs: Array[B]
Array[B]) : Unit
6)*>&%0)*%9,;&2'D*I=0)*&'2"%9*)(9 [B >: A] ,2;*%9#7,B9 B
A&)( A.

A 1=0)*(,:9*,*0=#9%)$#9 B >"%*A(&B(*,2*n&1#7&B&)o*"CI9B)
def max [B >: A] (implicit
">*)$#9 Ordering[B] 9H&0)0.*-=B(*,2*"%;9%&2'*9H&0)0*>"%
cmp: Ordering[B]) : A
2=1C9%0D*0)%&2'0D*,2;*")(9%*)$#90*A&)(*)(9 Ordered )%,&).
<(&0*;9B7,%,)&"2*(,##920*A(92*)(9*19)(";*B%9,)90*,
29A*B"779B)&"2.*-E&#*&)*,2;*7""E*>"%*)(9*0&1#79%
def padTo [B >: A, That
That] ,7)9%2,)&:9D*&2*)(&0*B,09
(len: Int, elem: B)(implicit
(implicit
bf: def padTo (len: Int, elem: A) : ArrayBuffer[A]
CanBuildFrom[ArrayBuffer[A],
B, That]) : That 6*>=)=%9*:9%0&"2*">*-B,7,;"B*A&77*(&;9*)(909
;9B7,%,)&"20.

3.7. Multi-Dimensional Arrays


T&E9*&2*?,:,D*1=7)&J;&1920&"2,7*,%%,$0*,%9*&1#79192)9;*,0*,%%,$0*">*,%%,$0.*Y"%*9H,1#79D
,*)A"J;&1920&"2,7*,%%,$*"> Double :,7=90*(,0*)(9*)$#9 Array[Array[Double]].*<"
B"20)%=B)*0=B(*,2*,%%,$D*=09*)(9 ofDim 19)(";R

val matrix = Array.ofDim[Double](3, 4) // <(%99*%"A0D*>"=%*B"7=120

<"*,BB900*,2*979192)D*$"=*=09*)A"*#,&%0*">*#,%92)(9090R

matrix(row)(column) = 42

X\
3.8. Interoperating with Java
-&2B9*-B,7,*,%%,$0*,%9*&1#79192)9;*,0*?,:,*,%%,$0D*$"=*B,2*#,00*)(91*C,BE*,2;*>"%)(
C9)A992*?,:,*,2;*-B,7,.

G>*$"=*B,77*,*?,:,*19)(";*)(,)*%9B9&:90*"%*%9)=%20*, java.util.ListD*$"=*B"=7;*">*B"=%09
=09*,*?,:, ArrayList &2*$"=%*-B,7,*B";9D*C=)*)(,)*&0*=2,))%,B)&:9.*G20)9,;D*&1#"%)*)(9
&1#7&B&)*B"2:9%0&"2*19)(";0*&2 collection.JavaConversions.*<(92*$"=*B,2*=09*-B,7,
C=>>9%0*&2*$"=%*B";9D*,2;*)(9$*,=)"1,)&B,77$*'9)*A%,##9;*&2)"?,:,*7&0)0*A(92*B,77&2'*,
?,:,*19)(";.

Y"%*9H,1#79D*)(9 java.lang.ProcessBuilder B7,00*(,0*,*B"20)%=B)"%*A&)(*, List<String>


#,%,19)9%.*/9%9*&0*("A*$"=*B,2*B,77*&)*>%"1*-B,7,.

import collection.JavaConversions.asJavaList
// Q%*0&1#7$ import collection.JavaConversions._
val commands = collection.mutable.ArrayBuffer("ls", "-al", "/home/cay")
val pb = new ProcessBuilder(commands)

<(9*-B,7,*C=>>9%*&0*A%,##9;*&2)"*,2*"CI9B)*">*,*?,:,*B7,00*)(,)*&1#79192)0*)(9
java.util.List &2)9%>,B9.

!"2:9%097$D*A(92*,*?,:,*19)(";*%9)=%20*, java.util.ListD*$"=*B,2*(,:9*&)*,=)"1,)&B,77$
B"2:9%)9;*&2)"*, BufferR

import collection.JavaConversions.asScalaBuffer
val cmds : collection.mutable.Buffer[String] = pb.commands()
// c"=*B,2L)*=09 ArrayBufferh)(9*A%,##9;*"CI9B)*&0*"27$*'=,%,2)99;*)"*C9*, Buffer

G>*)(9*?,:,*19)(";*%9)=%20*,*A%,##9;*-B,7,*C=>>9%D*)(92*)(9*&1#7&B&)*B"2:9%0&"2*=2A%,#0
)(9*"%&'&2,7*"CI9B).*G2*"=%*9H,1#79D cmds == commands.

<(9*9H#7&B&)*#,BE,'9*2,190*1,E9*)(9*0,1#79*B";9*1"%9*B"1#79H*)(,2*A(,)*$"=*A"=7;
;"*&2*#%,B)&B9.*b&)(*)(9*&1#"%)0

import collection.JavaConversions._
import collection.mutable.Buffer

A9*(,:9

val pb = new ProcessBuilder(Buffer("ls", "-al", "/home/cay")) // -B,7,*)"*?,:,


val cmds : Builder[String] = pb.commands() // ?,:,*)"*-B,7,

X]
3.9. Exercises
5. b%&)9*,*B";9*02&##9)*)(,)*09)0 a )"*,2*,%%,$*"> n %,2;"1*&2)9'9%0*C9)A992*4
M&2B7=0&:9N*,2; n M9HB7=0&:9N.
3. b%&)9*,*7""#*)(,)*0A,#0*,;I,B92)*979192)0*">*,2*,%%,$*">*&2)9'9%0.*Y"%*9H,1#79D
Array(1, 2, 3, 4, 5) C9B"190 Array(2, 1, 4, 3, 5).
X. 89#9,)*)(9*#%9B9;&2'*,00&'2192)D*C=)*#%";=B9*,*29A*,%%,$*A&)(*)(9*0A,##9;
:,7=90.*e09 foriyield.
Z. t&:92*,2*,%%,$*">*&2)9'9%0D*#%";=B9*,*29A*,%%,$*)(,)*B"2),&20*,77*#"0&)&:9*:,7=90
">*)(9*"%&'&2,7*,%%,$D*&2*)(9&%*"%&'&2,7*"%;9%D*>"77"A9;*C$*,77*:,7=90*)(,)*,%9*p9%"*"%
29',)&:9D*&2*)(9&%*"%&'&2,7*"%;9%.
[. /"A*;"*$"=*B"1#=)9*)(9*,:9%,'9*">*,2 Array[Double]g
\. /"A*;"*$"=*%9,%%,2'9*)(9*979192)0*">*,2 Array[Int] 0"*)(,)*)(9$*,##9,%*&2
%9:9%09*0"%)9;*"%;9%g*/"A*;"*$"=*;"*)(9*0,19*A&)(*,2 ArrayBuffer[Int]g
]. b%&)9*,*B";9*02&##9)*)(,)*#%";=B90*,77*:,7=90*>%"1*,2*,%%,$*A&)(*;=#7&B,)90
%91":9;.*M/&2)R*T""E*,)*-B,7,U"BN
^. 89A%&)9*)(9*9H,1#79*,)*)(9*92;*"> -9B)&"2*Z =0&2'*)(9 drop 19)(";*>"%*;%"##&2'
)(9*&2;9H*">*)(9*>&%0)*1,)B(.*T""E*)(9*19)(";*=#*&2*-B,7,U"B.
_. P,E9*,*B"779B)&"2*">*,77*)&19*p"290*%9)=%29;*C$
java.util.TimeZone.getAvailableIds )(,)*,%9*&2*619%&B,.*-)%&#*">>*)(9
"America/" #%9>&H*,2;*0"%)*)(9*%90=7).
54. G1#"%) java.awt.datatransfer._ ,2;*1,E9*,2*"CI9B)*">*)$#9 SystemFlavorMap
A&)(*)(9*B,77

val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]

<(92*B,77*)(9 getNativesForFlavor 19)(";*A&)(*#,%,19)9%


DataFlavor.imageFlavorD*,2;*'9)*)(9*%9)=%2*:,7=9*,0*,*-B,7,*C=>>9%.*Mb($*)(&0
"C0B=%9*B7,00g*G)L0*(,%;*)"*>&2;*=090*"> java.util.List &2*)(9*0),2;,%;*?,:,
7&C%,%$.N

X^
4. Maps and Tuples (A1)
6*B7,00&B*#%"'%,119%L0*0,$&2'*&0*nG>*G*B,2*"27$*(,:9*"29*;,),*0)%=B)=%9D*1,E9*&)*,*(,0(
),C79o.*/,0(*),C790D*"%*1"%9*'929%,77$D*1,#0D*,%9*,1"2'*)(9*1"0)*:9%0,)&79*;,),*0)%=B)=%90.
60*$"=*A&77*099*&2*)(&0*B(,#)9%D-B,7,*1,E90*&)*#,%)&B=7,%7$*9,0$*)"*=09*)(91.

P,#0*,%9*,*B"779B)&"2*">*E9$i:,7=9*#,&%0.*-B,7,*(,0*,*'929%,7*2"),)&"2*">*)=#790D
,''%9',)90*"> n "CI9B)0D*2")*29B900,%&7$*">*)(9*0,19*)$#9.*6*#,&%*&0*0&1#7$*,*)=#79*A&)( n r
3.*<=#790*,%9*=09>=7*A(929:9%*$"=*299;*)"*,''%9',)9*)A"*"%*1"%9*:,7=90*)"'9)(9%D*,2;*A9
C%&9>7$*;&0B=00*)(9*0$2),H*,)*)(9*92;*">*)(&0*B(,#)9%.

/&'(7&'()0*">*)(9*B(,#)9%*,%9R

d -B,7,*(,0*,*#79,0,2)*0$2),H*>"%*B%9,)&2'D*K=9%$&2'D*,2;*)%,:9%0&2'*1,#0
d c"=*299;*)"*B(""09*C9)A992*1=),C79*,2;*&11=),C79*1,#0
d V$*;9>,=7)D*$"=*'9)*,*(,0(*1,#D*C=)*$"=*B,2*,70"*'9)*,*)%99*1,#
d c"=*B,2*9,0&7$*B"2:9%)*C9)A992*-B,7,*,2;*?,:,*1,#0
d <=#790*,%9*=09>=7*>"%*,''%9',)&2'*:,7=90

4.1. Constructing a Map


c"=*B,2*B"20)%=B)*,*1,#*,0

val scores = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)

<(&0*B"20)%=B)0*,2*&11=),C79 Map[String, Int] A("09*B"2)92)0*B,2L)*C9*B(,2'9;.*G>*$"=


A,2)*,*1=),C79*1,#D*=09

val scores = collection.mutable.Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)

G>*$"=*A,2)*)"*0),%)*"=)*A&)(*,*C7,2E*1,#D*$"=*(,:9*)"*#&BE*,*1,#*&1#79192),)&"2*,2;
0=##7$*)$#9*#,%,19)9%0R

val scores = new collection.mutable.HashMap[String, Int]

G2*-B,7,D*,*1,#*&0*,*B"779B)&"2*"> pairs.*6*#,&%*&0*0&1#7$*,*'%"=#&2'*">*)A"*:,7=90D*2")
29B900,%&7$*">*)(9*0,19*)$#9D*0=B(*,0 ("Alice", 10).

<(9 -> "#9%,)"%*1,E90*,*#,&%.*<(9*:,7=9*">

"Alice" -> 10

&0

X_
("Alice", 10)

c"=*B"=7;*(,:9*9K=,77$*A977*;9>&29;*)(9*1,#*,0

val scores = Map(("Alice", 10), ("Bob", 3), ("Cindy", 8))

<(9 -> "#9%,)"%*&0*I=0)*,*7&))79*9,0&9%*"2*)(9*9$90*)(,2*)(9*#,%92)(9090.*G)*,70"*0=##"%)0*)(9


&2)=&)&"2*)(,)*,*1,#*;,),*0)%=B)=%9*&0*,*E&2;*">*>=2B)&"2*)(,)*1,#0*E9$0*)"*:,7=9.*<(9
;&>>9%92B9*&0*)(,)*,*>=2B)&"2*B"1#=)90*:,7=90D*,2;*,*1,#*I=0)*7""E0*)(91*=#.

4.2. Accessing Map Values


G2*-B,7,D*)(9*,2,7"'$*C9)A992*>=2B)&"20*,2;*1,#0*&0*#,%)&B=7,%7$*B7"09*C9B,=09*$"=*=09
)(9 () 2"),)&"2*)"*7""E*=#*E9$*:,7=90.

val bobsScore = scores("Bob") // 7&E9 scores.get("Bob") &2*?,:,

G>*)(9*1,#*;"902L)*B"2),&2*,*:,7=9*>"%*)(9*%9K=90)9;*E9$D*,2*9HB9#)&"2*&0*)(%"A2.

<"*B(9BE*A(9)(9%*)(9%9*&0*,*E9$*A&)(*)(9*'&:92*:,7=9D*B,77*)(9 contains 19)(";R

val bobsScore = if (scores.contains("Bob")) scores("Bob") else 0

V9B,=09*)(&0*B,77*B"1C&2,)&"2*&0*0"*B"11"2D*)(9%9*&0*,*0("%)B=)R

val bobsScore = scores.getOrElse("Bob", 0)


// G>*)(9*1,#*B"2),&20*)(9*E9$ "Bob"D*%9)=%2*)(9*:,7=9F*")(9%A&09D*%9)=%2*4.

Y&2,77$D*)(9*B,77 map.get(key) %9)=%20*,2 Option "CI9B)*)(,)*&0*9&)(9% Some(value for key)


"% None.*b9*;&0B=00*)(9 Option B7,00*&2 )(9*nS,))9%2*P,)B(&2'*,2;*!,09*!7,0090o*B(,#)9%.

4.3. Updating Map Values


G2*,*1=),C79*1,#D*$"=*B,2*=#;,)9*,*1,#*:,7=9D*"%*,;;*,*29A*"29D*A&)(*, () )"*)(9*79>)*">
,2 = 0&'2R

scores("Bob") = 10 // e#;,)90*)(9*9H&0)&2'*:,7=9*>"%*)(9*E9$ "Bob"D*,00=1&2' scores &0*1=),C79


scores("Fred") = 7 // 6;;0*,*29A*E9$i:,7=9*#,&%*)" scores M,00=1&2'*&)*&0*1=),C79N

67)9%2,)&:97$D*$"=*B,2*=09*)(9 += "#9%,)&"2*)"*,;;*1=7)&#79*,00"B&,)&"20R

scores += ("Bob" -> 10, "Fred" -> 7)

c"=*%91":9*,*E9$*,2;*&)0*,00"B&,)9;*:,7=9*A&)(*)(9 -= "#9%,)"%R

Z4
scores -= "Alice"

c"=*B,2L)*=#;,)9*,2*&11=),C79*1,#D*C=)*$"=*B,2*;"*0"19)(&2'*)(,)L0*I=0)*,0
=09>=7h"C),&2*,*29A*1,#*)(,)*(,0*)(9*;90&%9;*=#;,)9.

val newScores = scores + ("Bob" -> 10, "Fred" -> 7) // f9A*1,#*A&)(*=#;,)9

<(9 newScores 1,#*B"2),&20*)(9*0,19*,00"B&,)&"20*,0 scoresD*9HB9#)*)(,) "Bob" (,0*C992


=#;,)9;*,2; "Fred" ,;;9;.

G20)9,;*">*0,:&2'*)(9*%90=7)*,0*,*29A*:,7=9D*$"=*B,2*=#;,)9*, varR

var scores = ...


scores = scores + ("Bob" -> 10, "Fred" -> 7)

-&1&7,%7$D*)"*%91":9*,*E9$*>%"1*,2*&11=),C79*1,#D*$"=*=09*)(9 - "#9%,)"%*)"*"C),&2*,
29A*1,#*A&)("=)*)(9*E9$R

scores = scores - "Alice"

c"=*1&'()*)(&2E*)(,)*&)*&0*&29>>&B&92)*)"*E99#*B"20)%=B)&2'*29A*1,#0D*C=)*)(,)*&0*2")*)(9
B,09.*<(9*"7;*,2;*29A*1,#*0(,%9*1"0)*">*)(9&%*0)%=B)=%9.*M<(&0*&0*#"00&C79*C9B,=09*)(9$
,%9*&11=),C79.N

4.4. Iterating Over Maps


<(9*>"77"A&2'*,1,p&2'7$*0&1#79*7""#*&)9%,)90*":9%*,77*E9$J:,7=9*#,&%0*">*,*1,#R

for ((k, v) <- map) process k and v

<(9*1,'&B*(9%9*&0*)(,)*$"=*B,2*=09*#,))9%2*1,)B(&2'*&2*,*-B,7, for 7""#.*M)(9*nS,))9%2


P,)B(&2'*,2;*!,09*!7,0090o*B(,#)9% (,0*,77*)(9*;9),&70.N*<(,)*A,$D*$"=*'9)*)(9*E9$*,2;
:,7=9*">*9,B(*#,&%*&2*)(9*1,#*A&)("=)*,2$*)9;&"=0*19)(";*B,770.

G>*>"%*0"19*%9,0"2*$"=*I=0)*A,2)*)"*:&0&)*)(9*E9$0*"%*:,7=90D*=09*)(9 keySet ,2; values


19)(";0D*,0*$"=*A"=7;*&2*?,:,.*<(9 values 19)(";*%9)=%20*,2 Iterable )(,)*$"=*B,2*=09
&2*, for 7""#.

scores.keySet // 6*09)*0=B(*,0 Set("Bob", "Cindy", "Fred", "Alice")


for (v <- scores.values) println(v) // S%&2)0 10 8 7 10 "%*0"19*#9%1=),)&"2*)(9%9">

<"*%9:9%09*,*1,#D*)(,)*&0D*0A&)B(*E9$0*,2;*:,7=90D*=09

for ((k, v) <- map) yield (v, k)

Z5
4.5. Hash Tables and Trees
b(92*A"%E&2'*A&)(*,*1,#D*$"=*299;*)"*B(""09*,2*&1#79192),)&"2h,*(,0(*),C79*"%*,
C,7,2B9;*)%99.*V$*;9>,=7)D*-B,7,*'&:90*$"=*,*(,0(*),C79.*c"=*1&'()*A,2)*,*)%99*1,#*&>*$"=
;"2L)*(,:9*,*'"";*(,0(*>=2B)&"2*>"%*)(9*E9$0D*"%*&>*$"=*299;*)"*:&0&)*)(9*E9$0*&2*0"%)9;
"%;9%.

V$*;9>,=7)D*-B,7,*'&:90*$"=*,*(,0(*1,#.*<"*'9)*,2*&11=),C79*)%99*1,#D*=09

val scores = collection.immutable.SortedMap("Alice" -> 10,


"Fred" -> 7, "Bob" -> 3, "Cindy" -> 8)

e2>"%)=2,)97$D*)(9%9*&0*M,0*">*-B,7,*3._N*2"*1=),C79*)%99*1,#.*c"=%*C90)*C9)*&0*)"*,;,#)*,
?,:, TreeMapD*,0*;90B%&C9;*&2 )(9*n!"779B)&"20o*B(,#)9%.

Tip: G>*$"=*A,2)*)"*:&0&)*)(9*E9$0*&2*&209%)&"2*"%;9%D*=09*, LinkedHashMap.*Y"%


9H,1#79D

val months = collection.mutable.LinkedHashMap("January" -> 1,


"February" -> 2, "March" -> 3, "April" -> 4, "May" -> 5, ...)

4.6. Interoperating with Java


G>*$"=*'9)*,*?,:,*1,#*>%"1*B,77&2'*,*?,:,*19)(";D*$"=*1,$*A,2)*)"*B"2:9%)*&)*)"*,*-B,7,
1,#*0"*)(,)*$"=*B,2*=09*)(9*#79,0,2)*-B,7,*1,#*6SG.*<(&0*&0*,70"*=09>=7*&>*$"=*A,2)*)"
A"%E*A&)(*,*1=),C79*)%99*1,#D*A(&B(*-B,7,*;"902L)*#%":&;9.

-&1#7$*,;;*,2*&1#"%)*0),)9192)

import collection.JavaConversions.mapAsScalaMap

<(92*)%&''9%*)(9*B"2:9%0&"2*C$*0#9B&>$&2'*)(9*-B,7,*1,#*)$#9R

val scores: collection.mutable.Map[String, Int] =


new java.util.TreeMap[String, Int]

G2*,;;&)&"2D*$"=*B,2*'9)*,*B"2:9%0&"2*>%"1 java.util.Properties )"*, Map[String,


String]R

import collection.JavaConversions.propertiesAsScalaMap
val props: collection.Map[String, String] = System.getProperties()

Z3
!"2:9%097$D*)"*#,00*,*-B,7,*1,#*)"*,*19)(";*)(,)*9H#9B)0*,*?,:,*1,#D*#%":&;9*)(9
"##"0&)9*&1#7&B&)*B"2:9%0&"2.*Y"%*9H,1#79R

import collection.JavaConversions.mapAsJavaMap
import java.awt.font.TextAttribute._ // G1#"%)*E9$0*>"%*1,#*C97"A
val attrs = Map(FAMILY -> "Serif", SIZE -> 12) // 6*-B,7,*1,#
val font = new java.awt.Font(attrs) // WH#9B)0*,*?,:,*1,#

4.7. Tuples
P,#0*,%9*B"779B)&"20*">*E9$i:,7=9*#,&%0.*S,&%0*,%9*)(9*0&1#790)*B,09*"> tuplesD*,''%9',)90
">*:,7=90*">*;&>>9%92)*)$#90.

6*)=#79*:,7=9*&0*>"%19;*C$*92B7"0&2'*&2;&:&;=,7*:,7=90*&2*#,%92)(9090.*Y"%*9H,1#79D

(1, 3.14, "Fred")

&0*,*)=#79*">*)$#9

Tuple3[Int, Double, java.lang.String]

A(&B(*&0*,70"*A%&))92*,0

(Int, Double, java.lang.String)

G>*$"=*(,:9*,*)=#79D*0,$D

val t = (1, 3.14, "Fred")

)(92*$"=*B,2*,BB900*&)0*B"1#"292)0*A&)(*)(9*19)(";0 _1D _2D _3.*Y"%*9H,1#79D

val second = t._2 // 09)0 second )" 3.14

e27&E9*,%%,$*"%*0)%&2'*#"0&)&"20D*)(9*B"1#"292)*#"0&)&"20*">*,*)=#79*0),%)*A&)(*5D*2")*4.

Note: c"=*B,2*A%&)9 t._2 ,0 t _2 MA&)(*,*0#,B9*&20)9,;*">*,*#9%&";ND*C=)*2")


t_2.

e0=,77$D*&)*&0*C9))9%*)"*=09*#,))9%2*1,)B(&2'*)"*'9)*,)*)(9*B"1#"292)0*">*,*)=#79D*>"%
9H,1#79

val (first, second, third) = t // -9)0 first )" 1D second )" 3.14D third )" "Fred"

ZX
<=#790*,%9*=09>=7*>"%*>=2B)&"20*)(,)*%9)=%2*1"%9*)(,2*"29*:,7=9.*Y"%*9H,1#79D*)(9
partition 19)(";*">*)(9 StringOps B7,00*%9)=%20*,*#,&%*">*0)%&2'0D*B"2),&2&2'*)(9
B(,%,B)9%0*)(,)*>=7>&77*,*B"2;&)&"2*,2;*)("09*)(,)*;"2L)R

"New York".partition(_.isUpper) // $&97;0*)(9*#,&% ("NY", "ew ork")

4.8. Zipping
Q29*%9,0"2*>"%*=0&2'*)=#790*&0*)"*C=2;79*)"'9)(9%*:,7=90*0"*)(,)*)(9$*B,2*C9*#%"B9009;
)"'9)(9%.*<(&0*&0*B"11"27$*;"29*A&)(*)(9 zip 19)(";.*Y"%*9H,1#79D*)(9*B";9

val symbols = Array("<", "-", ">");


val counts = Array(2, 10, 2)
val pairs = symbols.zip(counts)

$&97;0*,2*,%%,$*">*#,&%0

Array(("<", 2), ("-", 10), (">", 2))

<(9*#,&%0*B,2*)(92*C9*#%"B9009;*)"'9)(9%R

for ((s, n) <- pairs) Console.print(s * n) // #%&2)0 <<---------->>

Tip: <(9 toMap 19)(";*)=%20*,*B"779B)&"2*">*#,&%0*&2)"*,*1,#.

G>*$"=*(,:9*,*B"779B)&"2*">*E9$0*,2;*,*#,%,7797*B"779B)&"2*">*:,7=90D*)(92*p&#
)(91*=#*,2;*)=%2*)(91*&2)"*,*1,#D*7&E9*)(&0R

keys.zip(values).toMap

4.9. Exercises
5. -9)*=#*,*1,#*">*#%&B90*>"%*,*2=1C9%*">*'&p1"0*)(,)*$"=*B":9).*<(92*#%";=B9*,
09B"2;*1,#*A&)(*)(9*0,19*E9$0*,2;*)(9*#%&B90*,)*,*54*#9%B92)*;&0B"=2).
3. b%&)9*,*#%"'%,1*)(,)*%9,;0*A"%;0*>%"1*,*>&79.*e09*,*1=),C79*1,#*)"*B"=2)*("A
">)92*9,B(*A"%;*,##9,%0.*<"*%9,;*)(9*A"%;0D*0&1#7$*=09*, java.util.ScannerR

val in = new java.util.Scanner(java.io.File("myfile.txt"))


while (in.hasNext()) process in.next()

Q%*7""E*,) )(9*nY&790*,2;*89'=7,%*WH#%900&"20o*B(,#)9% >"%*,*-B,7,90K=9*A,$.

ZZ
6)*)(9*92;D*#%&2)*"=)*,77*A"%;0*,2;*)(9&%*B"=2)0.

X. 89#9,)*)(9*#%9B9;&2'*9H9%B&09*A&)(*,2*&11=),C79*1,#.
Z. 89#9,)*)(9*#%9B9;&2'*9H9%B&09*A&)(*,*0"%)9;*1,#D*0"*)(,)*)(9*A"%;0*,%9*#%&2)9;*&2
0"%)9;*"%;9%.
[. 89#9,)*)(9*#%9B9;&2'*9H9%B&09*A&)(*, java.util.TreeMap )(,)*$"=*,;,#)*)"*)(9
-B,7,*6SG.
\. U9>&29*,*7&2E9;*(,0(*1,#*)(,)*1,#0 "Monday" )" java.util.Calendar.MONDAYD
,2;*0&1&7,%7$*>"%*)(9*")(9%*A99E;,$0.*U91"20)%,)9*)(,)*)(9*979192)0*,%9*:&0&)9;
&2*&209%)&"2*"%;9%.
]. S%&2)*,*),C79*">*,77*?,:,*#%"#9%)&90D*7&E9*)(&0R

java.runtime.name | Java(TM) SE Runtime Environment


sun.boot.library.path | /home/apps/jdk1.6.0_21/jre/lib/i386
java.vm.version | 17.0-b16
java.vm.vendor | Sun Microsystems Inc.
java.vendor.url | http://java.sun.com/
path.separator | :
java.vm.name | Java HotSpot(TM) Server VM

c"=*299;*)"*>&2;*)(9*792')(*">*)(9*7"2'90)*E9$*C9>"%9*$"=*B,2*#%&2)*)(9*),C79.

^. b%&)9*,*>=2B)&"2 minmax(values: Array[Int]) )(,)*%9)=%20*,*#,&%*B"2),&2&2'*)(9


01,7790)*,2;*7,%'90)*:,7=9*&2*)(9*,%%,$.
_. b%&)9*,*>=2B)&"2 lteqgt(values: Array[Int], v: int) )(,)*%9)=%20*,*)%&#79
B"2),&2&2'*B"=2)*">*:,7=90*7900*)(,2 vD*9K=,7*)" vD*,2;*'%9,)9%*)(,2 v.
54. b(,)*(,##920*A(92*$"=*p&#*)"'9)(9%*)A"*0)%&2'0D*0=B(*,0 "Hello".zip("World")g
!"19*=#*A&)(*,*#7,=0&C79*=09*B,09.

Z[
5. Classes (A1)
G2*)(&0*B(,#)9%D*$"=*A&77*79,%2*("A*)"*&1#79192)*B7,0090*&2*-B,7,.*G>*$"=*E2"A*B7,0090*&2
?,:,*"%*!@@D*$"=*A"2L)*>&2;*)(&0*;&>>&B=7)D*,2;*$"=*A&77*92I"$*)(9*1=B(*1"%9*B"2B&09
2"),)&"2*">*-B,7,.

<(9*E9$*#"&2)0*">*)(&0*B(,#)9%*,%9R

d Y&97;0*&2*B7,0090*,=)"1,)&B,77$*B"19*A&)(*'9))9%0*,2;*09))9%0
d c"=*B,2*%9#7,B9*,*>&97;*A&)(*,*B=0)"1*'9))9%i09))9%*A&)("=)*B(,2'&2'*)(9*B7&92)*">
,*B7,00h)(,)*&0*)(9*n=2&>"%1*,BB900*#%&2B&#79o
d e09*)(9 @BeanProperty ,22"),)&"2*)"*'929%,)9*?,:,V9,20 getXxxisetXxx 19)(";0
d W:9%$*B7,00*(,0*,*#%&1,%$*B"20)%=B)"%*)(,)*&0*n&2)9%A":92o*A&)(*)(9*B7,00
;9>&2&)&"2.*G)0*#,%,19)9%0*)=%2*&2)"*>&97;0*">*)(9*B7,00.*<(9*#%&1,%$*B"20)%=B)"%
9H9B=)90*,77*0),)9192)0*&2*)(9*C";$*">*)(9*B7,00.
d 6=H&7&,%$*B"20)%=B)"%0*,%9*"#)&"2,7.*<(9$*,%9*B,779; this.

5.1. Simple Classes and Parameter-Less Methods


G2*&)0*0&1#790)*>"%1D*,*-B,7,*B7,00*7""E0*:9%$*1=B(*7&E9*&)0*9K=&:,792)*&2*?,:,*"%*!@@R

class Counter {
private var value: Int = 0 // c"= must &2&)&,7&p9*)(9*>&97;
def increment() { value += 1 } // P9)(";0*,%9*#=C7&B*C$*;9>,=7)
def current() = value
}

G2*-B,7,D*,*B7,00*&0*2")*;9B7,%9;*,0 public.*6*-B,7,*0"=%B9*>&79*B,2*B"2),&2*1=7)&#79
B7,0090D*,2;*,77*">*)(91*(,:9*#=C7&B*:&0&C&7&)$.

<"*=09*)(&0*B7,00D*$"=*B"20)%=B)*"CI9B)0*,2;*&2:"E9*19)(";0*&2*)(9*=0=,7*A,$R

val myCounter = new Counter // "% new Counter()


myCounter.increment()
println(myCounter.current)

c"=*B,2*B,77*,*#,%,19)9%J7900*19)(";*M0=B(*,0 currentN*A&)("=)*"%*A&)(*#,%92)(9090R

myCounter.current // QE
myCounter.current() // 670"*"E

Z\
b(&B(*>"%1*0("=7;*$"=*=09g*G)*&0*B"20&;9%9;*'"";*0)$79*)"*=09 () >"%*, mutator 19)(";*M,
19)(";*)(,)*B(,2'90*)(9*"CI9B)*0),)9ND*,2;*)"*;%"#*)(9 () >"%*,2 accessor 19)(";*M,
19)(";*)(,)*;"90*2")*B(,2'9*)(9*"CI9B)*0),)9N.

<(,)L0*A(,)*A9*;&;*&2*"=%*9H,1#79R

myCounter.increment()
increment() // e09 () A&)(*1=),)"%
println(myCounter.current
current) // U"2L)*=09 () A&)(*,BB900"%

c"=*B,2*92>"%B9*)(&0*0)$79*C$*;9B7,%&2' current A&)("=) ()R

class Counter {
...
def current = value // f" () &2*;9>&2&)&"2
}

f"A*)(9*B7,00*=09%*1=0)*=09 myCounter.currentD*A&)("=)*#,%92)(9090.

5.2. Properties with Getters and Setters


b(92*A%&)&2'*,*?,:,*B7,00D*A9*;"2L)*7&E9*)"*=09*#=C7&B*>&97;0R

public class Person { // <(&0*&0*?,:,


public int age; // >%"A29;*=#"2*&2*?,:,
}

b&)(*,*#=C7&B*>&97;D*,2$"29*B"=7;*A%&)9*)" fred.ageD*1,E&2'*Y%9;*$"=2'9%*"%*"7;9%.*<(,)L0
A($*A9*#%9>9%*)"*=09*'9))9%*,2;*09))9%*19)(";0R

public class Person {


private int age;
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}

6*'9))9%i09))9%*#,&%*0=B(*,0*)(&0*"29*&0*">)92*B,779;*, property.*b9*0,$*)(,)*)(9*B7,00
Person (,0*,2 age #%"#9%)$.

b($*&0*)(&0*,2$*C9))9%g*V$*&)097>D*&)*&02L).*62$"29*B,2*B,77 fred.setAge(21)D*E99#&2'*(&1
>"%9:9%*)A92)$J"29.

V=)*&>*)(,)*C9B"190*,*#%"C791D*A9*B,2*'=,%;*,',&20)*&)R

public void setAge(int newValue) { if (newValue > age) age = newValue; }


// !,2L)*'9)*$"=2'9%

Z]
t9))9%0*,2;*09))9%0*,%9*C9))9%*)(,2*#=C7&B*>&97;0*C9B,=09*)(9$*79)*$"=*0),%)*A&)(*0&1#79*'9)i
09)*091,2)&B0*,2;*9:"7:9*)(91*,0*299;9;.

Note: ?=0)*C9B,=09*'9))9%0*,2;*09))9%0*,%9*C9))9%*)(,2*#=C7&B*>&97;0*;"902L)*19,2
)(9$*,%9*,7A,$0*'"";.*Q>)92D*&)*&0*#7,&27$*C,;*&>*9:9%$*B7&92)*B,2*'9)*"%*09)*C&)0
,2;*#&9B90*">*,2*"CI9B)L0*0),)9.*G2*)(&0*09B)&"2D*G*0("A*$"=*("A*)"*&1#79192)
#%"#9%)&90*&2*-B,7,.*G)*&0*=#*)"*$"=*)"*B(""09*A&097$*A(92*,*'9)),C79i09)),C79
#%"#9%)$*&0*,2*,##%"#%&,)9*;90&'2.

-B,7,*#%":&;90*'9))9%*,2;*09))9%*19)(";0*>"%*9:9%$*>&97;.*/9%9D*A9*;9>&29*,*#=C7&B*>&97;R

class Person {
var age: Int = 0
}

-B,7,*'929%,)90*,*B7,00*>"%*)(9*?sP*A&)(*, private age >&97;*,2;*'9))9%*,2;*09))9%*19)(";0.


<(909*19)(";0*,%9*#=C7&B*C9B,=09*A9*;&;*2")*;9B7,%9 age ,0 private.*MY"%*,*#%&:,)9*>&97;D
)(9*'9))9%*,2;*09))9%*19)(";0*,%9*#%&:,)9.N

G2*-B,7,D*)(9*'9))9%*,2;*09))9%*19)(";0*,%9*B,779; age ,2; age_=.*Y"%*9H,1#79D

println(fred.age) // !,770*)(9 method fred.age()


fred.age = 21 // !,770 fred.age_=(21)

Note: <"*099*)(909*19)(";0*A&)(*$"=%*"A2*9$90D*B"1#&79*)(9 Person B7,00D*,2;


)(92*7""E*,)*)(9*C$)9*B";90*A&)( javapR

$ scalac Person.scala
$ scala -private Person
Compiled from "Person.scala"
public class Person extends java.lang.Object implements scala.ScalaObject{
private int age;
public int age();
public void age_$eq(int);
public Person();
}

60*$"=*B,2*099D*)(9*B"1#&79%*B%9,)9;*19)(";0 age ,2; age_$eq.*M<(9 = 0$1C"7


&0*)%,207,)9;*)" $eq C9B,=09*)(9*?sP*;"90*2")*,77"A*,2 = 0$1C"7*&2*,*19)(";
2,19.N

Z^
Note: G2*-B,7,D*)(9*'9))9%0*,2;*09))9%0*,%9*2")*2,19; getXxx ,2; setXxxD*C=)
)(9$*>=7>&77*)(9*0,19*#=%#"09. -9B)&"2*[ 0("A0*("A*)"*'929%,)9*?,:,J0)$79
getXxx ,2; setXxx 19)(";0D*0"*)(,)*$"=%*-B,7,*B7,0090*B,2*&2)9%"#9%,)9*A&)(
?,:,*)""70.

6)*,2$*)&19D*$"=*B,2*%9;9>&29*)(9*'9))9%*,2;*09))9%*19)(";0*$"=%097>.*Y"%*9H,1#79D

class Person {
private var privateAge: Int = 0 // P,E9*#%&:,)9*,2;*%92,19

def age = privateAge


def age_=(newValue: Int) {
if (newValue > privateAge) privateAge = newValue; // !,2L)*'9)*$"=2'9%
}
}

<(9*=09%*">*$"=%*B7,00*0)&77*,BB90090 fred.ageD*C=)*2"A*Y%9;*B,2L)*'9)*$"=2'9%R

val fred = new Person


fred.age = 30
fred.age = 21
println(fred.age) // 30

Note: V9%)%,2;*P9$9%D*)(9*&2:92)"%*">*)(9*&2>7=92)&,7*W&>>97*7,2'=,'9D
>"%1=7,)9;*)(9 Uniform Access Principle )(,)*0),)90R*n677*09%:&B90*">>9%9;*C$*,
1";=79*0("=7;*C9*,:,&7,C79*)(%"='(*,*=2&>"%1*2"),)&"2D*A(&B(*;"90*2")*C9)%,$
A(9)(9%*)(9$*,%9*&1#79192)9;*)(%"='(*0)"%,'9*"%*)(%"='(*B"1#=),)&"2.o*G2
-B,7,D*)(9*B,779%*"> fred.age ;"902L)*E2"A*A(9)(9% age &0*&1#79192)9;
)(%"='(*,*>&97;*"%*,*19)(";.*MQ>*B"=%09D*&2*)(9*?sPD*)(9*09%:&B9*&0 always
&1#79192)9;*)(%"='(*,*19)(";D*9&)(9%*0$2)(90&p9;*"%*#%"'%,119%J0=##7&9;.N

Tip: G)*1,$*0"=2;*0B,%$*)(,)*-B,7,*'929%,)90*'9))9%*,2;*09))9%*19)(";0*>"%
9:9%$*>&97;.*V=)*$"=*(,:9*0"19*B"2)%"7*":9%*)(&0*#%"B900.

d G>*)(9*>&97;*&0*#%&:,)9D*)(9*'9))9%*,2;*09))9%*,%9*#%&:,)9
d G>*)(9*>&97;*&0*, valD*"27$*,*'9))9%*&0*'929%,)9;
d G>*$"=*;"2L)*A,2)*,2$*'9))9%*"%*09))9%D*;9B7,%9*)(9*>&97;*,0
private[this] M099 -9B)&"2*ZN

Z_
5.3. Properties with Only Getters
c"=*0"19)&190*A,2)*, read only propertyD*A&)(*,*'9))9%*C=)*2"*09))9%.*G>*)(9*:,7=9*">*)(9
#%"#9%)$*29:9%*B(,2'90*,>)9%*)(9*"CI9B)*(,0*C992*B"20)%=B)9;D*=09*, val >&97;R

class Message {
val timeStamp = new java.util.Date
...
}

-B,7,*1,E90*,*#%&:,)9 final >&97;*,2;*,*'9))9%*19)(";D*C=)*2"*09))9%.

-"19)&190D*("A9:9%D*$"=*A,2)*,*#%"#9%)$*)(,)*,*B7&92)*B,2L)*09)*,)*A&77D*C=)*)(,)*&0*1=),)9;
0"19*")(9%*A,$.*<(9 Counter B7,00*>%"1 -9B)&"2*5 &0*,*'"";*9H,1#79.*!"2B9#)=,77$D*)(9
B"=2)9%*(,0*, current #%"#9%)$*)(,)*&0*=#;,)9;*A(92*)(9 increment 19)(";*&0*B,779;D*C=)
)(9%9*&0*2"*09))9%*>"%*)(9*#%"#9%)$.

c"=*B,2L)*&1#79192)*0=B(*,*#%"#9%)$*A&)(*, valh, val 29:9%*B(,2'90.*G20)9,;D*#%":&;9*,


#%&:,)9*>&97;*,2;*,*#%"#9%)$*'9))9%D*7&E9*)(&0R

class Counter {
private var value: Int = 0
def increment() { value += 1 }
def current = value // f" () &2*;9B7,%,)&"2
}

f")9*)(,)*)(9%9*,%9*2" () &2*)(9*;9>&2&)&"2*">*)(9*'9))9%*19)(";.*<(9%9>"%9D*$"= must B,77


)(9*19)(";*A&)("=)*#,%92)(9090R

val n = myCounter.current // !,77&2' myCounter.current() &0*,*0$2),H*9%%"%

<"*0=11,%&p9D*$"=*(,:9*>"=%*B("&B90*>"%*&1#79192)&2'*#%"#9%)&90R

5. var fooR*-B,7,*0$2)(90&p90*,*'9))9%*,2;*09))9%
3. val fooR*-B,7,*0$2)(90&p90*,*'9))9%
X. c"=*;9>&29*19)(";0 foo ,2; foo_=
Z. c"=*;9>&29*,*19)("; foo

Tip: b(92*$"=*099*,*>&97;*&2*,*-B,7,*B7,00D*%9191C9%*)(,)*&)*&0*2")*)(9*0,19*,0
,*>&97;*&2*?,:,*"%*!@@.*G)*&0*,*#%&:,)9*>&97; together with ,*'9))9%*M>"%*, val
>&97;N*"%*,*'9))9%*,2;*09))9%*M>"%*, var >&97;N.

[4
5.4. Object-Private Fields
G2*-B,7,*M,0*A977*,0*&2*?,:,*"%*!@@ND*,*19)(";*B,2*,BB900*)(9*#%&:,)9*>&97;0*"> all "CI9B)0
">*&)0*B7,00.*Y"%*9H,1#79D

class Person {
private var name
def comesBefore(otherPerson : Person) = name < otherPerson.
otherPerson.name
...
}

<(9*,BB900 otherPerson.name &0*79',7*C9B,=09 otherPerson &0*,70"*, Person "CI9B).

-B,7,*,77"A0*,2*9:92*1"%9*09:9%9*,BB900*%90)%&B)&"2D*A&)(*)(9 private[this] K=,7&>&9%R

private[this] var name // ,BB900 someObject.name &0*2")*,77"A9;

f"AD*)(9*19)(";0*">*)(9 Person B7,00*B,2*"27$*,BB900*)(9 name >&97;*">*)(9*B=%%92)*"CI9B)D


2")*">*")(9%*"CI9B)0*">*)$#9 Person.*<(&0*,BB900*&0*0"19)&190*B,779; object-privateD*,2;*&)
&0*B"11"2*&2*0"19*QQ*7,2'=,'90D*0=B(*,0*-1,77<,7E.

b&)(*,*B7,00J#%&:,)9*>&97;D*-B,7,*'929%,)90*#%&:,)9*'9))9%*,2;*09))9%*19)(";0.*/"A9:9%D*>"%
,2*"CI9B)J#%&:,)9*>&97;D*2"*'9))9%0*,2;*09))9%0*,%9*'929%,)9;*,)*,77.

Note: -B,7,*,77"A0*$"=*)"*'%,2)*,BB900*%&'()0*)"*0#9B&>&B*B7,0090.*<(9
private[ClassName] K=,7&>&9%*0),)90*)(,)*"27$*19)(";0*">*)(9*'&:92*B7,00*B,2
,BB900*)(9*'&:92*>&97;.*/9%9D*)(9 ClassName 1=0)*C9*)(9*2,19*">*)(9*B7,00*)(,)
&0*C9&2'*;9>&29;D*"%*,2*92B7"0&2'*B7,00.*M-99 )(9*nG229%*!7,0090*,2;*6C0)%,B)
<$#90o*B(,#)9% >"%*,*;&0B=00&"2*">*&229%*B7,0090.N

G2*)(&0*B,09D*)(9*&1#79192),)&"2*A&77*'929%,)9*,=H&7,%$*'9))9%*,2;*09))9%
19)(";0*)(,)*,77"A*)(9*92B7"0&2'*B7,00*)"*,BB900*)(9*>&97;.*<(909*19)(";0*,%9
#=C7&B*C9B,=09*)(9*?sP*;"90*2")*(,:9*,*>&29J'%,&29;*,BB900JB"2)%"7*0$0)91D
,2;*)(9$*(,:9*,2*&1#79192),)&"2J;9#92;92)*2,19.

5.5. Bean Properties


60*$"=*0,A*&2*)(9*#%9B9;&2'*09B)&"20D*-B,7,*#%":&;90*'9))9%*,2;*09))9%*19)(";0*>"%*)(9
>&97;0*)(,)*$"=*#%":&;9.*/"A9:9%D*)(9*2,190*">*)(909*19)(";0*,%9*2")*A(,)*?,:,*)""70
9H#9B).*<(9*?,:,V9,20*0#9B&>&B,)&"2*M())#RiiAAA."%,B79.B"1i)9B(29)A"%EiI,:,iI,:,09i
)9B(i&2;9HJI0#J5X^]_[.()17N*;9>&290*,*?,:,*#%"#9%)$*,0*,*#,&%*"> getFooisetFoo 19)(";0

[5
M"%*I=0)*, getFoo 19)(";*>"%*,*%9,;J"27$*#%"#9%)$N.*P,2$*?,:,*)""70*%97$*"2*)(&0*2,1&2'
B"2:92)&"2.

b(92*$"=*,22"),)9*,*-B,7,*>&97;*A&)( @reflect.BeanPropertyD*)(92*)(909*19)(";0*,%9
,=)"1,)&B,77$*'929%,)9;.*Y"%*9H,1#79D

class Person {
@BeanProperty var name : String = _
}

'929%,)90 four 19)(";0R

5. name : String
3. name_=(newValue : String) : Unit
X. getName() : String
Z. setName(newValue : String) : Unit

<,C79*5 0("A0*A(&B(*19)(";0*,%9*'929%,)9;*&2*,77*B,090.

<,C79*[J5R t929%,)9;*P9)(";0*>"%*Y&97;0
Generated
Scala Field When to Use
Methods
val name #=C7&B name <"*&1#79192)*,*#%"#9%)$*)(,)*&0
#=C7&B nameD #=C7&B7$*,BB900&C79*,2;*C,BE9;*C$*,
var name
name_= >&97;.

@BeanProperty val #=C7&B nameD


name getName()
#=C7&B nameD <"*&2)9%"#9%,)9*A&)(*?,:,*C9,20.
@BeanProperty var getName()D
name name_=D
setName(...)
<"*B"2>&29*)(9*>&97;*)"*)(9*19)(";0
private val/var #%&:,)9 nameD ">*,*B7,00D*I=0)*7&E9*&2*?,:,.
name name_= e09 private =27900*$"=*%9,77$*A,2)*,
#=C7&B*#%"#9%)$.

private[this] val/
<"*B"2>&29*)(9*>&97;*)"*19)(";0
var name
f"29 &2:"E9;*"2*)(9*0,19*"CI9B). f")
B"11"27$*=09;.
private[ClassName] G1#79192),)&"2J <"*'%,2)*,BB900*)"*,2*92B7"0&2'*B7,00.
val/var name ;9#92;92) f")*B"11"27$*=09;.

[3
Note: G>*$"=*;9>&29*,*>&97;*,0*,*#%&1,%$*B"20)%=B)"%*#,%,19)9%*M099 -9B)&"2*]ND
,2;*$"=*A,2)*?,:,V9,20*'9))9%0*,2;*09))9%0D*,22"),)9*)(9*B"20)%=B)"%
#,%,19)9%D*7&E9*)(&0R

class Person(@BeanProperty var name : String)

5.6. Auxiliary Constructors


60*&2*?,:,*"%*!@@D*,*-B,7,*B7,00*B,2*(,:9*,0*1,2$*B"20)%=B)"%0*,0*$"=*7&E9.*/"A:9%D*,
-B,7,*B7,00*(,0*"29*B"20)%=B)"%*)(,)*&0*1"%9*&1#"%),2)*)(,2*,77*)(9*")(9%0D*B,779;*)(9
primary constructor.*G2*,;;&)&"2D*,*B7,00*1,$*(,:9*,2$*2=1C9% "> auxiliary constructors.

b9*;&0B=00*,=H&7&,%$*B"20)%=B)"%0*>&%0)*C9B,=09*)(9$*,%9*9,0&9%*)"*=2;9%0),2;.*<(9$*,%9
:9%$*0&1&7,%*)"*B"20)%=B)"%0*&2*?,:,*"%*!@@D*A&)(*I=0)*)A"*;&>>9%92B90R

5. <(9*,=H&7&,%$*B"20)%=B)"%0*,%9*B,779; this.*MG2*?,:,*"%*!@@D*B"20)%=B)"%0*(,:9*)(9
0,19*2,19*,0*)(9*B7,00hA(&B(*&0*2")*0"*B"2:92&92)*&>*$"=*%92,19*)(9*B7,00.N
3. W,B(*,=H&7&,%$*B"20)%=B)"% must 0),%)*A&)(*,*B,77*)"*,*#%9:&"=07$*;9>&29;*,=H&7&,%$
B"20)%=B)"%*"%*)(9*#%&1,%$*B"20)%=B)"%.

/9%9*&0*,*B7,00*A&)(*)A"*,=H&7&,%$*B"20)%=B)"%0.

class Person {
private var name : String = ""
private var age : Int = 0

def this(name : String) { // 62*,=H&7&,%$*B"20)%=B)"%


this() // !,770*#%&1,%$*B"20)%=B)"%
this.name = name
}

def this(name : String, age : Int) { // 62")(9%*,=H&7&,%$*B"20)%=B)"%


this(name) // !,770*#%9:&"=0*,=H&7&,%$*B"20)%=B)"%
this.age = age
}
}

b9*A&77*7""E*,)*)(9*#%&1,%$*B"20)%=B)"%*&2*)(9*29H)*09B)&"2.*Y"%*2"AD*&)*&0*0=>>&B&92)*)"
E2"A*)(,)*,*B7,00*>"%*A(&B(*$"=*;"2L)*;9>&29*,*#%&1,%$*B"20)%=B)"%*(,0*,*#%&1,%$
B"20)%=B)"%*A&)(*2"*,%'=192)0.

c"=*B,2*B"20)%=B)*"CI9B)0*">*)(&0*B7,00*&2*)(%99*A,$0R

[X
val p1 = new Person // S%&1,%$*B"20)%=B)"%
val p2 = new Person("Fred") // Y&%0)*,=H&7&,%$*B"20)%=B)"%
val p3 = new Person("Fred", 42) // -9B"2;*,=H&7&,%$*B"20)%=B)"%

5.7. The Primary Constructor


G2*-B,7,D*9:9%$*B7,00*(,0*,*#%&1,%$*B"20)%=B)"%.*<(9*#%&1,%$*B"20)%=B)"%*&0*2")*;9>&29;
A&)(*, this 19)(";.*G20)9,;D*&)*&0*&2)9%A":92*A&)(*)(9*B7,00*;9>&2&)&"2.

5. <(9*#,%,19)9%0*">*)(9*#%&1,%$*B"20)%=B)"%*,%9*#7,B9; immediately after the class


name.

class Person(val
(val name: String, val age: Int) {
// S,%,19)9%0*">*#%&1,%$*B"20)%=B)"%*&2 (...)
...
}

S,%,19)9%0*">*)(9*#%&1,%$*B"20)%=B)"%*)=%2*&2)"*>&97;0*)(,)*,%9*&2&)&,7&p9;*A&)(*)(9
B"20)%=B)&"2*#,%,19)9%0.*G2*"=%*9H,1#79D name ,2; age C9B"19*>&97;0*">*)(9
Person B7,00.*6*B"20)%=B)"%*B,77*0=B(*,0 new Person("Fred", 42) 09)0*)(9 name
,2; age >&97;0.

/,7>*,*7&29*">*-B,7,*&0*)(9*9K=&:,792)*">*09:92*7&290*">*?,:,R

public class Person { // <(&0*&0*?,:,


private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String name() { return this.name; }
public int age() { return this.age; }
...
}

3. <(9*#%&1,%$*B"20)%=B)"%*9H9B=)90 all statements in the class definition.*Y"%


9H,1#79D*&2*)(9*>"77"A&2'*B7,00

class Person(val name: String, val age: Int) {


println("Just constructed another person")
override def toString = "[name=" + name + ",age=" + age + "]"
}

[Z
)(9 println 0),)9192)*&0*,*#,%)*">*)(9*#%&1,%$*B"20)%=B)"%.*G)*&0*9H9B=)9;
A(929:9%*,2*"CI9B)*&0*B"20)%=B)9;.

<(&0*&0*=09>=7*A(92*$"=*299;*)"*B"2>&'=%9*,*>&97;*;=%&2'*B"20)%=B)&"2.*Y"%
9H,1#79D

public class MyProg {


private Properties props = new Properties
props.load("myprog.properties") // <(&0*7&29*&0*,*#,%)*">*)(9*#%&1,%$*B"20)%=B)"%
...
}

Note: G>*)(9%9*,%9*2"*#,%,19)9%0*,>)9%*)(9*B7,00*2,19D*)(92*)(9*B7,00*(,0*,
#%&1,%$*B"20)%=B)"%*A&)(*2"*#,%,19)9%0.*<(,)*B"20)%=B)"%*0&1#7$*9H9B=)90*,77
0),)9192)0*&2*)(9*C";$*">*)(9*B7,00.

S%&1,%$*B"20)%=B)"%*#,%,19)9%0*B,2*(,:9*,2$*">*)(9*>"%10*&2 <,C79*5.*Y"%*9H,1#79D

class Person(val
val name: String, private var age: Int)

;9B7,%90*,2;*&2&)&,7&p90*>&97;0

val name: String


private var age: Int

!"20)%=B)&"2*#,%,19)9%0*B,2*,70"*C9*%9'=7,%*19)(";*#,%,19)9%0D*A&)("=) val "% var.*/"A


)(909*#,%,19)9%0*,%9*#%"B9009;*;9#92;0*"2*)(9*=0,'9*&20&;9*)(9*B7,00.

d G>*,*#,%,19)9%*A&)("=) val "% var &0*=09;*&20&;9*,)*79,0)*"29*19)(";D*&)*C9B"190*,


>&97;.*Y"%*9H,1#79D

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


def description = name + " is " + age + " years old"
}

;9B7,%90*,2;*&2&)&,7&p90*&11=),C79*>&97;0 name ,2; age )(,)*,%9*"CI9B)J#%&:,)9.

-=B(*,*>&97;*&0*)(9*9K=&:,792)*">*, private[this] val >&97;*M099 -9B)&"2*ZN.

d Q)(9%A&09D*)(9*#,%,19)9%*&0*2")*0,:9;*,0*,*>&97;.*G)L0*I=0)*,*%9'=7,%*#,%,19)9%*)(,)
B,2*C9*,BB9009;*&2*)(9*B";9*">*)(9*#%&1,%$*B"20)%=B)"%.*M-)%&B)7$*0#9,E&2'D*)(&0*&0
,2*&1#79192),)&"2J0#9B&>&B*"#)&1&p,)&"2.N

[[
<,C79*3 0=11,%&p90*)(9*>&97;0*,2;*19)(";0*)(,)*,%9*'929%,)9;*>"%*;&>>9%92)*E&2;0*">
#%&1,%$*B"20)%=B)"%*#,%,19)9%0.

<,C79*[J3R Y&97;0*,2;*P9)(";0*t929%,)9;*Y"%*S%&1,%$*!"20)%=B)"%
S,%,19)9%0
Primary Constructor
Generated Field/Methods
Parameter

name: String
"CI9B)J#%&:,)9*>&97;D*"%*2"*>&97;*&>*2"*19)(";
=090 name
private valivarname: String #%&:,)9*>&97;D*#%&:,)9*'9))9%i09))9%
valivar name: String #%&:,)9*>&97;D*#=C7&B*'9))9%i09))9%
@BeanProperty valivarname: #%&:,)9*>&97;D*#=C7&B*-B,7,*,2;*?,:,V9,20
String '9))9%0i09))9%0

G>*$"=*>&2;*)(9*#%&1,%$*B"20)%=B)"%*2"),)&"2*B"2>=0&2'D*$"=*;"2L)*299;*)"*=09*&).*?=0)
#%":&;9*"29*"%*1"%9*,=H&7&,%$*B"20)%=B)"%0*&2*)(9*=0=,7*A,$D*C=)*%9191C9%*)"*B,77
this() &>*$"=*;"2L)*B(,&2*)"*,2")(9%*,=H&7&,%$*B"20)%=B)"%.

/"A9:9%D*1,2$*#%"'%,119%0*7&E9*)(9*B"2B&09*0$2),H.*P,%)&2*Q;9%0E$*0=''90)0*)"*)(&2E
,C"=)*&)*)(&0*A,$R*G2*-B,7,D*B7,0090*),E9*#,%,19)9%0D*I=0)*7&E9*19)(";0*;".

Note: b(92*$"=*)(&2E*">*#%&1,%$*B"20)%=B)"%*#,%,19)9%0*,0*B7,00*#,%,19)9%0D
#,%,19)9%0*A&)("=) val "% var C9B"19*9,0&9%*)"*=2;9%0),2;.*<(9*0B"#9*">*0=B(
,*#,%,19)9%*&0*)(9*92)&%9*B7,00.*<(9%9>"%9D*$"=*B,2 =09*)(9*#,%,19)9%*&2
19)(";0. G>*$"=*;"D*&)*&0*)(9*B"1#&79%L0*I"C*)"*0,:9*&)*&2*,*>&97;.

Tip: <(9*-B,7,*;90&'29%0*)(&2E*)(,) every keystroke is preciousD*0"*)(9$*79)*$"=


B"1C&29*,*B7,00*,2;*,*#%&1,%$*B"20)%=B)"%.*b(92*%9,;&2'*,*-B,7,*B7,00D*$"=
299;*)"*;&092),2'79*)(9*)A".*Y"%*9H,1#79D*A(92*$"=*099

class Person(val name: String) {


var age: Int = 0
age = 0
override def toString = "[name=" + name + ",age=" + age + "]"
}

),E9*)(9*;9>&2&)&"2*,#,%)*&2)"*,*B7,00*;9>&2&)&"2

[\
class Person(
val name: String) {
var age: Int = 0
override def toString = "[name=" + name + ",age=" + age + "]"
}

,2;*,*B"20)%=B)"%*;9>&2&)&"2

class Person(val name: String) {


var age: Int = 0
override def toString = "[name=" + name + ",age=" + age + "]"
}

Note: <"*1,E9*)(9*#%&1,%$*B"20)%=B)"%*#%&:,)9D*#7,B9*)(9*E9$A"%; private


7&E9*)(&0R

class Person private(val id: Int) { ... }

6*B7,00*=09%*1=0)*)(92*=09*,2*,=H&7&,%$*B"20)%=B)"%*)"*B"20)%=B)*,
Person "CI9B).

5.8. Nested Classes (L1)


G2*-B,7,D*$"=*B,2*290)*I=0)*,C"=)*,2$)(&2'*&20&;9*,2$)(&2'.*c"=*B,2*;9>&29*>=2B)&"20
&20&;9*")(9%*>=2B)&"20D*,2;*B7,0090*&20&;9*")(9%*B7,0090.*/9%9*&0*,*0&1#79*9H,1#79*">*)(9
7,))9%.

import collection.mutable._
class Network {
class Member(val name: String) {
val contacts = new ArrayBuffer[Member]
}

private val members = new ArrayBuffer[Member]

def join(name: String) = {


val m = new Member(name)
members += m
m
}
}

[]
!"20&;9%*)A"*29)A"%E0R

val chatter = new Network


val myFace = new Network

G2*-B,7,D*9,B( instance (,0*&)0*"A2*B7,00 MemberD*I=0)*7&E9*9,B(*&20),2B9*(,0*&)0*"A2


>&97; members.*<(,)*&0D chatter.Member ,2; myFace.Member ,%9 different classes.

Note: <(&0*&0*;&>>9%92)*)(,2*&2*?,:,D*A(9%9*,2*&229%*B7,00*C97"2'0*)"*)(9*"=)9%
B7,00.

<(9*-B,7,*,##%",B(*&0*1"%9*%9'=7,%.*Y"%*9H,1#79D*)"*1,E9*,*29A*&229%*"CI9B)D
$"=*0&1#7$*=09 new A&)(*)(9*)$#9*2,19R new chatter.Member.*G2*?,:,D*$"=
299;*)"*=09*,*0#9B&,7*0$2),HD chatter.new Member().

G2*"=%*29)A"%E*9H,1#79D*$"=*B,2*,;;*,*191C9%*A&)(&2*&)0*"A2*29)A"%ED*C=)*2")*,B%"00
29)A"%E0.

val fred = chatter.join("Fred")


val wilma = chatter.join("Wilma")
fred.contacts += wilma // QE
val barney = myFace.join("Barney") // /,0*)$#9 myFace.Member
fred.contacts += barney
// f"hB,2L)*,;;*, myFace.Member )"*,*C=>>9%*"> chatter.Member 979192)0

Y"%*29)A"%E0*">*#9"#79D*)(&0*C9(,:&"%*#%"C,C7$*1,E90*09209.*G>*$"=*;"2L)*A,2)*&)D*)(9%9
,%9*)A"*0"7=)&"20.

Y&%0)D*$"=*B,2*1":9*)(9 Member )$#9*0"19A(9%9*9709.*6*'"";*#7,B9*A"=7;*C9*)(9 Network


B"1#,2&"2*"CI9B).

object Network {
class Member(val name: String) {
val contacts = new ArrayBuffer[Member]
}
}

class Network {
private val members = new ArrayBuffer[Network.Member]
...
}

[^
67)9%2,)&:97$D*$"=*B,2*=09*, type projection Network#MemberD*A(&B(*19,20*n, Member ">
any Networko.*Y"%*9H,1#79D

class Network {
class Member(val name: String) {
val contacts = new ArrayBuffer[Network#Member]
}
...
}

c"=*A"=7;*;"*)(,)*&>*$"=*A,2)*)(9*>&29J'%,&29;*n&229%*B7,00*#9%*"CI9B)o*>9,)=%9*&2*0"19
#7,B90*">*$"=%*#%"'%,1D*C=)*2")*9:9%$A(9%9.*-99 )(9*n6;:,2B9;*<$#90o*B(,#)9% >"%*1"%9
&2>"%1,)&"2*,C"=)*)$#9*#%"I9B)&"20.

Note: G2*,*290)9;*B7,00D*$"=*B,2*,BB900*)(9 this %9>9%92B9*">*)(9*"=)9%*B7,00*,0


Outer.thisD*7&E9*&2*?,:,.*G>*$"=*7&E9D*$"=*B,2*90),C7&0(*,2*,7&,0*>"%*)(,)
%9>9%92B9*A&)(*)(9*0$2),H

class Outer {
outer =>
class Inner {
override def toString = super.toString + " inside " + outer
}
}

<(9*2,19 outer %9>9%0*)" Outer.this &2*)(9*0B"#9*"> Outer.*c"=*B,2*B(""09


,2$*2,19*>"%*)(&0*:,%&,C79.*<(9*2,19 self &0*B"11"2D*C=)*#9%(,#0*B"2>=0&2'
A(92*=09;*A&)(*290)9;*B7,0090.

<(&0*0$2),H*&0*%97,)9;*)"*)(9*n097>*)$#9o*0$2),H*)(,)*$"=*A&77*099*&2 )(9
n6;:,2B9;*<$#90o*B(,#)9%.

5.9. Exercises
5. G1#%":9*)(9 Counter B7,00*&2 -9B)&"2*5 0"*)(,)*&)*;"902L)*)=%2*29',)&:9*,)
Int.MaxValue.
3. b%&)9*,*B7,00 BankAccount A&)(*19)(";0 deposit ,2; withdrawD*,2;*,*%9,;J"27$
#%"#9%)$ balance.
X. b%&)9*,*B7,00 Time A&)(*%9,;J"27$*#%"#9%)&90 hours ,2; minutes ,2;*,*19)(";
before(other: Time): Boolean )(,)*B(9BE0*A(9)(9%*)(&0*)&19*B"190*C9>"%9*)(9
")(9%.*6 Time "CI9B)*0("=7;*C9*B"20)%=B)9;*,0 new Time(hrs, min)D*A(9%9 hrs &0
&2*1&7&),%$*)&19*MC9)A992*4*,2;*3XN.

[_
Z. 89&1#79192)*)(9 Time B7,00*>%"1*)(9*#%9B9;&2'*9H9%B&09*0"*)(,)*)(9*&2)9%2,7
%9#%9092),)&"2*&0*)(9*2=1C9%*">*1&2=)90*0&2B9*1&;2&'()*MC9)A992*4*,2;*3Zu\4J5N.
Do not B(,2'9*)(9*#=C7&B*&2)9%>,B9.*<(,)*&0D*B7&92)*B";9*0("=7;*C9*=2,>>9B)9;*C$
$"=%*B(,2'9.
[. P,E9*,*B7,00 Student A&)(*%9,;JA%&)9*?,:,V9,20*#%"#9%)&90 name M">*)$#9 StringN
,2; id M">*)$#9 LongN.*b(,)*19)(";0*,%9*'929%,)9;g*Me09 javap )"*B(9BE.N*!,2
$"=*B,77*)(9*?,:,V9,20*'9))9%0*,2;*09))9%0*&2*-B,7,g*-("=7;*$"=g
\. G2*)(9 Person B7,00*"> -9B)&"2*5D*#%":&;9*,*#%&1,%$*B"20)%=B)"%*)(,)*)=%20*29',)&:9
,'90*)"*4.
]. b%&)9*,*B7,00 Person A&)(*,*#%&1,%$*B"20)%=B)"%*)(,)*,BB9#)0*,*0)%&2'*B"2),&2&2'*,
>&%0)*2,19D*,*0#,B9D*,2;*,*7,0)*2,19D*0=B(*,0 new Person("Fred Smith").*-=##7$
%9,;J"27$*#%"#9%)&90 firstName ,2; lastName.*-("=7;*)(9*#%&1,%$*B"20)%=B)"%
#,%,19)9%*C9*, varD*, valD*"%*,*#7,&2*#,%,19)9%g*b($g
^. P,E9*,*B7,00 Car A&)(*%9,;J"27$*#%"#9%)&90*>"%*1,2=>,B)=%9%D*1";97*2,19D*,2;
1";97*$9,%D*,2;*,*%9,;JA%&)9*#%"#9%)$*>"%*)(9*7&B9209*#7,)9.*-=##7$*>"=%
B"20)%=B)"%0.*677*%9K=&%9*)(9*1,2=>,B)=%9%*,2;*1";97*2,19.*Q#)&"2,77$D*1";97
$9,%*,2;*7&B9209*#7,)9*B,2*,70"*C9*0#9B&>&9;*&2*)(9*B"20)%=B)"%.*G>*2")D*)(9*1";97
$9,%*&0*09)*)"*J5*,2;*)(9*7&B9209*#7,)9*)"*)(9*91#)$*0)%&2'.*b(&B(*B"20)%=B)"%*,%9
$"=*B(""0&2'*,0*)(9*#%&1,%$*B"20)%=B)"%g*b($g
_. 89&1#79192)*)(9*B7,00*">*)(9*#%9B9;&2'*9H9%B&09*&2*?,:,D*!OD*"%*!@@*M$"=%
B("&B9N.*/"A*1=B(*0("%)9%*&0*)(9*-B,7,*B7,00g
54. !"20&;9%*)(9*B7,00

class Employee(val name: String, var salary: Double) {


def this() { this("John Q. Public", 0.0) }
}

89A%&)9*&)*)"*=09*9H#7&B&)*>&97;0*,2;*,*;9>,=7)*#%&1,%$*B"20)%=B)"%.*b(&B(*>"%1*;"
$"=*#%9>9%g*b($g

\4
6. Objects (A1)
G2*)(&0*0("%)*B(,#)9%D*$"=*A&77*79,%2*A(92*)"*=09*)(9 object B"20)%=B)*&2*-B,7,.*c"=*=09*&)
A(929:9%*$"=*A,2)*,*B7,00*A&)(*,*0&2'79*&20),2B9D*"%*A(92*$"=*A,2)*)"*>&2;*,*("19*>"%
1&0B977,29"=0*:,7=90*"%*>=2B)&"20.

<(9*E9$*#"&2)0*">*)(&0*B(,#)9%*,%9R

d e09*"CI9B)0*>"%*0&2'79)"20*,2;*=)&7&)$*19)(";0
d 6*B7,00*B,2*(,:9*,*B"1#,2&"2*"CI9B)*A&)(*)(9*0,19*2,19
d QCI9B)0*B,2*9H)92;*B7,0090*"%*)%,&)0
d <(9 apply 19)(";*">*,2*"CI9B)*&0*=0=,77$*=09;*>"%*B"20)%=B)&2'*29A*&20),2B90*">
)(9*B"1#,2&"2*B7,00
d <"*,:"&;*)(9 main 19)(";D*=09*,2*"CI9B)*)(,)*9H)92;0*)(9 App )%,&)
d c"=*B,2*&1#79192)*92=19%,)&"20*C$*9H)92;&2'*)(9 Enumeration "CI9B)

6.1. Singletons
-B,7,*(,0*2"*0),)&B*19)(";0*"%*>&97;0.*G20)9,;D*$"=*=09*)(9 object B"20)%=B).*62*"CI9B)
;9>&290*,*0&2'79*&20),2B9*">*,*B7,00*A&)(*)(9*>9,)=%90*)(,)*$"=*;9>&29.*Y"%*9H,1#79D

object Accounts {
private var lastNumber = 0
def newUniqueNumber() { lastNumber += 1; lastNumber }
}

G>*$"=*299; ,*29A*=2&K=9*,BB"=2)*2=1C9%*&2*$"=%*,##7&B,)&"2D*$"=*B,77
Accounts.newUniqueNumber().

<(9*B"20)%=B)"%*">*,2*"CI9B)*&0*9H9B=)9;*A(92*)(9*"CI9B)*&0*>&%0)*=09;.*G2*"=%*9H,1#79D*)(9
Accounts B"20)%=B)"%*&0*9H9B=)9;*A&)(*)(9*>&%0)*B,77*)" Accounts.newUniqueNumber().*G>*,2
"CI9B)*&0*29:9%*=09;D*&)0*B"20)%=B)"%*&0*2")*9H9B=)9;.

62*"CI9B)*B,2*(,:9*90092)&,77$*,77*)(9*>9,)=%90*">*,*B7,00h&)*B,2*9:92*9H)92;*")(9%*B7,0090
"%*)%,&)0*M099 -9B)&"2*XN.*<(9%9*&0*I=0)*"29*9HB9#)&"2.*c"=*B,22")*#%":&;9*B"20)%=B)"%
#,%,19)9%0.

c"=*=09*,2*"CI9B)*&2*-B,7,*A(929:9%*$"=*A"=7;*(,:9*=09;*,*0&2'79)"2*"CI9B)*&2*?,:,*"%
!@@R

d ,0*,*("19*>"%*=)&7&)$*>=2B)&"20*"%*B"20),2)0
d A(92*,*0&2'79*&11=),C79*&20),2B9*B,2*C9*0(,%9;*9>>&B&92)7$

\5
d A(92*,*0&2'79*&20),2B9*&0*%9K=&%9;*)"*B""%;&2,)9*0"19*09%:&B9*M&.9.D*)(9*-&2'79)"2
;90&'2*#,))9%2N

Note: P,2$*#9"#79*:&9A*)(9*-&2'79)"2*;90&'2*#,))9%2*A&)(*;&0;,&2.*-B,7,
'&:90*$"=*)(9*)""70*>"%*C")(*'"";*,2;*C,;*;90&'2D*,2;*&)*&0*=#*)"*$"=*)"*=09
)(91*A&097$.

6.2. Companion Objects


G2*?,:,*"%*!@@D*$"=*">)92*(,:9*,*B7,00*A&)(*C")(*&20),2B9*19)(";0*,2;*0),)&B*19)(";0.*G2
-B,7,D*$"=*,B(&9:9*)(&0*C$*(,:&2'*,*B7,00*,2;*,*nB"1#,2&"2o*"CI9B)*">*)(9*0,19*2,19.
Y"%*9H,1#79D

class Account {
val id = Account.newUniqueNumber()
private var balance = 0.0
public def deposit(amount: Double) { balance += amount }
...
}

object Account { // <(9*B"1#,2&"2*"CI9B)


private var lastNumber = 0
private def newUniqueNumber() { lastNumber += 1; lastNumber }
}

<(9*B7,00*,2;*B"1#,2&"2*"CI9B)*B,2*,BB900*9,B(*")(9%L0*#%&:,)9*>9,)=%90.*<(9$*1=0)*C9
7"B,)9;*&2*)(9 same source file.

Tip: G2*)(9*8WSTD*$"=*1=0)*;9>&29*)(9*B7,00*,2;*"CI9B)*)"'9)(9%*&2*#,0)9
1";9.*<$#9

:paste

<(92*)$#9*"%*#,0)9*C")(*)(9*B7,00*,2;*"CI9B)*;9>&2&)&"2D*,2;*)$#9 !Qf<8QT@a.

6.3. Objects Extending a Class or Trait


62 object B,2*9H)92;*,*B7,00*,2;i"%*"29*"%*1"%9*)%,&)0.*<(9*%90=7)*&0*,2*"CI9B)*">*,*B7,00
)(,)*9H)92;0*)(9*'&:92*B7,00*,2;i"%*)%,&)0D*,2;*&2*,;;&)&"2*(,0*,77*">*)(9*>9,)=%90*0#9B&>&9;
&2*)(9*"CI9B)*;9>&2&)&"2.

\3
Q29*=09>=7*,##7&B,)&"2*&0*)"*0#9B&>$*;9>,=7)*"CI9B)0*)(,)*B,2*C9*0(,%9;.*Y"%*9H,1#79D
B"20&;9%*,*B7,00*>"%*=2;",C79*,B)&"20*&2*,*#%"'%,1.

abstract class UndoableAction(val description: String) {


def undo(): Unit
def redo(): Unit
}

6*=09>=7*;9>,=7)*&0*)(9*n;"*2")(&2'o*,B)&"2.*Q>*B"=%09D*A9*"27$*299;*"29*">*)(91.

object DoNothingAction extends UndoableAction("Do nothing") {


override def undo() {}
override def redo() {}
}

<(9 DoNothingAction "CI9B)*B,2*C9*0(,%9;*,1"2'*,77*#7,B90*)(,)*299;*)(&0*;9>,=7).

val actions = Map("open" -> DoNothingAction


DoNothingAction, "save" -> DoNothingAction
DoNothingAction, ...)
// Q#92*,2;*0,:9*2")*$9)*&1#79192)9;

6.4. The apply Method


G)*&0*B"11"2*)"*(,:9*"CI9B)0*A&)(*,2 apply 19)(";.*<(9 apply 19)(";*&0*B,779;*>"%
9H#%900&"20*">*)(9*>"%1

Object(arg1, ..., argN)

<$#&B,77$D*0=B(*,2 apply 19)(";*%9)=%20*,2*"CI9B)*">*)(9*B"1#,2&"2*B7,00.

Y"%*9H,1#79D*)(9 Array "CI9B)*;9>&290 apply 19)(";0*)(,)*,77"A*,%%,$*B%9,)&"2*A&)(


9H#%900&"20*0=B(*,0

Array("Mary", "had", "a", "little", "lamb")

b($*;"902L)*"29*I=0)*=09*,*B"20)%=B)"%g*f")*(,:&2'*)(9 new E9$A"%;*&0*(,2;$*>"%*290)9;


9H#%900&"20D*0=B(*,0

Array(Array(1, 7), Array(2, 9))

Caution: G)*&0*9,0$*)"*B"2>=09 Array(100) ,2; new Array(100).*<(9*>&%0)


9H#%900&"2*B,770 apply(100)D*$&97;&2'*,2 Array[Int] A&)(*,*0&2'79*979192)D*)(9
&2)9'9%*544.*<(9*09B"2;*9H#%900&"2*&2:"E90*)(9*B"20)%=B)"% this(100).*<(9
%90=7)*&0*,2 Array[Nothing] A&)(*544 null 979192)0.

\X
6.5. Application Objects
W,B(*-B,7,*#%"'%,1*1=0)*0),%)*A&)(*,2*"CI9B)L0 main 19)(";*">*)$#9 Array[String] =>
UnitR

object Hello {
def main(args: Array[String]) {
println("Hello, World!")
}
}

G20)9,;*">*#%":&;&2'*, main 19)(";*>"%*$"=%*,##7&B,)&"2D*$"=*B,2*9H)92;*)(9 App )%,&)*,2;


#7,B9*)(9*#%"'%,1*B";9*&2)"*)(9*B"20)%=B)"%*C";$R

object Hello extends App {


println("Hello, World!")
}

G>*$"=*299;*)(9*B"11,2;J7&29*,%'=192)0D*$"=*B,2*'9)*)(91*>%"1*)(9 args #%"#9%)$R

object Hello extends App {


if (args.size > 0)
println("Hello, " + args(0))
else
println("Hello, World!")
}

G>*$"=*&2:"E9*)(9*,##7&B,)&"2*A&)(*)(9 scala.time "#)&"2*09)D*)(92*)(9*97,#09;*)&19*&0


;&0#7,$9;*A(92*)(9*#%"'%,1*9H&)0.

$ scala -Dscala.time Hello Fred


Hello, Fred
[total 4ms]

677*)(&0*&2:"7:90*,*C&)*">*1,'&B.*<(9 App )%,&)*9H)92;0*,2")(9%*)%,&)D DelayedInitD*)(,)*'9)0


0#9B&,7*(,2;7&2'*C$*)(9*B"1#&79%.*677*&2&)&,7&p,)&"2*B";9*">*,*B7,00*A&)(*)(,)*)%,&)*&0*1":9;
&2)"*, delayedInit 19)(";.*<(9 main ">*)(9 App )%,&)*19)(";*B,#)=%90*)(9*B"11,2;J7&29
,%'=192)0D*B,770*)(9 delayedInit19)(";D*,2;*"#)&"2,77$*#%&2)0*)(9*97,#09;*)&19.

Note: Q7;9%*:9%0&"20*">*-B,7,*(,;*,2 Application )%,&)*>"%*)(9*0,19*#=%#"09.


<(,)*)%,&)*B,%%&9;*"=)*)(9*#%"'%,1L0*,B)&"2*&2*)(9*0),)&B*&2&)&,7&p9%D*A(&B(*B,=090
0=C)79*&00=90*A&)(*0"19*:&%)=,7*1,B(&290.*e09*)(9 App )%,&)*&20)9,;.

\Z
6.6. Enumerations
e27&E9*?,:,*"%*!@@D*-B,7,*;"90*2")*(,:9*92=19%,)9;*)$#90.*/"A9:9%D*)(9*0),2;,%;*7&C%,%$
#%":&;90*,2 Enumeration (97#9%*B7,00*)(,)*$"=*B,2*=09*)"*#%";=B9*92=19%,)&"20.

U9>&29*,2*"CI9B)*)(,)*9H)92;0*)(9 Enumeration B7,00*,2;*&2&)&,7&p9*9,B(*:,7=9*&2*$"=%


92=19%,)&"2*A&)(*,*B,77*)"*)(9 Value 19)(";.*Y"%*9H,1#79D

object TrafficLightColor extends Enumeration {


val Red, Yellow, Green = Value
}

/9%9*A9*;9>&29*)(%99*>&97;0 RedD YellowD*,2; GreenD*,2;*&2&)&,7&p9*9,B(*">*)(91*A&)(*,*B,77


Value.*<(&0*&0*,*0("%)B=)*>"%

val Red = Value


val Yellow = Value
val Green = Value

W,B(*B,77*)"*)(9 Value 19)(";*%9)=%20*,*29A*&20),2B9*">*,2*&229%*B7,00D*,70"*B,779; Value.

67)9%2,)&:97$D*$"=*B,2*#,00*GU0D*2,190D*"%*C")(*)"*)(9 Value 19)(";R

val Red = Value(0, "Stop")


val Yellow = Value(10) // f,19 "Yellow"
val Green = Value("Go") // GU*55

G>*2")*0#9B&>&9;D*)(9*GU*&0*"29*1"%9*)(,2*)(9*#%9:&"=07$*,00&'29;*"29D*0),%)&2'*A&)(*p9%".
<(9*;9>,=7)*2,19*&0*)(9*>&97;*2,19.

c"=*B,2*2"A*%9>9%*)"*)(9*92=19%,)&"2*:,7=90*,0 TrafficLightColor.RedD*,2;*0"*"2.*G>*)(,)
'9)0*)""*)9;&"=0D*=09*,*0),)9192)

import TrafficLightColor._

M-99 )(9*nS,BE,'90*,2;*G1#"%)0o*B(,#)9% >"%*1"%9*&2>"%1,)&"2*,C"=)*&1#"%)&2'*191C9%0


">*,*B7,00*"%*"CI9B).N

89191C9%*)(,)*)(9*)$#9*">*)(9*92=19%,)&"2*&0 TrafficLightColor.Value ,2; not


TrafficLightColorh)(,)L0*)(9*)$#9*">*)(9*"CI9B)*("7;&2'*)(9*:,7=90.*-"19*#9"#79
%9B"1192;*)(,)*$"=*,;;*,*)$#9*,7&,0

object TrafficLightColor extends Enumeration {


type TrafficLightColor = Value

\[
val Red, Yellow, Green = Value
}

f"A*)(9*)$#9*">*)(9*92=19%,)&"2*&0 TrafficLightColor.TrafficLightColorD*A(&B(*&0
"27$*,2*&1#%":9192)*&>*$"=*=09*,2 import 0),)9192).*Y"%*9H,1#79D

import TrafficLightColor._
def doWhat(color: TrafficLightColor) =
if (color == Red) "stop"
else if (color == Yellow) "hurry up"
else if (color == Green) "go"

<(9*GU*">*,2*92=19%,)&"2*:,7=9*&0*%9)=%29;*C$*)(9 id 19)(";D*,2;*)(9*2,19*C$*)(9
toString 19)(";.

<(9*B,77 TrafficLightColor.values $&97;0*,*09)*">*,77*:,7=90.

for (c <- TrafficLightColor.values) println(c.id + ": " + c)

Y&2,77$D*$"=*B,2*7""E*=#*,2*92=19%,)&"2*:,7=9*C$*GU*"%*2,19.*V")(*">*)(9*>"77"A&2'

TrafficLightColor(0) // !,770 Enumeration.apply


TrafficLightColor.withName("Red")

$&97;*)(9*"CI9B) TrafficLightColor.Red.

6.7. Exercises
5. b%&)9*,2*"CI9B) Conversions A&)(*19)(";0 inchesToCentimeterD gallonsToLiterD
,2; milesToKilometer.
3. <(9*#%9B9;&2'*#%"C791*A,02L)*:9%$*"CI9B)J"%&92)9;.*S%":&;9*,*'929%,7*0=#9%B7,00
UnitConversion ,2;*;9>&29*"CI9B)0 InchesToCentimeterD GallonsToLiterD*,2;
MilesToKilometer )(,)*9H)92;*&).
X. U9>&29*,2 Origin "CI9B)*)(,)*9H)92;0 java.awt.Point.*b($*&0*)(&0*2")*,B)=,77$*,
'"";*&;9,g*M/,:9*,*B7"09*7""E*,)*)(9*19)(";0*">*)(9 Point B7,00.N
Z. U9>&29*, Point B7,00*A&)(*,*B"1#,2&"2*"CI9B)*0"*)(,)*$"=*B,2*B"20)%=B) Point
&20),2B90*,0 Point(3, 4)D*A&)("=)*=0&2' new.
[. b%&)9*,*-B,7,*,##7&B,)&"2D*=0&2'*)(9 App )%,&)D*)(,)*#%&2)0*)(9*B"11,2;J7&29
,%'=192)0*&2*%9:9%09*"%;9%D*09#,%,)9;*C$*0#,B90.*Y"%*9H,1#79D scala Reverse
Hello World 0("=7;*#%&2) World Hello.
\. b%&)9*,2*92=19%,)&"2*;90B%&C&2'*)(9*>"=%*#7,$&2'*B,%;*0=&)0*0"*)(,)*)(9 toString
19)(";*%9)=%20*vD*wD*xD*y.
]. G1#79192)*,*>=2B)&"2*)(,)*B(9BE0*A(9)(9%*,*B,%;*0=&)*:,7=9*>%"1*)(9*#%9B9;&2'
9H9%B&09*&0*%9;.

\\
^. b%&)9*,2*92=19%,)&"2*;90B%&C&2'*)(9*9&'()*B"%29%0*">*)(9*8tV*B"7"%*B=C9.*60
GU0D*=09*)(9*B"7"%*:,7=90*M>"%*9H,1#79D 0xff0000 >"% RedN.

\]
7. Packages and Imports (A1)
G2*)(&0*B(,#)9%D*$"=*A&77*79,%2*("A*#,BE,'90*,2;*&1#"%)*0),)9192)0*A"%E*&2*-B,7,.*V")(
#,BE,'90*,2;*&1#"%)0*,%9*1"%9*%9'=7,%*)(,2*&2*?,:,D*,2;*)(9$*,%9*,70"*,*C&)*1"%9*>79H&C79.

<(9*E9$*#"&2)0*">*)(&0*B(,#)9%*,%9R

d S,BE,'90*290)*I=0)*7&E9*&229%*B7,0090
d S,BE,'9*#,)(0*,%9 not ,C0"7=)9
d 6*B(,&2 x.y.z &2*,*#,BE,'9*B7,=09*79,:90*)(9*&2)9%19;&,)9*#,BE,'90 x ,2; x.y
&2:&0&C79
d S,BE,'9*0),)9192)0*A&)("=)*C%,B90*,)*)(9*)"#*">*)(9*>&79*9H)92;*)"*)(9*92)&%9*>&79
d 6*#,BE,'9*"CI9B)*B,2*("7;*>=2B)&"20*,2;*:,%&,C790
d G1#"%)*0),)9192)0*B,2*&1#"%)*#,BE,'90D*B7,0090D*,2;*"CI9B)0
d G1#"%)*0),)9192)0*B,2*C9*,2$A(9%9
d G1#"%)*0),)9192)0*B,2*%92,19*,2;*(&;9*191C9%0
d java.langD scalaD*,2; Predef ,%9*,7A,$0*&1#"%)9;

7.1. Packages
S,BE,'90*&2*-B,7,*>=7>&77*)(9*0,19*#=%#"09*,0*#,BE,'90*&2*?,:,*"%*2,190#,B90*&2*!@@D*)"
1,2,'9*2,190*&2*,*7,%'9*#%"'%,1.*Y"%*9H,1#79D*)(9*2,19 Map B,2*"BB=%*&2*)(9*#,BE,'90
scala.collection.immutable ,2; scala.collection.mutable A&)("=)*B"2>7&B).*<"*,BB900
9&)(9%*2,19D*$"=*B,2*=09*)(9*>=77$*K=,7&>&9; scala.collection.immutable.Map "%
scala.collection.mutable.Map.*67)9%2,)&:97$D*=09*,2 import 0),)9192)*)"*#%":&;9*,
0("%)9%*,7&,0h099 -9B)&"2*].

<"*,;;*&)910*)"*,*#,BE,'9D*$"=*B,2*&2B7=;9*)(91*&2*#,BE,'9*0),)9192)0*0=B(*,0

package com {
package horstmann {
package impatient {
class Person
...
}
}
}

<(92*)(9*B7,00*2,19 Person B,2*C9*,BB9009;*,2$A(9%9*,0


com.horstmann.impatient.Person.

\^
e27&E9*)(9*;9>&2&)&"2*">*,2*"CI9B)*"%*,*B7,00D*,*#,BE,'9*B,2*C9*;9>&29;*":9%*1=7)&#79*>&790.
<(9*#%9B9;&2'*B";9*1&'()*C9*&2*,*>&79 Person.scalaD*,2;*,*>&79 Student.scala 1&'()
B"2),&2

package com {
package horstmann {
package impatient {
class Student extends Person
...
}
}
}

Note: <(9%9*&0*2"*92>"%B9;*%97,)&"20(&#*C9)A992*)(9*;&%9B)"%$*">*)(9*0"=%B9
>&79*,2;*)(9*#,BE,'9.*c"=*;"2L)*(,:9*)"*#=) Person.scala ,2; Student.scala
&2)"*, com/horstmann/impatient ;&%9B)"%$.

!"2:9%097$D*$"=*B,2*B"2)%&C=)9*)"*1"%9*)(,2*"29*#,BE,'9*&2*,*0&2'79*>&79.*<(9*>&79
Person.scala B,2*B"2),&2

package com {
package horstmann {
package impatient {
class Person
...
}
}
}

package org {
package bigjava {
class Student extends com.horstmann.impatient.Person
}
}

7.2. Scope Rules


G2*-B,7,D*)(9*0B"#9*%=790*>"%*#,BE,'90*,%9*1"%9*B"20&0)92)*)(,2*)("09*&2*?,:,.*-B,7,
#,BE,'90*290)*I=0)*7&E9*,77*")(9%*0B"#90.*c"=*B,2*,BB900*2,190*>%"1*)(9*92B7"0&2'*0B"#9.
Y"%*9H,1#79D

\_
package com {
package horstmann {
object Utils {
def percentOf(value: Double, rate: Double) = value * rate / 100
...
}

package impatient {
class Employee {
...
def giveRaise(rate: scala.Double) {
salary += Utils.percentOf
Utils.percentOf(salary, rate)
}
}
}
}
}

f")9*)(9 Utils.percentOf K=,7&>&9%.*<(9 Utils B7,00*A,0*;9>&29;*&2*)(9 parent #,BE,'9.


W:9%$)(&2'*&2*)(9*#,%92)*#,BE,'9*&0*&2*0B"#9D*,2;*&)*&0*2")*29B900,%$*)" =09
com.horstmann.Utils.percentOf.*Mc"=*B"=7;D*)("='(D*&>*$"=*A,2)9;h,>)9%*,77D com &0*,70"
&2*0B"#9.N

<(9%9*&0*,*>7$*&2*)(9*"&2)192)D*("A9:9%.*!"20&;9%

package com {
package horstmann {
package impatient {
class Manager {
val subordinates = new scala.collection.mutable.ArrayBuffer[Employee]
...
}
}
}
}

62;*2"A*0=##"09*0"19"29*&2)%";=B90*)(9*>"77"A&2'*#,BE,'9D*#9%(,#0*&2*,*;&>>9%92)*>&79.

package com {
package horstmann {
package scala {
...
}
}

]4
f"A*)(9 Manager B7,00*2"*7"2'9%*B"1#&790.*G)*7""E0*>"%*, collection 191C9%*&20&;9*)(9
impatient.scala #,BE,'9*,2;*;"902L)*>&2;*&).*<(9*&2)92)*&2*)(9 Manager B7,00*A,0*)(9*)"#J
79:97 scala #,BE,'9D*2")*A(,)9:9% scala 0=C#,BE,'9*(,##929;*)"*C9*&2*0"19*,BB900&C79
0B"#9D*C=)*)(,)L0*2")*("A*#,BE,'9*0B"#90*A"%E*&2*-B,7,.

G2*?,:,D*)(&0*#%"C791*B,2L)*"BB=%*C9B,=09*#,BE,'9*2,190*,%9*,7A,$0 absoluteD*0),%)&2'*,)
)(9*%"")*">*)(9*#,BE,'9*(&9%,%B($.*V=)*&2*-B,7,D*#,BE,'9*2,190*,%9*%97,)&:9D*I=0)*7&E9*&229%
B7,00*2,190.*b&)(*&229%*B7,0090D*"29*;"902L)*=0=,77$*%=2*&2)"*#%"C7910*C9B,=09*,77*)(9
B";9*&0*"29*>&79D*=2;9%*B"2)%"7*">*A("9:9%*&0*&2*B(,%'9*">*)(,)*>&79.*V=)*#,BE,'90*,%9*"#92J
92;9;.*62$"29*B,2*B"2)%&C=)9*)"*,*#,BE,'9*,)*,2$*)&19.

Q29*0"7=)&"2*&0*)"*=09*,C0"7=)9*#,BE,'9*2,190D*0),%)&2'*A&)( _root_D*>"%*9H,1#79

val subordinates = new _root_.scala.collection.mutable.ArrayBuffer


_root_.scala.collection.mutable.ArrayBuffer[Employee]

62")(9%*,##%",B(*&0*)"*=09*nB(,&29;o*#,BE,'9*B7,=090h099*)(9*29H)*09B)&"2.

7.3. Chained Package Clauses


6*#,BE,'9*B7,=09*B,2*B"2),&2*,*nB(,&2o*"%*#,)(*09'192)D*>"%*9H,1#79

package com.horstmann.impatient {
// P91C9%0*"> com ,2; com.horstmann ,%9 not :&0&C79*(9%9
package people {
class Person
...
}
}

-=B(*,*B7,=09*7&1&)0*)(9*:&0&C79*191C9%0.*f"A*, com.horstmann.scala #,BE,'9*A"=7;*2"


7"2'9%*C9*,BB900&C79*,0 scala.

7.4. Top-of-File Notation


G20)9,;*">*)(9*290)9;*2"),)&"2*)(,)*A9*(,:9*=09;*=#*)"*2"AD*$"=*B,2*(,:9 package B7,=090
,)*)(9*)"#*">*)(9*>&79D*A&)("=)*C%,B90.*Y"%*9H,1#79D

package com.horstmann.impatient
package people

class Person
...

<(&0*&0*9K=&:,792)*)"

]5
package com.horstmann.impatient {
package people {
class Person
...
// e2)&7*)(9*92;*">*)(9*>&79
}
}

<(&0*&0*)(9*#%9>9%%9;*2"),)&"2*&>*,77*)(9*B";9*&2*)(9*>&79*C97"2'0*)"*)(9*0,19*#,BE,'9
MA(&B(*&0*)(9*=0=,7*B,09N.

f")9*)(,)*&2*)(9*9H,1#79*,C":9D*9:9%$)(&2'*&2*)(9*>&79*C97"2'0*)"*)(9*#,BE,'9
com.horstmann.impatient.peopleD*C=)*)(9*#,BE,'9 com.horstmann.impatient (,0*,70"
C992*"#929;*=#D*0"*)(,)*"29*B,2*%9>9%*)"*&)0*B"2)92)0.

7.5. Package Objects


6*#,BE,'9*B,2*B"2),&2*B7,0090D*"CI9B)0D*,2;*)%,&)0D*C=)*2")*)(9*;9>&2&)&"20*">*>=2B)&"20*"%
:,%&,C790.*<(,)L0*,2*=2>"%)=2,)9*7&1&),)&"2*">*)(9*?,:,*:&%)=,7*1,B(&29.*G)*A"=7;*1,E9
1"%9*09209*)"*,;;*=)&7&)$*>=2B)&"20*"%*B"20),2)0*)"*,*#,BE,'9*)(,2*)"*0"19 Utils "CI9B).
S,BE,'9*"CI9B)0*,;;%900*)(&0*7&1&),)&"2.

W:9%$*#,BE,'9*B,2*(,:9*"29*#,BE,'9*"CI9B).*c"=*;9>&29*&)*&2*)(9 parent #,BE,'9D*,2;*&)


(,0*)(9*0,19*2,19*,0*)(9*B(&7;*#,BE,'9.*Y"%*9H,1#79D

package com.horstmann.impatient

package object people {


val defaultName = "John Q. Public"
}

package people {
class Person {
var name = defaultName // 6*B"20),2)*>%"1*)(9*#,BE,'9
}
...
}

f")9*)(,)*)(9 defaultName :,7=9*;&;2L)*299;*)"*C9*K=,7&>&9;*C9B,=09*&)*A,0*&2*)(9*0,19


#,BE,'9.*W709A(9%9D*&)*&0*,BB900&C79*,0 com.horstmann.impatient.people.defaultName.

V9(&2;*)(9*0B9290D*)(9*#,BE,'9*"CI9B)*'9)0*B"1#&79;*&2)"*,*?sP*B7,00*A&)(*0),)&B*19)(";0
,2;*>&97;0D*B,779; package.class &20&;9*)(9*#,BE,'9.*G2*"=%*9H,1#79D*)(,)*A"=7;*C9*,*B7,00

]3
com.horstmann.impatient.people.package A&)(*,*0),)&B*>&97; defaultName.*MG2*)(9*?sPD
$"=*B,2*=09 package ,0*,*B7,00*2,19.N

G)*&0*,*'"";*&;9,*)"*=09*)(9*0,19*2,1&2'*0B(919*>"%*0"=%B9*>&790.*S=)*)(9*#,BE,'9*"CI9B)
&2)"*,*>&79 com/horstmann/impatient/people/package.scala.*<(,)*A,$D*,2$"29*A("
A,2)0*)"*,;;*>=2B)&"20*"%*:,%&,C790*)"*,*#,BE,'9*B,2*>&2;*)(9*#,BE,'9*"CI9B)*9,0&7$.

7.6. Package Visibility


G2*?,:,D*,*B7,00*191C9%*)(,)*&02L)*;9B7,%9;*,0 publicD privateD*"% protected &0*:&0&C79*&2
)(9*#,BE,'9*B"2),&2&2'*)(9*B7,00.*G2*-B,7,D*$"=*B,2*,B(&9:9*)(9*0,19*9>>9B)*A&)(
K=,7&>&9%0.*<(9*>"77"A&2'*19)(";*&0*:&0&C79*&2*&)0*"A2*#,BE,'9.

package com.horstmann.impatient.people

class Person {
private[people] def giveRaise(rate: Double)
...
}

c"=*B,2*9H)92;*)(9*:&0&C&7&)$*)"*,2*92B7"0&2'*#,BE,'9R

private[impatient] def giveRaise(rate: Double)

7.7. Imports
G1#"%)0*79)*$"=*=09*0("%)*2,190*&20)9,;*">*7"2'*"290.*b&)(*)(9*B7,=09

import scala.collection.mutable.HashMap

$"=*B,2*A%&)9 HashMap &2*$"=%*B";9*&20)9,;*"> scala.collection.mutable.HashMap.

<(,)*&0*)(9*0"79*#=%#"09*">*&1#"%)0.*G>*$"=*;"2L)*1&2;*7"2'*2,190D*$"=*29:9%*299;*)(91.

c"=*B,2*&1#"%)*,77*191C9%0*">*,*#,BE,'9*,0

import scala.collection.mutable._

<(&0*&0*)(9*0,19*,0*)(9 * A&7;B,%;*&2*?,:,.*MG2*-B,7,D * &0*,*:,7&;*2,19*>"%*,2*&;92)&>&9%.


c"=*B"=7;*;9>&29*,*#,BE,'9 com.horstmann.*.peopleD*C=)*#79,09*;"2L).N

c"=*B,2*,70"*&1#"%)*,77*191C9%0*">*,*B7,00*"%*"CI9B).

]X
import java.awt.Color._
val c1 = RED // Color.RED
val c2 = decode("#ff0000") // Color.decode

<(&0*&0*7&E9 import static &2*?,:,.*?,:,*#%"'%,119%0*0991*)"*7&:9*&2*>9,%*">*)(&0*:,%&,2)D


C=)*&2*-B,7,*&)*&0*B"11"27$*=09;.

b(92*$"=*&1#"%)*,*#,BE,'9D*$"=*B,2*,BB900*&)0*0=C#,BE,'90*A&)(*0("%)9%*2,190.*Y"%
9H,1#79D

import java.awt._

def handler(evt: event.ActionEvent) { // java.awt.event.ActionEvent


...
}

<(9 event #,BE,'9*&0*,*191C9%*"> java.awtD*,2;*)(9*&1#"%)*C%&2'0*&)*&2)"*0B"#9.

7.8. Imports Can Be Anywhere


G2*-B,7,D*,2*&1#"%)*0),)9192)*B,2*C9*,2$A(9%9D*2")*I=0)*&2*)(9*)"#*">*,*>&79.*<(9*0B"#9*">
)(9*&1#"%)*0),)9192)*9H)92;0*=2)&7*)(9*92;*">*)(9*92B7"0&2'*C7"BE.*Y"%*9H,1#79D

class Manager {
import scala.collection.mutable._
val subordinates = new ArrayBuffer[Employee]
...
}

<(&0*&0*,*:9%$*=09>=7*>9,)=%9D*#,%)&B=7,%7$*A&)(*A&7;B,%;*&1#"%)0.*G)*&0*,7A,$0*,*C&)
A"%%&0"19*)"*&1#"%)*7")0*">*2,190*>%"1*;&>>9%92)*0"=%B90.*G2*>,B)D*0"19*?,:,
#%"'%,119%0*;&07&E9*A&7;B,%;*&1#"%)0*0"*1=B(*)(,)*)(9$*29:9%*=09*)(91D*C=)*79)*)(9*GUW
'929%,)9*7"2'*7&0)0*">*&1#"%)9;*B7,0090.

V$*#=))&2'*)(9*&1#"%)0*A(9%9*)(9$*,%9*299;9;D*$"=*B,2*'%9,)7$*%9;=B9*)(9*#")92)&,7*>"%
B"2>7&B)0.

7.9. Renaming and Hiding Members


G>*$"=*A,2)*)"*&1#"%)*,*>9A*191C9%0*>%"1*,*#,BE,'9D*=09*, selectorD*7&E9*)(&0R

import java.awt.{Color, Graphics}

<(9*0979B)"%*0$2),H*79)0*$"=*%92,19*191C9%0.

]Z
import java.util.{HashMap => JavaHashMap}
import scala.collection.mutable._

f"A JavaHashMap &0*, java.util.HashMap ,2;*#7,&2 HashMap &0*,


scala.collection.mutable.HashMap.

<(9*0979B)"% HashMap => _ (&;90*,*191C9%*&20)9,;*">*%92,1&2'*&).*<(&0*&0*"27$*=09>=7*&>


$"=*&1#"%)*,77*")(9%0R

import java.util.{HashMap => _, _}


import scala.collection.mutable._

f"A HashMap =2,1C&'="=07$*%9>9%0*)" scala.collection.mutable.HashMap 0&2B9


java.util.HashMap &0*(&;;92.

7.10. Implicit Imports


W:9%$*-B,7,*#%"'%,1*&1#7&B&)7$*0),%)0*A&)(

import java.lang._
import scala._
import Predef._

60*A&)(*?,:,*#%"'%,10D java.lang &0*,7A,$0*&1#"%)9;.*f9H)D*)(9 scala #,BE,'9*&0


&1#"%)9;D*C=)*&2*,*0#9B&,7*A,$.*e27&E9*,77*")(9%*&1#"%)0D*)(&0*"29*&0*,77"A9;*)"*":9%%&;9
)(9*#%9B9;&2'*&1#"%). Y"%*9H,1#79D scala.StringBuilder ":9%%&;90
java.lang.StringBuilder &20)9,;*">*B"2>7&B)&2'*A&)(*&).

Y&2,77$D*)(9 Predef "CI9B)*&0*&1#"%)9;.*G)*B"2),&20*K=&)9*,*>9A*=09>=7*>=2B)&"20.*M<(909


B"=7;*9K=,77$*A977*(,:9*C992*#7,B9;*&2)"*)(9 scala #,BE,'9*"CI9B)D*C=) Predef A,0
&2)%";=B9;*C9>"%9*-B,7,*(,;*#,BE,'9*"CI9B)0.N

-&2B9*)(9 scala #,BE,'9*&0*&1#"%)9;*C$*;9>,=7)D*$"=*29:9%*299;*)"*A%&)9*#,BE,'9*2,190


)(,)*0),%)*A&)( scala.*Y"%*9H,1#79D

import collection.mutable.HashMap

&0*I=0)*,0*'"";*,0

import scala.collection.mutable.HashMap

7.11. Exercises
5. b%&)9*,2*9H,1#79*#%"'%,1*)"*;91"20)%,)9*)(,)

][
package com.horstmann.impatient

&0*2")*)(9*0,19*,0

package com
package horstmann
package impatient

3. b%&)9*,*#=pp79%*)(,)*C,>>790*$"=%*-B,7,*>%&92;0D*=0&2'*,*#,BE,'9 com )(,)*&02L)*,)


)(9*)"#*79:97.
X. b%&)9*,*#,BE,'9 random A&)(*>=2B)&"20 nextInt(): IntD nextDouble(): DoubleD
,2; setSeed(seed: Int): Unit.*<"*'929%,)9*%,2;"1*2=1C9%0D*=09*)(9*7&29,%
B"2'%=92)&,7*'929%,)"%

next r previous u a @ b 1";*3nD

A(9%9 a r*5\\Z[3[D b r*545X_4Z33XD*,2; n r*X3.

Z. b($*;"*$"=*)(&2E*)(9*-B,7,*7,2'=,'9*;90&'29%0*#%":&;9;*)(9 package object


0$2),H*&20)9,;*">*0&1#7$*79))&2'*$"=*,;;*>=2B)&"20*,2;*:,%&,C790*)"*,*#,BE,'9g
[. b(,)*&0*)(9*19,2&2'*"> private[com] def giveRaise(rate: Double)g*G0*&)
=09>=7g
\. b%&)9*,*#%"'%,1*)(,)*B"#&90*,77*979192)0*>%"1*,*?,:,*(,0(*1,#*&2)"*,*-B,7,*(,0(
1,#.*e09*&1#"%)0*)"*%92,19*C")(*B7,0090.
]. G2*)(9*#%9B9;&2'*9H9%B&09D*1":9*,77*&1#"%)0*&2)"*)(9*&229%1"0)*0B"#9*#"00&C79.
^. b(,)*&0*)(9*9>>9B)*">

import java._
import javax._

G0*)(&0*,*'"";*&;9,g

_. b%&)9*,*#%"'%,1*)(,)*&1#"%)0*)(9 java.lang.System B7,00D*%9,;0*)(9*=09%*2,19


>%"1*)(9 user.name 0$0)91*#%"#9%)$D*%9,;0*,*#,00A"%;*>%"1*)(9 Console "CI9B)D
,2;*#%&2)0*,*1900,'9*)"*)(9*0),2;,%;*9%%"%*0)%9,1*&>*)(9*#,00A"%;*&0*2") "secret".
Q)(9%A&09*#%&2)*,*'%99)&2'*)"*)(9*0),2;,%;*"=)#=)*0)%9,1.*U"*2")*=09*,2$*")(9%
&1#"%)0D*,2;*;"*2")*=09*,2$*K=,7&>&9;*2,190*MA&)(*;")0N.
54. 6#,%)*>%"1 StringBuilderD*A(&B(*")(9%*191C9%0*"> java.lang ;"90*)(9 scala
#,BE,'9*":9%%&;9g

]\
8. Inheritance (A1)
G2*)(&0*B(,#)9%D*$"=*A&77*79,%2*)(9*1"0)*&1#"%),2)*A,$0*&2*A(&B(*&2(9%&),2B9*&2*-B,7,
;&>>9%0*>%"1*&)0*B"=2)9%#,%)*&2*?,:,*"%*!@@.*<(9*(&'(7&'()0*,%9R

d <(9 extends ,2; final E9$A"%;0*,%9*,0*&2*?,:,


d c"=*1=0)*=09 override A(92*$"=*":9%%&;9*,*19)(";
d Q27$*)(9*#%&1,%$*B"20)%=B)"%*B,2*B,77*)(9*#%&1,%$*0=#9%B7,00*B"20)%=B)"%
d c"=*B,2*":9%%&;9*>&97;0

G2*)(&0*B(,#)9%D*A9*"27$*;&0B=00*)(9*B,09*&2*A(&B(*,*B7,00*&2(9%&)0*>%"1*,2")(9%*B7,00.*-99
)(9*n<%,&)0o*B(,#)9% >"%*&2(9%&)&2' traitsh)(9*-B,7,*B"2B9#)*)(,)*'929%,7&p90*?,:,
&2)9%>,B90.

8.1. Extending a Class


c"=*9H)92;*,*B7,00*&2*-B,7,*I=0)*7&E9*$"=*A"=7;*&2*?,:,D*A&)(*)(9 extends E9$A"%;.

class Employee extends Person {


var salary: Double
...
}

60*&2*?,:,D*$"=*0#9B&>$*>&97;0*,2;*19)(";0*)(,)*,%9*29A*)"*)(9*0=CB7,00*"%*)(,)*":9%%&;9
19)(";0*&2*)(9*0=#9%B7,00.

60*&2*?,:,D*$"=*B,2*;9B7,%9*,*B7,00 final 0"*)(,)*&)*B,22")*C9*9H)92;9;.*c"=*B,2*,70"


;9B7,%9*&2;&:&;=,7*19)(";0*"%*>&97;0*MzN*,0 final 0"*)(,)*)(9$*B,22")*C9*":9%%&;;92.*M-99
-9B)&"2*\ >"%*":9%%&;&2'*>&97;0.N

8.2. Overriding Methods


G2*-B,7,D*$"= must =09*)(9 override 1";&>&9%*A(92*$"=*":9%%&;9*,*19)(";*)(,)*&02L)
,C0)%,B).*M-99 -9B)&"2*^ >"%*,C0)%,B)*19)(";0.N*Y"%*9H,1#79D

public class Person {


...
override def toString = getClass.getName + "[name=" + name + "]"
}

<(9 override 1";&>&9%*B,2*'&:9*=09>=7*9%%"%*1900,'90*&2*,*2=1C9%*">*B"11"2*B,090.


61"2'*)(91*,%9R

]]
d b(92*$"=*1&00#977*)(9*2,19*">*)(9*19)(";*)(,)*$"=*,%9*":9%%&;&2'
d b(92*$"=*,BB&;92),77$*#%":&;9*)(9*A%"2'*#,%,19)9%*)$#9*&2*)(9*":9%%&;&2'
19)(";
d b(92*$"=*&2)%";=B9*,*29A*19)(";*&2*,*0=#9%B7,00*)(,)*B7,0(90*A&)(*,*0=CB7,00
19)(";

Note: <(9*7,0)*B,09*&0*,2*&20),2B9*">*)(9 fragile base class problemD*A(9%9*,


B(,2'9*&2*)(9*0=#9%B7,00*B,22")*C9*:9%&>&9;*A&)("=)*7""E&2'*,)*,77*)(9
0=CB7,0090.*/9%9*&0*,2*9H,1#79.*-=##"09*#%"'%,119%*67&B9*;9>&290*,
Person B7,00D*,2;D*=2C9E2"A20)*)"*67&B9D*#%"'%,119%*V"C*;9>&290*,*0=CB7,00
Student A&)(*,*19)("; id $&97;&2'*)(9*0)=;92)*GU.*T,)9%D*67&B9*,70"*;9>&290*,
19)("; id )(,)*("7;0*)(9*#9%0"2L0*2,)&"2,7*GU.*b(92*V"C*#&BE0*=#*)(,)*B(,2'9D
0"19)(&2'*1,$*C%9,E*&2*V"CL0*#%"'%,1*MC=)*2")*&2*67&B9L0*)90)*B,090N*0&2B9
Student "CI9B)0*%9)=%2*=29H#9B9;*GU0.

G2*?,:,D*"29*&0*">)92*,;:&09;*)"*n0"7:9o*)(&0*#%"C791*C$*;9B7,%&2'*,77*19)(";0
,0 final =27900*)(9$*,%9*9H#7&B&)7$*;90&'29;*)"*C9*":9%%&;;92.*<(,)*0"=2;0
'"";*&2*)(9"%$D*C=)*#%"'%,119%0*(,)9*&)*&>*)(9$*B,2L)*9:92*1,E9*)(9*1"0)
&22"B="=0*B(,2'90*)"*,*19)(";*M0=B(*,0*,;;&2'*,*7"''&2'*B,77N.*<(,)L0*A($
?,:,*9:92)=,77$*&2)%";=B9;*,2*"#)&"2,7 @Overrides ,22"),)&"2.

G2:"E&2'*,*0=#9%B7,00*19)(";*A"%E0*9H,B)7$*7&E9*&2*?,:,D*A&)(*)(9*E9$A"%; superR

public class Employee extends Person {


override def toString = super.
super.toString + "[salary=" + salary + "]"
}

<(9*B,77 super.toString B,770*)(9 toString 19)(";*">*)(9*0=#9%B7,00D*)(,)*&0D*)(9


Person.toString 19)(";.

8.3. Type Checks and Casts


<"*)90)*A(9)(9%*,2*"CI9B)*C97"2'0*)"*,*'&:92*B7,00D*$"=*=09*)(9 isInstanceOf 19)(";.*G>
)(9*)90)*0=BB99;0D*$"=*B,2*=09*)(9 asInstanceOf 19)(";*)"*B"2:9%)*,*%9>9%92B9*)"*,
0=CB7,00*%9>9%92B9.

if (p.isInstanceOf[Student]) {
val s = p.asInstanceOf[Student] // s (,0*)$#9 Student
...
}

<(9 p.isInstanceOf[Student] )90)*0=BB99;0*&> p %9>9%0*)"*,2*"CI9B)*">*B7,00 Student "%*,


0=CB7,00*M0=B(*,0 GraduateStudentN.

]^
G> p &0 nullD*)(92 p.isInstanceOf[Student] %9)=%20 false ,2; p.asInstanceOf[Student]
%9)=%20 null.

G> p &0*2")*,*0)=;92)D*)(92 p.asInstanceOf[Student] %9)=%20 nullh&)*;"90*2")*)(%"A*,2


9HB9#)&"2.

G>*$"=*A,2)*)"*)90)*A(9)(9% p %9>9%0*)"*, Student "CI9B)D*C=)*2")*,*0=CB7,00D*=09

if (p.getClass == classOf[Student])

<(9 classOf 19)(";*&0*;9>&29;*&2*)(9 scala.Predef "CI9B)*)(,)*&0*,7A,$0*&1#"%)9;.

<,C79*5 0("A0*)(9*B"%%%90#"2;92B9*C9)A992*-B,7,*,2;*?,:,*)$#9*B(9BE0*,2;*B,0)0.

<,C79*^J5R <$#9*!(9BE0*,2;*!,0)0*&2*-B,7,*,2;*?,:,
Scala Java
obj.isInstanceOf[Cl] obj instanceof Cl
obj.asInstanceOf[Cl] (Cl) obj "% null &> obj &0*2")*,2*&20),2B9*"> C
classOf[Cl] Cl.class

/"A9:9%D*#,))9%2*1,)B(&2'*&0*=0=,77$*,*C9))9%*,7)9%2,)&:9*)(,2*=0&2'*)$#9*B(9BE0*,2;
B,0)0.*Y"%*9H,1#79D

p match {
case s: Student => ... // S%"B900 s ,0*, Student
case _ => ... // p A,02L)*, Student
}

-99 )(9*nS,))9%2*P,)B(&2'*,2;*!,09*!7,0090o*B(,#)9% >"%*1"%9*&2>"%1,)&"2.

8.4. Protected Fields and Methods


60*&2*?,:,*"%*!@@D*$"=*B,2*;9B7,%9*,*>&97;*"%*19)(";*,0 protected.*-=B(*,*191C9%*&0
,BB900&C79*>%"1*,2$*0=CB7,00D*C=)*2")*>%"1*")(9%*7"B,)&"20.

e27&E9*&2*?,:,D*, protected 191C9%*&0 not :&0&C79*)(%"='("=)*)(9*#,BE,'9*)"*A(&B(*)(9


B7,00*C97"2'0.*MG>*$"=*A,2)*)(&0*:&0&C&7&)$D*$"=*B,2*=09*,*#,BE,'9*1";&>&9%h099 )(9
nS,BE,'90*,2;*G1#"%)0o*B(,#)9%.N

<(9%9*&0*,70"*, protected[this] :,%&,2)*)(,)*%90)%&B)0*,BB900*)"*)(9*B=%%92)*"CI9B)D*0&1&7,%


)"*)(9 private[this] :,%&,2)*;&0B=009;*&2 )(9*n!7,0090o*B(,#)9%.

]_
8.5. Superclass Construction
89B,77*>%"1 )(9*n!7,0090o*B(,#)9% )(,)*,*B7,00*(,0*,2$*2=1C9%*">*,=H&7&,%$*B"20)%=B)"%0
,2;*"29*#%&1,%$*B"20)%=B)"%D*,2;*)(,)*,77*,=H&7&,%$*B"20)%=B)"%0*1=0)*0),%)*A&)(*,*B,77*)"*,
#%9B9;&2'*,=H&7&,%$*B"20)%=B)"%*"%*)(9*#%&1,%$*B"20)%=B)"%.

60*,*B"209K=92B9D*,2*,=H&7&,%$*B"20)%=B)"%*B,2 never &2:"E9*,*0=#9%B7,00*B"20)%=B)"%


;&%9B)7$.

<(9*,=H&7&,%$*B"20)%=B)"%0*">*)(9*0=CB7,00*9:92)=,77$*B,77*)(9*#%&1,%$*B"20)%=B)"%*">*)(9
0=CB7,00.*Q27$*)(9*#%&1,%$*B"20)%=B)"%*B,2*B,77*,*0=#9%B7,00*B"20)%=B)"%.

89B,77*)(,)*)(9*#%&1,%$*B"20)%=B)"%*&0*&2)9%)A&29;*A&)(*)(9*B7,00*;9>&2&)&"2.*<(9*B,77*)"*)(9
0=#9%B7,00*B"20)%=B)"%*&0*0&1&7,%7$*&2)9%)A&29;.*/9%9*&0*,2*9H,1#79.

<(9*-B,7,*9K=&:,792)*&0R

class Employee(name: String, age: Int, val salary : Double) extends


Person(name, age)

<(&0*;9>&290*,*0=CB7,00

class Employee(name: String, age: Int, val salary : Double) extends


Person(name, age)

,2;*,*#%&1,%$*B"20)%=B)"%*)(,)*B,770*)(9*0=#9%B7,00*B"20)%=B)"%

class Employee(name: String, age: Int, val salary : Double) extends


Person(name, age)

G2)9%)A&2&2'*)(9*B7,00*,2;*)(9*B"20)%=B)"%*1,E90*>"%*:9%$*B"2B&09*B";9.*c"=*1,$*>&2;*&)
(97#>=7*)"*)(&2E*">*)(9*#%&1,%$*B"20)%=B)"%*#,%,19)9%0*,0*#,%,19)9%0*">*)(9*B7,00.*/9%9D
)(9 Employee B7,00*(,0*)(%99*#,%,19)9%0 nameD ageD*,2; salaryD*)A"*">*A(&B(*&)*n#,0090o*)"
)(9*0=#9%B7,00.

G2*?,:,D*)(9*9K=&:,792)*B";9*&0*K=&)9*,*C&)*1"%9*:9%C"09.

public class Employee extends Person { // ?,:,


private double salary;
public Employee(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
}

^4
Note: G2*,*-B,7,*B"20)%=B)"%D*$"=*B,2*29:9%*B,77 super(params)D*,0*$"=*A"=7;
&2*?,:,D*)"*B,77*)(9*0=#9%B7,00*B"20)%=B)"%.

6*-B,7,*B7,00*B,2*9H)92;*,*?,:,*B7,00.*G)0*#%&1,%$*B"20)%=B)"%*1=0)*&2:"E9*"29*">*)(9
B"20)%=B)"%0*">*)(9*?,:,*0=#9%B7,00.*Y"%*9H,1#79D

class Square(x: Int, y: Int, width: Int) extends


java.awt.Rectangle(x, y, width, width)

8.6. Overriding Fields


89B,77*>%"1 )(9*n!7,0090o*B(,#)9% )(,)*,*>&97;*&2*-B,7,*B"20&0)0*">*,*#%&:,)9*>&97; and
,BB900"%i1=),)"%*19)(";0.*c"=*B,2*":9%%&;9*, val M"%*,*#,%,19)9%7900 defN*A&)(*,2")(9%
val >&97;*">*)(9*0,19*2,19.*<(9*0=CB7,00*(,0*,*#%&:,)9*>&97;*,2;*,*#=C7&B*'9))9%D*,2;*)(9
'9))9%*":9%%&;90*)(9*0=#9%B7,00*'9))9%*M"%*19)(";N.

Y"%*9H,1#79D

class Person(val name: String) {


override def toString = getClass.getName + "[name=" + name + "]"
}

class SecretAgent(codename: String) extends Person(codename) {


override val name = "secret" // U"2L)*A,2)*)"*%9:9,7*2,19...
override val toString = "secret" // ..."%*B7,00*2,19
}

<(&0*9H,1#79*0("A0*)(9*19B(,2&B0D*C=)*&)*&0*%,)(9%*,%)&>&B&,7.*6*1"%9*B"11"2*B,09*&0*)"
":9%%&;9*,2*,C0)%,B) def A&)(*, valD*7&E9*)(&0R

abstract class Person { // -99 -9B)&"2*^ >"%*,C0)%,B)*B7,0090


def id: Int // W,B(*#9%0"2*(,0*,2*GU*)(,)*&0*B"1#=)9;*&2*0"19*A,$
...
}

class Student(override
override val id: Int) extends Person
// 6*0)=;92)*GU*&0*0&1#7$*#%":&;9;*&2*)(9*B"20)%=B)"%

f")9*)(9*>"77"A&2'*%90)%&B)&"20*M099*,70" <,C79*3NR

d 6 def B,2*"27$*":9%%&;9*,2")(9% def


d 6 val B,2*"27$*":9%%&;9*,2")(9% val "%*#,%,19)9%7900 def

^5
d 6 var B,2*"27$*":9%%&;9*,2*,C0)%,B) var M099 -9B)&"2*^N

<,C79*^J3R Q:9%%&;&2' valD defD*,2; var

with val with var


with
def
d 0=CB7,00*(,0
#%&:,)9*>&97;*MA&)(
)(9*0,19*2,19*,0
Override W%%"%R*299;0*)"*C9*,*0),C79D*&11=),C79
val
)(9*0=#9%B7,00
:,7=9
>&97;h)(,)L0*QaN
d '9))9%*":9%%&;90
0=#9%B7,00*'9))9%
d 0=CB7,00*(,0 6 var B,2*":9%%&;9*,*'9))9%i
T&E9
Override #%&:,)9*>&97; 09))9%*#,&%.*Q:9%%&;&2'*I=0)*,
def
&2
d '9))9%*":9%%&;90 '9))9%*;"902L)*A"%E*MW%%"%R*09))9%
?,:,
0=#9%B7,00*19)("; ":9%%&;90*2")(&2'N
Override Q27$*&>*)(9*0=#9%B7,00 var &0
var
W%%"%R*":9%%&;&2'*:,%&,C79
,C0)%,B)*M099 -9B)&"2*^N

Note: G2 )(9*n!7,0090o*B(,#)9%D*G*0,&;*)(,)*&)L0*"E*)"*=09*, var C9B,=09*$"=*B,2


,7A,$0*B(,2'9*$"=%*1&2;*,2;*%9&1#79192)*&)*,0*,*'9))9%i09))9%*#,&%.*/"A9:9%D
)(9*#%"'%,119%0*9H)92;&2'*$"=%*B7,00*;"*2")*(,:9*)(,)*B("&B9.*<(9$*B,22")
":9%%&;9*, var A&)(*,*'9))9%i09))9%*#,&%.*G2*")(9%*A"%;0D*&>*$"=*#%":&;9*, varD*,77
0=CB7,0090*,%9*0)=BE*A&)(*&).

8.7. Anonymous Subclasses


60*&2*?,:,D*$"=*1,E9*,2*&20),2B9*">*,2 anonymous 0=CB7,00*&>*$"=*&2B7=;9*,*C7"BE*A&)(
;9>&2&)&"20*"%*":9%%&;90D*0=B(*,0

val alien = new Person("Fred") {


override val toString = "Greetings, Earthling! My name is Fred."
}

<9B(2&B,77$D*)(&0*1,E90*, structural typeh099 )(9*n-)%=B)=%,7*<$#90o*B(,#)9% >"%*;9),&70.


G2*?,:,D*,77*,2"2$1"=0*B7,0090*,%9*;&0)&2B)D*C=)*&2*-B,7,D*,2"2$1"=0*)$#90*A&)(*)(9*0,19
0)%=B)=%9*,%9*,B)=,77$*)(9*0,19*)$#9.

^3
8.8. Abstract Classes
60*&2*?,:,D*$"=*=09*)(9 abstract E9$A"%;*)"*;92")9*,*B7,00*)(,)*B,22")*C9*&20),2)&,)9;D
=0=,77$*C9B,=09*"29*"%*1"%9*">*&)0*19)(";0*&0*2")*;9>&29;.*Y"%*9H,1#79D

abstract class Person(val name: String) {


def id(): Int // f"*19)(";*C";$h)(&0*&0*,2*,C0)%,B)*19)(";
{

/9%9*A9*0,$*)(,)*9:9%$*#9%0"2*(,0*,2*GUD*C=)*A9*;"2L)*E2"A*("A*)"*B"1#=)9*&).*W,B(
B"2B%9)9*0=CB7,00*"> Person 299;0*)"*0#9B&>$*,2 id 19)(";.*G2*-B,7,D*=27&E9*?,:,D*$"=*;"
2")*=09*)(9 abstract E9$A"%;*>"%*,2*,C0)%,B)*19)(";.*c"=*0&1#7$*"1&)*&)0*C";$.*60*&2
?,:,D*,*B7,00*A&)(*,)*79,0)*"29*,C0)%,B)*19)(";*1=0)*C9*;9B7,%9; abstract.

G2*,*0=CB7,00D*$"=*299;*2")*=09*)(9 override E9$A"%;*A(92*$"=*;9>&29*,*19)(";*)(,)*A,0


,C0)%,B)*&2*)(9*0=#9%B7,00.

class Employee(name: String) extends Person(name) {


def id() = 42 // override E9$A"%;*2")*%9K=&%9;
}

8.9. Abstract Fields


G2*,;;&)&"2*)"*,C0)%,B)*19)(";0D*,*B7,00*B,2*,70"*(,:9*,C0)%,B)*>&97;0.*62*,C0)%,B)*>&97;*&0
0&1#7$*,*>&97;*A&)("=)*,2*&2&)&,7*:,7=9.*Y"%*9H,1#79D

abstract class Person {


val id: Int // f"*&2&)&,7&p9%h)(&0*&0*,2*,C0)%,B)*>&97;*A&)(*,2*,C0)%,B)*'9))9%*19)(";
var name: String // 62")(9%*,C0)%,B)*>&97;D*A&)(*,C0)%,B)*'9))9%*,2;*09))9%*19)(";0
}

<(&0*B7,00*;9>&290*,C0)%,B)*'9))9%*19)(";0*>"%*)(9 id ,2; name >&97;0D*,2;*,2*,C0)%,B)*09))9%


>"%*)(9 name >&97;.*<(9*'929%,)9;*?,:,*B7,00*(,0 no fields.

!"2B%9)9*0=CB7,0090*1=0)*#%":&;9*B"2B%9)9*>&97;0D*>"%*9H,1#79R

class Employee(val id: Int) extends Person { // -=CB7,00*(,0*B"2B%9)9 id #%"#9%)$


var name = "" // ,2;*B"2B%9)9 name #%"#9%)$
}

60*A&)(*19)(";0D*2" override E9$A"%;*&0*%9K=&%9;*&2*)(9*0=CB7,00*A(92*$"=*;9>&29*,


>&97;*)(,)*A,0*,C0)%,B)*&2*)(9*0=#9%B7,00.

c"=*B,2*,7A,$0*B=0)"1&p9*,2*,C0)%,B)*>&97;*C$*=0&2'*,2*,2"2$1"=0*)$#9R

^X
val fred = new Person {
val id = 1729
var name = "Fred"
}

8.10. Construction Order and Early Definitions (L3)


b(92*$"=*":9%%%&;9*, val &2*,*0=CB7,00 and =09*)(9*:,7=9*&2*,*0=#9%B7,00*B"20)%=B)"%D*)(92
)(9*%90=7)&2'*C9(,:&"%*&0*=2&2)=&)&:9.

/9%9*&0*,2*9H,1#79.*6*B%9,)=%9*B,2*09209*,*#,%)*">*&)0*92:&%"2192).*Y"%*0&1#7&B&)$D*A9
,00=19*)(9*B%9,)=%9*7&:90*&2*,*"29J;&1920&"2,7*A"%7;D*,2;*)(9*0920"%$*;,),*,%9
%9#%9092)9;*,0*&2)9'9%0.*6*;9>,=7)*B%9,)=%9*B,2*099*)92*=2&)0*,(9,;.

class Creature {
val range: Int = 10
val env: Array[Int] = new Array[Int](range)
}

62)0D*("A9:9%D*,%9*29,%J0&'()9;R

class Ant extends Creature {


override val range = 2
}

e2>"%)=2,)97$D*A9*2"A*(,:9*,*#%"C791.*<(9 range :,7=9*&0*=09;*&2*)(9*0=#9%B7,00


B"20)%=B)"%D*,2;*)(9*0=#9%B7,00*B"20)%=B)"%*%=20 before )(9*0=CB7,00*B"20)%=B)"%.
-#9B&>&B,77$D*(9%9*&0*A(,)*(,##920.

5. <(9 Ant B"20)%=B)"%*B,770*)(9 Creature B"20)%=B)"%*C9>"%9*;"&2'*&)0*"A2


B"20)%=B)&"2
3. <(9 Creature B"20)%=B)"%*09)0 its range >&97;*)"*54.
X. <(9 Creature B"20)%=B)"%D*&2*"%;9%*)"*&2&)&,7&p9*)(9 env ,%%,$D*B,770*)(9 range()
'9))9%
Z. <(,)*19)(";*&0*":9%%&;;92*)"*$&97;*)(9*M,0*$9)*=2&2&)&,7&p9;N range >&97;*">*)(9 Ant
B7,00
[. <(9 range 19)(";*%9)=%20*4.*M<(,)*&0*)(9*&2&)&,7*:,7=9*">*,77*&2)9'9%*>&97;0*A(92*,2
"CI9B)*&0*,77"B,)9;.N
\. env &0*09)*)"*,2*,%%,$*">*792')(*4.
]. <(9 Ant B"20)%=B)"%*B"2)&2=90D*09))&2'*&)0*%,2'9*>&97;*)"*3.

W:92*)("='(*&)*,##9,%0*,0*&> range A,0*9&)(9%*54*"%*3D env (,0*C992*09)*)"*,2*,%%,$*">


792')(*4.*<(9*1"%,7*&0*)(,)*$"=*0("=7;*2")*%97$*"2*)(9*:,7=9*">*, val &2*)(9*C";$*">*,
B"20)%=B)"%.

^Z
G2*?,:,D*$"=*(,:9*,*0&1&7,%*&00=9*A(92*$"=*B,77*,*19)(";*&2*,*0=#9%B7,00*B"20)%=B)"%.*<(9
19)(";*1&'()*C9*":9%%&;;92*&2*,*0=CB7,00D*,2;*&)*1&'()*2")*;"*A(,)*$"=*A,2)*&)*)"*;".*MG2
>,B)D*)(,)*&0*)(9*%"")*B,=09*">*"=%*#%"C791h)(9*9H#%900&"2 range B,770*)(9*'9))9%*19)(";.N

<(9%9*,%9*09:9%,7*%919;&90R

d U9B7,%9*)(9 val ,0 final.*<(&0*&0*0,>9*C=)*2")*:9%$*>79H&C79.


d U9B7,%9*)(9 val ,0 lazy M099*`8WYN.*<(&0*&0*0,>9*C=)*,*C&)*&29>>&B&92).
d e09*)(9 early definition syntax &2*)(9*0=CB7,00h099*C97"A

<(9*n9,%7$*;9>&2&)&"2o*0$2),H*79)0*$"=*&2&)&,7&p9 val >&97;0*">*,*0=CB7,00 before )(9


0=#9%B7,00*&0*9H9B=)9;.*<(9*0$2),H*&0*0"*='7$*)(,)*"27$*,*1")(9%*B"=7;*7":9*&).*c"=*#7,B9
)(9 val >&97;0*&2*,*C7"BE*,>)9%*)(9 extends E9$A"%;D*7&E9*)(&0R

class Bug extends {


override val range = 3
} with Creature

f")9*)(9 with E9$A"%;*C9>"%9*)(9*0=#9%B7,00*2,19.*<(&0*E9$A"%;*&0*2"%1,77$*=09;*A&)(


)%,&)0h099 )(9*n<%,&)0o*B(,#)9%.

<(9*%&'()*(,2;*0&;9*">*,2*9,%7$*;9>&2&)&"2*B,2*"27$*%9>9%*)"*#%9:&"=0*9,%7$*;9>&2&)&"20D*2")
)"*")(9%*>&97;0*"%*19)(";0*">*)(9*B7,00.

Tip: c"=*B,2*;9C='*B"20)%=B)&"2*"%;9%*#%"C7910*A&)(*)(9 -Xcheckinit


B"1#&79%*>7,'.*<(&0*>7,'*'929%,)90*B";9*)(,)*)(%"A0*,2*9HB9#)&"2*M&20)9,;*">
$&97;&2'*)(9*;9>,=7)*:,7=9N*A(92*,2*=2&2&)&,7&p9;*>&97;*&0*,BB9009;.

Note: 6)*)(9*%"")*">*)(9*B"20)%=B)&"2*"%;9%*#%"C791*7&90*,*;90&'2*;9B&0&"2*">
)(9*?,:,*7,2'=,'9D*2,197$*)"*,77"A*)(9*&2:"B,)&"2*">*0=CB7,00*19)(";0*&2*,
0=#9%B7,00*B"20)%=B)"%.*G2*!@@D*,2*"CI9B)L0*:&%)=,7*>=2B)&"2*),C79*#"&2)9%*&0*09)
)"*)(9*),C79*">*)(9*0=#9%B7,00*A(92*)(9*0=#9%B7,00*B"20)%=B)"%*9H9B=)90.
6>)9%A,%;0D*)(9*#"&2)9%*&0*09)*)"*)(9*0=CB7,00*),C79.*<(9%9>"%9D*&2*!@@D*&)*&0*2")
#"00&C79*)"*1";&>$*B"20)%=B)"%*C9(,:&"%*)(%"='(*":9%%&;&2'.*<(9*?,:,
;90&'29%0*>97)*)(,)*)(&0*0=C)79)$*A,0*=229B900,%$D*,2;*)(9*?,:,*:&%)=,7*1,B(&29
;"90*2")*,;I=0)*)(9*:&%)=,7*>=2B)&"2*),C79*;=%&2'*B"20)%=B)&"2.

8.11. The Scala Inheritance Hierarchy


Y&'=%9*5 0("A0*)(9*&2(9%&),2B9*(&9%,%B($*">*-B,7,*B7,0090.*<(9*B7,0090*)(,)*B"%%90#"2;*)"
)(9*#%&1&)&:9*)$#90*&2*?,:,D*,0*A977*,0*)(9*)$#9 UnitD*9H)92; AnyVal.

^[
677*")(9%*B7,0090*,%9*0=CB7,0090*">*)(9 AnyRef B7,00D*A(&B(*&0*,*0$2"2$1*>"%*)(9 Object
B7,00*>%"1*)(9*?,:,*"%*.fW<*:&%)=,7*1,B(&29.

V")( AnyVal ,2; AnyRef 9H)92;*)(9 Any B7,00D*)(9*%"")*">*)(9*(&9%,%B($.

Y&'=%9*^J5R <(9*G2(9%&),2B9*/&9%,%B($*">*-B,7,*!7,0090From: Odersky, Altherr,


et al., An Overview of the Scala Programming Language, Second Edition,
Technical Report LAMP-REPORT-2006-001, ƒcole Polytechnique FŽdŽrale de
Lausanne (EPFL), Lausanne, Switzerland

<(9 Any B7,00*;9>&290*19)(";0 isInstanceOfD asInstanceOfD*,2;*)(9*19)(";0*>"%*9K=,7&)$


,2;*(,0(*B";90*)(,)*A9*A&77*7""E*,)*&2*`8WY.

AnyVal ;"90*2")*,;;*,2$*19)(";0.*G)*&0*I=0)*,*1,%E9%*>"%*:,7=9*)$#90.

<(9 AnyRef B7,00*,;;0*)(9*1"2&)"%*19)(";0 wait ,2; notifyinotifyAll >%"1*)(9


Object B7,00.*G)*,70"*#%":&;90*, synchronized 19)(";*A&)(*,*>=2B)&"2*#,%,19)9%.*<(,)
19)(";*&0*)(9*9K=&:,792)*">*, synchronized C7"BE*&2*?,:,.*Y"%*9H,1#79D

account.synchronized { account.balance += amount }

^\
Note: ?=0)*7&E9*&2*?,:,D*G*0=''90)*$"=*0),$*,A,$*>%"1 waitD notifyD*,2;
synchronized =27900*$"=*(,:9*,*'"";*%9,0"2*)"*=09*)(91*&20)9,;*">*(&'(9%J
79:97*B"2B=%%92B$*B"20)%=B)0.

677*-B,7,*B7,0090*&1#79192)*)(9*1,%E9%*&2)9%>,B9 ScalaObjectD*A(&B(*(,0*2"*19)(";0.

Q2*)(9*")(9%*92;*">*)(9*(&9%,%B($*,%9*)(9 Nothing ,2; Null )$#90.

Null &0*)(9*)$#9*A("09*0"79*&20),2B9*&0*)(9*:,7=9 null.*c"=*B,2*,00&'2 null )"*,2$


%9>9%92B9D*C=)*2")*)"*"29*">*)(9*:,7=9*)$#90.*Y"%*9H,1#79D*09))&2'*,2 Int )"*2=77*&0*2")
#"00&C79.*<(&0*&0*C9))9%*)(,2*&2*?,:,D*A(9%9*&)*A"=7;*C9*#"00&C79*)"*09)*,2 Integer A%,##9%
)" null.

<(9 Nothing )$#9*(,0*2"*&20),2B90.*G)*&0*"BB,0&"2,77$*=09>=7*>"%*'929%&B*B"20)%=B)0.*Y"%


9H,1#79D*)(9*91#)$*7&0) Nil (,0*)$#9 List[Nothing]D*A(&B(*&0*,*0=C)$#9*"> List[T] >"%
,2$ T.

Caution: <(9 Nothing )$#9*&0*2")*,)*,77*)(9*0,19*,0 void &2*?,:,*"%*!@@.*G2


-B,7,D void &0*%9#%9092)9;*C$*)(9 Unit )$#9D*)(9*)$#9*A&)(*)(9*0"79*:,7=9 ().
f")9*)(,) Unit &0*2")*,*0=#9%)$#9*">*,2$*")(9%*)$#9.*/"A9:9%D*)(9*B"1#&79%*0)&77
,77"A0*,2$*:,7=9*)"*C9 replaced C$*, ().*!"20&;9%

def printAny(x: Any) { println(x) }


def printUnit(x: Unit) { println(x) }
printAny("Hello") // S%&2)0 Hello
printUnit("Hello")
// 89#7,B90 "Hello" A&)( () ,2;*B,770 printUnit(())D*A(&B(*#%&2)0 ()

8.12. Object Equality (L1)


G2*-B,7,D*)(9 eq 19)(";*">*)(9 AnyRef B7,00*B(9BE0*A(9)(9%*)A"*%9>9%92B90*%9>9%*)"*)(9
0,19*"CI9B).*<(9 equals 19)(";*&2 AnyRef B,770 eq.*b(92*$"=*&1#79192)*,*B7,00D*$"=
0("=7;*B"20&;9%*":9%%&;&2'*)(9 equals 19)(";*)"*#%":&;9 ,*2,)=%,7*2")&"2*">*9K=,7&)$*>"%
$"=%*0&)=,)&"2.

Y"%*9H,1#79D*&>*$"=*;9>&29*, class Item(val description: String, val price:


Double)D*$"=*1&'()*A,2)*)"*B"20&;9%*)A"*&)910*9K=,7*&>*)(9$*(,:9*)(9*0,19*;90B%&#)&"2
,2;*#%&B9.*/9%9*&0*,2*,##%"#%&,)9 equals 19)(";R

final override def equals(other: Any) = {


val that = other.asInstanceOf[Item]
if (that == null) false

^]
else description == that.description && price == that.price
}

Note: b9*;9>&29;*)(9*19)(";*,0 final C9B,=09*&)*&0*'929%,77$*:9%$*;&>>&B=7)*)"


B"%%9B)7$*9H)92;*9K=,7&)$*&2*,*0=CB7,00.*<(9*#%"C791*&0*0$119)%$.*c"=*A,2)
a.equals(b) )"*(,:9*)(9*0,19*%90=7)*,0 b.equals(a)D*9:92*&> b C97"2'0*)"*,
0=CB7,00.

Caution: V9*0=%9*)"*;9>&29*)(9 equals 19)(";*A&)(*#,%,19)9%*)$#9 Any.*<(9


>"77"A&2'*A"=7;*C9*A%"2'R

final def equals(other: Iten) = { ... }

<(&0*&0*,*;&>>9%92)*19)(";*)(,)*;"90*2")*":9%%&;9*)(9 equals 19)(";*"> AnyRef.

b(92*$"=*;9>&29 equalsD*%9191C9%*)"*;9>&29 hashCode ,0*A977.*<(9*(,0(*B";9*0("=7;*C9


B"1#=)9;*"27$*>%"1*)(9*>&97;0*)(,)*$"=*=09;*&2*)(9*9K=,7&)$*B(9BE.*G2*)(9 Item 9H,1#79D
B"1C&29*)(9*(,0(*B";90*">*)(9*>&97;0R

final override def hashCode = 13 * description.hashCode + 17 * price.hashCode

Tip: c"=*,%9*2")*B"1#9779;*)"*":9%%&;9 equals ,2; hashCode.*Y"%*1,2$


B7,0090D*&)*&0*,##%"#%&,)9*)"*B"20&;9%*;&0)&2B)*"CI9B)0*=29K=,7.*Y"%*9H,1#79D*&>
$"=*(,:9*)A"*;&0)&2B)*&2#=)*0)%9,10*"%*%,;&"*C=))"20D*$"=*A&77*29:9%*B"20&;9%
)(91*9K=,7.

G2*,2*,##7&B,)&"2*#%"'%,1D*$"=*;"2L)*'929%,77$*B,77 eq "% equals.*-&1#7$*=09*)(9 ==


"#9%,)"%.*G)*B,770 equals >"%*%9>9%92B9*)$#90D*,>)9%*;"&2'*)(9*,##%"#%&,)9*B(9BE*>"% null
"#9%,2;0.

8.13. Exercises
5. WH)92;*)(9*>"77"A&2' BankAccount B7,00*)"*, CheckingAccount B7,00*)(,)*B(,%'90
|5*>"%*9:9%$*;9#"0&)*,2;*A&)(;%,A,7.

class BankAccount(initialBalance: Double) {


private var balance = initialBalance
def deposit(amount: Double) = { balance += amount; balance }
def withdraw(amount: Double) = { balance -= amount; balance }
}

3. WH)92;*)(9 BankAccount B7,00*">*)(9*#%9B9;&2'*9H9%B&09*)"*,*B7,00 SavingsAccount


)(,)*9,%20*&2)9%90)*9:9%$*1"2)(*MA(92*,*19)("; earnMonthlyInterest &0*B,779;N

^^
,2;*)(,)*(,0*)(%99*>%99*;9#"0&)0*"%*A&)(;%,A,70*9:9%$*1"2)(.*8909)*)(9
)%,20,B)&"2*B"=2)*&2*)(9 earnMonthlyInterest 19)(";.
X. !"20=7)*$"=%*>,:"%&)9*?,:,*"%*!@@*)9H)C""E*)(,)*&0*0=%9*)"*(,:9*,2*9H,1#79*">*,
)"$*&2(9%&),2B9*(&9%,%B($D*#9%(,#0*&2:"7:&2'*91#7"$990D*#9)0D*'%,#(&B,7*0(,#90D
"%*)(9*7&E9.*G1#79192)*)(9*9H,1#79*&2*-B,7,.
Z. U9>&29*,2*,C0)%,B)*B7,00 Item A&)(*19)(";0 price ,2; description.*6 SimpleItem
&0*,2*&)91*A("09*#%&B9*,2;*;90B%&#)&"2*,%9*0#9B&>&9;*&2*)(9*B"20)%=B)"%.*<,E9
,;:,2),'9*">*)(9*>,B)*)(,)*, val B,2*":9%%&;9*, def.*6 Bundle &0*,2*&)91*)(,)
B"2),&20*")(9%*&)910.*G)0*#%&B9*&0*)(9*0=1*">*)(9*#%&B90*&2*)(9*C=2;79.*670"*#%":&;9
,*19B(,2&01*>"%*,;;&2'*&)910*)"*)(9*C=2;79*,2;*,*0=&),C79 description 19)(";.
[. U90&'2*,*B7,00 Point A("09 xJ*,2; yJB""%;&2,)9*:,7=90*B,2*C9*#%":&;9;*&2*,
B"20)%=B)"%.*S%":&;9*,*0=CB7,00 LabeledPoint A("09*B"20)%=B)"%*),E90*,*7,C97
:,7=9*,2; xJ*,2; yJB""%;&2,)90D*0=B(*,0

new LabeledPoint("Black Thursday", 1929, 230.07)

\. U9>&29*,2*,C0)%,B)*B7,00 Shape A&)(*,2*,C0)%,B)*19)("; centerPoint ,2;


0=CB7,0090 Rectangle ,2; Circle.*S%":&;9*,##%"#%&,)9*B"20)%=B)"%0*>"%*)(9
0=CB7,0090*,2;*":9%%&;9*)(9 centerPoint 19)(";*&2*9,B(*0=CB7,00.
]. S%":&;9*,*B7,00 Square )(,)*9H)92;0 java.awt.Rectangle ,2;*(,0*)(%99
B"20)%=B)"%0D*"29*)(,)*B"20)%=B)0*,*0K=,%9*A&)(*,*'&:92*B"%29%*#"&2)*,2;*A&;)(D
"29*)(,)*B"20)%=B)0*,*0K=,%9*A&)(*B"%29%*M4D*4N*,2;*,*'&:92*A&;)(D*,2;*"29*)(,)
B"20)%=B)0*,*0K=,%9*A&)(*B"%29%*M4D*4N*,2;*A&;)(*4.
^. !"1#&79*)(9 Person ,2; SecretAgent B7,0090*&2 -9B)&"2*\ ,2;*,2,7$p9*)(9*B7,00
>&790*A&)( javap.*/"A*1,2$ name >&97;0*,%9*)(9%9g*/"A*1,2$ name '9))9%
19)(";0*,%9*)(9%9g*b(,)*;"*)(9$*'9)g*M/&2)R*e09*)(9 -c ,2; -private "#)&"20.N
_. G2*)(9 Creature B7,00*"> -9B)&"2*54D*%9#7,B9 val range A&)(*, def.*b(,)*(,##920
A(92*$"=*,70"*=09*, def &2*)(9 Ant 0=CB7,00g*b(,)*(,##920*A(92*$"=*=09*, val
&2*)(9*0=CB7,00g*b($g
54. <(9*>&79*0B,7,iB"779B)&"2i&11=),C79i-),BE.0B,7,*B"2),&20*)(9*;9>&2&)&"2

class Stack[A] protected (protected val elems: List[A])

WH#7,&2*)(9*19,2&2'0*">*)(9 protected E9$A"%;0.*M/&2)R*T""E*,)*)(9*;&0B=00&"2


">*#%&:,)9*B"20)%=B)"%0*&2 )(9*n!7,0090o*B(,#)9%.N

^_
9. Files and Regular Expressions (A1)
G2*)(&0*B(,#)9%D*$"=*A&77*79,%2*("A*)"*B,%%$*"=)*B"11"2*>&79*#%"B900&2'*),0E0D*0=B(*,0
%9,;&2'*,77*7&290*"%*A"%;0*">*,*>&79*"%*%9,;&2'*,*>&79*B"2),&2&2'*2=1C9%0.

!(,#)9%*/&'(7&'()0R

d Source.fromFile(...).getLines.toArray $&97;0*,77*7&290*">*,*>&79
d Source.fromFile(...).mkString $&97;0*)(9*>&79*B"2)92)0*,0*,*0)%&2'
d <"*B"2:9%)*,*0)%&2'*&2)"*,*2=1C9%D*=09*)(9 toInt "% toDouble 19)(";.
d e09*)(9*?,:, PrintWriter )"*A%&)9*)9H)*>&790
d "regex".r &0*, Regex "CI9B)
d e09 """...""" &>*$"=%*%9'=7,%*9H#%900&"2*B"2),&20*C,BE07,0(90*"%*K=")90
d G>*,*%9'9H*#,))9%2*(,0*'%"=#0D*$"=*9H)%,B)*)(9&%*B"2)92)0*A&)(*)(9*0$2),H for
(regex(var1, ...,varn) <- string)
d <(9 @serializable ,22"),)&"2*1,E90*,*-B,7,*B7,00*09%&,7&p,C79

9.1. Reading Lines


<"*%9,;*,77*7&290*>%"1*,*>&79D*B,77*)(9 getLines 19)(";*"2*, scala.io.Source "CI9B)R

import io.Source
val source = Source.fromFile("myfile.txt", "UTF-8")
// <(9*>&%0)*,%'=192)*B,2*C9*,*0)%&2'*"%*, java.io.File
// c"=*B,2*"1&)*)(9*92B";&2'*&>*$"=*E2"A*)(,)*)(9*>&79*=090*)(9*;9>,=7)*#7,)>"%1*92B";&2'
val lines = source.getLines

<(9*%90=7)*&0*,2*&)9%,)"%*M099 )(9*n!"779B)&"20o*B(,#)9%N.*c"=*B,2*=09*&)*)"*#%"B900*)(9*7&290
"29*,)*,*)&19R

for (l <- lines) process l

Q%*$"=*B,2*#=)*)(9*7&290*&2)"*,2*,%%,$*"%*,%%,$*C=>>9%*C$*,##7$&2'*)(9 toArray "% toBuffer


19)(";*)"*)(9*&)9%,)"%R

val lines = source.getLines.toArray

-"19)&190D*$"=*I=0)*A,2)*)"*%9,;*,2*92)&%9*>&79*&2)"*,*0)%&2'.*<(,)L0*9:92*0&1#79%R

val contents = source.mkString

_4
Caution: !,77 close A(92*$"=*,%9*;"29*=0&2'*)(9 Source "CI9B).

9.2. Reading Characters


<"*%9,;*&2;&:&;=,7*B(,%,B)9%0*>%"1*,*>&79D*$"=*B,2*=09*, Source "CI9B)*;&%9B)7$*,0*,2
&)9%,)"%*0&2B9*)(9 Source B7,00*9H)92;0 Iterator[Char].

for (c <- source) process c

G>*$"=*A,2)*)"*C9*,C79*)"*#99E*,)*,*B(,%,B)9%*A&)("=)*B"20=1&2'*&)*M7&E9 istream::peek &2


!@@*"%*, PushbackInputStreamReader &2*?,:,ND*B,77*)(9 buffered 19)(";*"2*)(9*0"=%B9.
<(92*$"=*B,2*#99E*,)*)(9*29H)*&2#=)*A&)(*)(9 head 19)(";*A&)("=)*B"20=1&2'*&)

val source = Source.fromFile("myfile.txt", "UTF-8")


val iter = source.buffered
while (iter.hasNext) {
if (iter.head is nice)
process iter.next
else
...
}
source.close()

67)9%2,)&:97$D*&>*$"=%*>&79*&02L)*7,%'9D*$"=*1,$*I=0)*A,2)*)"*%9,;*&)*&2)"*,*0)%&2'*,2;*#%"B900
)(,)R

val str = source.mkString

9.3. Reading Tokens and Numbers


/9%9*&0*,*K=&BEJ,2;J;&%)$*A,$*">*%9,;&2'*,77*A(&)90#,B9J09#,%,)9;*)"E920*&2*,*0"=%B9R

val tokens = source.mkString.split("\\s+")

<"*B"2:9%)*,*0)%&2'*&2)"*,*2=1C9%D*=09*)(9 toInt "% toDouble 19)(";.*Y"%*9H,1#79D*&>*$"=


(,:9*,*>&79*B"2),&2&2'*>7",)&2'J#"&2)*2=1C9%0D*$"=*B,2*%9,;*)(91*,77*&2)"*,2*,%%,$*,0

val numbers = for (w <- tokens) yield w.toDouble

"%D

val numbers = tokens.map(_.toDouble)

_5
Tip: 89191C9%h$"=*B,2*,7A,$0*=09*)(9 java.util.Scanner B7,00*)"*#%"B900
,*>&79*)(,)*B"2),&20*,*1&H)=%9*">*)9H)*,2;*2=1C9%0.

Y&2,77$D*2")9*)(,)*$"=*B,2*%9,;*2=1C9%0*>%"1*)(9 consoleR

print("How old are you? ")


// Console &0*&1#"%)9;*C$*;9>,=7)D*0"*$"=*;"2L)*299;*)"*K=,7&>$ print ,2; readInt
val age = readInt()
// Q%*=09 readDoubleD readLong

Caution: <(909*19)(";0*,00=19*)(,)*)(9*29H)*&2#=)*7&29*B"2),&20*,*0&2'79
2=1C9%D*A&)("=)*79,;&2'*"%*)%,&7&2'*A(&)90#,B9.*Q)(9%A&09D*,
NumberFormatException "BB=%0.

9.4. Reading from URLs and Other Sources


<(9 Source "CI9B)*(,0*19)(";0*)"*%9,;*>%"1*0"=%B90*")(9%*)(,2*>&790R

val source1 = Source.fromURL("http://horstmann.com", "UTF-8")


val source2 = Source.fromString("Hello, World!")
// 89,;0*>%"1*)(9*'&:92*0)%&2'h=09>=7*>"%*;9C=''&2'
val source3 = Source.stdin
// 89,;0*>%"1*0),2;,%;*&2#=)

Caution: b(92*$"=*%9,;*>%"1*,*e8TD*$"=*299;*)"*E2"A*)(9*B(,%,B)9%*09)*&2
,;:,2B9D*#9%(,#0*>%"1*,2*/<<S*(9,;9%.*-99 ())#RiiAAA.AX."%'iG2)9%2,)&"2,7i
QJB(,%09) >"%*1"%9*&2>"%1,)&"2.

9.5. Reading Binary Files


-B,7,*(,0*2"*#%":&0&"2*>"%*%9,;&2'*C&2,%$*>&790.*c"=L77*299;*)"*=09*)(9*?,:,*7&C%,%$.*/9%9*&0
("A*$"=*B,2*%9,;*,*>&79*&2)"*,*C$)9*,%%,$R

val file = new File(filename)


val in = new FileInputStream(file)
val bytes = new Array[Byte](file.length.toInt)

_3
in.read(bytes)
in.close()

9.6. Writing Text Files


-B,7,*(,0*2"*C=&7)J&2*0=##"%)*>"%*A%&)&2'*>&790.*<"*A%&)9*)9H)*>&790D*=09*,
java.io.PrintWriter.*Y"%*9H,1#79D

val out = new PrintWriter("numbers.txt")


for (i <- 1 to 100) out.println(i)
out.close()

677*A"%E0*,0*9H#9B)9;D*9HB9#)*>"%*)(9 printf 19)(";.*b(92*$"=*#,00*,*2=1C9%*)" printfD


)(9*B"1#&79%*A&77*B"1#7,&2*)(,)*$"=*299;*)"*B"2:9%)*&)*)"*,2 AnyRefR

out.printf("%6d %10.2f",
quantity.asInstanceOf[AnyRef], price.asInstanceOf[AnyRef]) // e'(

G20)9,;D*=09*)(9 format 19)(";*">*)(9 String B7,00R

out.print("%6d %10.2f".format(quantity, price))

Note: <(9 printf 19)(";*">*)(9 Console B7,00*;"90*2")*0=>>9%*>%"1*)(&0


#%"C791.*c"=*B,2*=09

printf("%6d %10.2f", quantity, price)

>"%*#%&2)&2'*,*1900,'9*)"*)(9*B"20"79.

9.7. Visiting Directories


<(9%9*,%9*B=%%92)7$*2"*n">>&B&,7o*-B,7,*B7,0090*>"%*:&0&)&2'*,77*>&790*&2*,*;&%9B)"%$D*"%*>"%
%9B=%0&:97$*)%,:9%0&2'*;&%9B)"%&90.*G2*)(&0*09B)&"2D*A9*;&0B=00*,*B"=#79*">*,7)9%2,)&:90.

Note: 6*#%&"%*:9%0&"2*">*-B,7,*(,; File ,2; Directory B7,0090.*c"=*B,2*0)&77


>&2;*)(91*&2*)(9 scala.tools.nsc.io #,BE,'9*&20&;9*0B,7,JB"1#&79%.I,%.

G)*&0*0&1#79*)"*A%&)9*,*>=2B)&"2*)(,)*#%";=B90*,2*&)9%,)"%*)(%"='(*,77*0=C;&%9B)"%&90*">*,
;&%9B)"%$R

_X
import java.io.File
def subdirs(dir: File): Iterator[File] = {
val children = dir.listFiles.filter(_.isDirectory)
children.toIterator ++ children.toIterator.flatMap(subdirs _)
}

b&)(*)(&0*>=2B)&"2D*$"=*B,2*:&0&)*,77*0=C;&%9B)"%&90*7&E9*)(&0R

for (d <- subdirs(dir)) process d

67)9%2,)&:97$D*&>*$"=*=09*?,:,*]D*$"=*B,2*,;,#)*)(9 walkFileTree 19)(";*">*)(9


java.nio.file.Files B7,00.*<(,)*B7,00*1,E90*=09*">*, FileVisitor &2)9%>,B9.*G2*-B,7,D*A9
'929%,77$*#%9>9%*)"*=09*>=2B)&"2*"CI9B)0D*2")*&2)9%>,B90D*>"%*0#9B&>$&2'*A"%E*M9:92*)("='(
&2*)(&0*B,09*)(9*&2)9%>,B9*,77"A0*1"%9*>&29J'%,&29;*B"2)%"7h099*)(9*?,:,;"B*>"%*;9),&70.N
<(9*>"77"A&2'*&1#7&B&)*B"2:9%0&"2*,;,#)0*,*>=2B)&"2*)"*)(9*&2)9%>,B9R

import java.nio.file._
implicit def makeFileVisitor(f: (Path) => Unit) = new SimpleFileVisitor[T] {
override def visitFile(p: Path, attrs: attribute.BasicFileAttributes) = {
f(p)
FileVisitResult.CONTINUE
}
}

<(92*$"=*B,2*#%&2)*,77*0=C;&%9B)"%&90*A&)(*)(9*B,77

Files.walkFileTree(dir.toPath, (f: Path) => println(f)


println(f))

Q>*B"=%09D*&>*$"=*;"2L)*I=0)*A,2)*)"*#%&2)*)(9*>&790D*$"=*B,2*0#9B&>$*")(9%*,B)&"20*&2*)(9
>=2B)&"2*)(,)*$"=*#,00*)"*)(9 walkFileTree 19)(";.

9.8. Serialization
G2*?,:,D*09%&,7&p,)&"2*&0*=09;*)"*)%,201&)*"CI9B)0*,B%"00*,*29)A"%E*"%*>"%*0("%)J)9%1
0)"%,'9.*MY"%*7"2'J)9%1*0)"%,'9D*09%&,7&p,)&"2*B,2*C9*,AEA,%;h&)*&0*)9;&"=0*)"*;9,7*A&)(
;&>>9%92)*"CI9B)*:9%0&"20*,0*B7,0090*9:"7:9*":9%*)&19.N

/9%9*&0*("A*$"=*;9B7,%9*,*09%&,7&p,C79*B7,00*&2*?,:,*,2;*-B,7,.

?,:,R

public class Person implements Serializable {


private static final long serialVersionUID = 42L;
...
}

_Z
-B,7,R

@serializable @SerialVersionUID(42L) class Person ...

Note: M5N*<(9 @serializable ,22"),)&"2*&0*7"A9%B,09.*M3N*c"=*B,2*"1&)*)(9


@SerialVersionUID ,22"),)&"2*&>*$"=*,%9*"E*A&)(*)(9*;9>,=7)*GU.

c"=*09%&,7&p9*,2;*;909%&,7&p9*"CI9B)0*&2*)(9*=0=,7*A,$R

val fred = new Person(...)


import java.io._
val out = new ObjectOutputStream(new FileOutputStream("/tmp/test.obj"))
out.writeObject(fred)
out.close()
val in = new ObjectInputStream(new FileInputStream("/tmp/test.obj"))
val savedFred = in.readObject().asInstanceOf[Person]

<(9*-B,7,*B"779B)&"20*,%9*09%&,7&p,C79D*0"*$"=*B,2*(,:9*)(91*,0*191C9%0*">*$"=%
09%&,7&p,C79*B7,0090R

@serializable class Person {


private val friends: ArrayBuffer[Person] // QEhArrayBuffer &0*09%&,7&p,C79
..
}

9.9. Regular Expressions


b(92*$"=*#%"B900*&2#=)D*$"=*">)92*A,2)*)"*=09*%9'=7,%*9H#%900&"20*)"*,2,7$p9*&).*<(9
scala.util.matching.Regex B7,00*1,E90*)(&0*0&1#79.*<"*B"20)%=B)*, Regex "CI9B)D*=09*)(9
r 19)(";*">*)(9 String B7,00R

val numPattern = "[0-9]+".r

G>*)(9*%9'=7,%*9H#%900&"2*B"2),&20*C,BE07,0(90*"%*K="),)&"2*1,%E0D*)(92*&)*&0*,*'"";*&;9,*)"
=09*)(9*n%,Ao*0)%&2'*0$2),H """...""".*Y"%*9H,1#79D

val wsnumwsPattern = """\s+[0-9]+\s+""".r


// 6*C&)*9,0&9%*)"*%9,;*)(,2 "\\s+[0-9]+\\s+".r

<(9 findAllIn 19)(";*%9)=%20*,2*&)9%,)"%*)(%"='(*,77*1,)B(90.*c"=*B,2*=09*&)*&2*, for


7""#R

_[
for (matchString <- numPattern.findAllIn("99 bottles, 98 bottles"))
process matchString

Q%*)=%2*)(9*&)9%,)"%*&2)"*,2*,%%,$R

val matches = numPattern.findAllIn("99 bottles, 98 bottles").toArray


// Array(99, 98)

<"*>&2;*)(9*>&%0)*1,)B(*,2$A(9%9*&2*,*0)%&2'D*=09 findFirstIn.*c"=*'9)*,2 Option[String].


M-99 )(9*nS,))9%2*P,)B(&2'*,2;*!,09*!7,0090o*B(,#)9% >"%*)(9 Option B7,00.N

val m1 = wsnumwsPattern.findFirstIn("99 bottles, 98 bottles")


// Some(" 98 ")

<"*B(9BE*A(9)(9%*)(9*C9'&22&2'*">*,*0)%&2'*1,)B(90D*=09 findPrefixOf.

numPattern.findPrefixOf("99 bottles, 98 bottles")


// Some(99)
wsnumwsPattern.findPrefixOf("99 bottles, 98 bottles")
// None

c"=*B,2*%9#7,B9*)(9*>&%0)*1,)B(D*"%*,77*1,)B(90.

numPattern.replaceFirstIn("99 bottles, 98 bottles", "XX")


// "XX bottles, 98 bottles"
numPattern.replaceAllIn("99 bottles, 98 bottles", "XX")
// "XX bottles, XX bottles"

9.10. Regular Expression Groups


t%"=#0*,%9*=09>=7*)"*'9)*0=C9H#%900&"20*">*%9'=7,%*9H#%900&"20.*6;;*#,%92)(9090*,%"=2;
)(9*0=C9H#%900&"20*)(,)*$"=*A,2)*)"*9H)%,B)D*>"%*9H,1#79

val numitemPattern = "(([0-9]+)) ([a-z]+)".r

<"*1,)B(*)(9*'%"=#0D*=09*)(9*%9'=7,%*9H#%900&"2*"CI9B)*,0*,2*n9H)%,B)"%o*M099 )(9*nS,))9%2
P,)B(&2'*,2;*!,09*!7,0090o*B(,#)9%ND*7&E9*)(&0R

val numitemPattern(num, item) = "99 bottles"


// 09)0 num )" "99"D item )" "bottles"

G>*$"=*A,2)*)"*9H)%,B)*'%"=#0*>%"1*1=7)&#79*1,)B(90D*=09*, for 0),)9192)D*7&E9*)(&0R

for (numitemPattern(num, item) <- numitemPattern.findAllIn("99 bottles, 98 bottles"))


process num and item

_\
9.11. Exercises
5. b%&)9*,*-B,7,*B";9*02&##9)*)(,)*%9:9%090*)(9*7&290*&2*,*>&79*M1,E&2'*)(9*7,0)*7&29
)(9*>&%0)*"29D*,2;*0"*"2N.
3. b%&)9*,*-B,7,*#%"'%,1*)(,)*%9,;0*,*>&79*A&)(*),C0D*%9#7,B90*9,B(*),C*A&)(*0#,B90*0"
)(,)*)(9%9*,%9*),C*0)"#0*9:9%$ n B"7=120D*,2;*A%&)90*)(9*%90=7)*)"*)(9*0,19*>&79.
X. b%&)9*,*-B,7,*B";9*02&##9)*)(,)*%9,;0*,*>&79*,2;*#%&2)0*,77*A"%;0*A&)(*1"%9*)(,2
53*B(,%,B)9%0*&2*)(9*>&79*)"*)(9*B"20"79.*WH)%,*B%9;&)*&>*$"=*B,2*;"*)(&0*&2*,*0&2'79
7&29.
Z. b%&)9*,*-B,7,*#%"'%,1*)(,)*%9,;0*,*)9H)*>&79*B"2),&2&2'*"27$*>7",)&2'J#"&2)
2=1C9%0.*S%&2)*)(9*0=1D*,:9%,'9D*1,H&1=1D*,2;*1&2&1=1*">*)(9*2=1C9%0*&2*)(9
>&79.
[. b%&)9*,*-B,7,*#%"'%,1*)(,)*A%&)90*)(9*#"A9%0*">*3*,2;*)(9&%*%9B&#%"B,70*)"*,*>&79D
A&)(*)(9*9H#"292)*%,2'&2'*>%"1*4*)"*34.*T&29*=#*)(9*B"7=120R

1 1
2 0.5
4 0.25
... ...

\. P,E9*,*%9'=7,%*9H#%900&"2*>"%*K=")9;*0)%&2'0 "like this, maybe with \" or \\"


&2*,*?,:,*"%*!@@*#%"'%,1.*b%&)9*,*-B,7,*#%"'%,1*)(,)*#%&2)0*"=)*,77*0=B(*0)%&2'0
&2*,*0"=%B9*>&79.
]. b%&)9*,*-B,7,*#%"'%,1*)(,)*%9,;0*,*)9H)*>&79*,2;*#%&2)0*,77*)"E920*&2*)(9*>&79*)(,)
,%9 not >7",)&2'J#"&2)*2=1C9%0.*e09*,*%9'=7,%*9H#%900&"2.
^. b%&)9*,*-B,7,*#%"'%,1*)(,)*#%&2)0*)(9 src ,))%&C=)90*">*,77 img ),'0*">*,*A9C*#,'9.
e09*%9'=7,%*9H#%900&"20*,2;*'%"=#0.
_. b%&)9*,*-B,7,*#%"'%,1*)(,)*B"=2)0*("A*1,2$*>&790*A&)(*9H)920&"2 .class ,%9*&2*,
'&:92*;&%9B)"%$*,2;*&)0*0=C;&%9B)"%&90.
54. WH#,2;*)(9*9H,1#79*A&)(*)(9*09%&,7&p,C79 Person B7,00*)(,)*0)"%90*,*B"779B)&"2*">
>%&92;0.*!"20)%=B)*,*>9A Person "CI9B)0D*1,E9*0"19*">*)(91*>%&92;0*">*,2")(9%D
,2;*)(92*0,:9*,2 Array[Person] )"*,*>&79.*89,;*)(9*,%%,$*C,BE*&2*,2;*:9%&>$*)(,)
)(9*>%&92;*%97,)&"20*,%9*&2),B).

_]

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy