371
8
스칼라 객체지향 프로그래밍
def x
:
Int
^
scala
>
trait Foo
{
|
val x
:
Int
|
def x
(
i
:
Int
):
Int
|
}
defined trait Foo
타입 이름은 유일해야 한다.
스칼라에는 자바와 달리 정적 멤버가 없다. 대신 여러 인스턴스에 걸친 멤버 (예를 들면 상수 )
저장하기 위해 객체를 사용할 있다.
객체와 클래스의 이름이 같고 같은 파일에 정의되어 있다면, 이 둘을 서로의 동반자
companion
말한다.
1
장에서 이미 이런 동반 객체와 클래스를 봤다. 케이스 클래스의 경우에는 컴파일러
자동으로 동반 객체를 만들어준다.
8.2
참조 타입과 값 타입
자바의 구문은
JVM
데이터를 구현하는 모습을 모델링한다. 먼저 특별한 기본 타입
primitive
type
short
,
int
,
long
,
float
,
double
,
boolean
,
char
,
byte
, 그리고 키워드인
void
가 있다.
이들은 나은 성능을 위해 스택이나
CPU
레지스터에 저장된다.
다른 모든 타입을 참조 타입이라고 부른다. 왜냐하면 이들의 인스턴스는 힙에 할당되며, 변수
실제로는 힙에 있는 인스턴스를 가리키는 역할을 하기 때문이다.
C
C
++와 달리 스택에
재하는 조적타입은 없다. 다만 향후 나올 자바의 버전에서는 이를 고려중이다. 따라서
타입이라는 이름은 이런 인스턴스를 기본값과 구분하기 위해 사용한다. 이런 타입의 인스턴
스는
new
키워드를 사용해서 만들 있다.
물론 스칼라도
JVM
규칙을 지켜야 한다. 하지만 스칼라는 타입참조 타입 간의 구별을
더욱 다듬었다.
모든 참조 타입은
AnyRef
의 서브타입이다.
AnyRef
는 스칼라 타입 계층구조의 최상위에 있는
Any
서브타입이다. 모든 값 타입은
AnyVal
서브타입이며,
AnyVal
또한
Any
서브타입이
372
2
기본기 다지기
다.
Any
의 서브타입은
AnyVal
AnyRef
뿐이다. 자바의 최상위 타입인
Object
(
http
://
bit
.
ly
/
1E8xJKR
)실제로는
Any
아니라
AnyRef
가장 가깝다.
참조 타입의 인스턴스는 여전히
new
키워드를 사용해서 만든다. 다른 인자가 없는 메서드와 마찬
가지로 생성자가 인자를 받지 않는 경우에는 괄호를 생략해도 된다 (일부 언어에서는 이를 기본
생성자
default
constructor
라고 부른다 ).
스칼라는 타입과
String
리터럴 값에 대해서는 자바의 관례를 따른다. 예를 들어
val
name
=
"
Programming
Scala
"
val
name
=
new
String
("
Programming
Scala
")
와 같다.
하지만 스칼라는 튜플을 위한 문법으로
(
1
,
2
,
3
)
을 지원하며, 이는
new
Tuple3
(
1
,
2
,
3
)
과 같
다. 우리는 스칼라가 제공하는 언어적 특징을 활용해서 컴파일러의 지원 없이도 전용 리터럴
구문을 만들어내는 것이 쉽다는 것을 이미 살펴봤다. 예를 들어
List
만들 때는
1
::
2
::
3
::
Nil
있고,
Map
만들 때는
Map
("
one
"
-
>
1
, "
two
"
-
>
2
)
있다.
참조 타입의 인스턴스를
apply
메서드가 있는 객체를 사용해서 만드는 일도 자주 있다. 그런
수를 팩토리
factory
라고 부른다 (이런 메서드는 내부적으로
new
다른 리터럴 구문을 사용한다 ).
케이스 클래스에는 그런 함수가 들어 있는 동반 객체가 자동으로 만들어지기 때문에, 케이스
래스의 인스턴스는 이런 방식을 사용해서 만드는 것이 보통이다.
Short
,
Int
,
Long
,
Float
,
Double
,
Boolean
,
Char
,
Byte
,
Unit
타입을 값 타입이라고 한다.
이들은 각각
JVM
기본 타입
short
,
int
,
long
,
float
,
double
,
boolean
,
char
,
byte
,
void
대응한다. 스칼라 객체 모델에서 모든 타입은
AnyVal
서브타입이다.
AnyVal
Any
서브타입 번째다.
입의 ‘인스턴스’는 힙에 만들어지지 않는다. 대신
JVM
기본값을 사용해서 스택이나 레지스
터에 저장된다. 이들의 인스턴스는
1
,
3
.
14
,
true
같이 항상 리터럴 값을 사용해서 만들어진
다.
Unit
리터럴 값은
( )
지만, 값을 직접 사용할 일은 거의 없다.
사실 이런 타입에는 공개된 생성자가 없다. 따라서
val
i
=
new
Int
(
1
)
컴파일되지 않는다.
Unit
의 리터럴 값이 ()인 이유는 뭔가?
Unit
실제로
()
라고 있는 원소가 없는
0
-
튜플처럼 작동한다. ‘유닛
unit
이라는 이름은
학의 곱셈에서 나온 것으로, 어떤 값을 유닛에 곱해도 원래의 값이 되는 값을 의미한다. 물론

Get 프로그래밍 스칼라: 실용적인 스칼라 활용법을 익히는 가장 확실한 실전 바이블 (2.11.x 버전 기반) now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.